OpenGL|OpenGL--shader入门

  • 理论基础
    着色器:opengl渲染管线分为固定管线和可编程管线,3.1版本后固定管线已经废除了。可编程管线主要是包括顶点着色器和片段着色器,而我们所讲的shader其实就是说我们可以自己控制这两个阶段的操作。本质其实和固定管线一样,还是走那套流程,只是现在更灵活些而已。
    下面是着色器编程的步骤示意图:
OpenGL|OpenGL--shader入门
文章图片
  • 实例代码
//源程序
#include "GLTools.h" #include "GLShaderManager.h"#ifdef __APPLE__ #include #else #define FREEGLUT_STATIC #include #endifGLuint v, f, f2,p; GLint loc; //文件读取(将本地shader文件读取为字符串形式加载) char *textFileRead(char *fn) { FILE *fp; char *content = NULL; int count=0; if (fn != NULL) { fp = fopen(fn,"rt"); if (fp != NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); if (count > 0) { content = (char *)malloc(sizeof(char) * (count+1)); count = fread(content,sizeof(char),count,fp); content[count] = '\0'; } fclose(fp); } } return content; }void changeSize(int w, int h) { if(h == 0) h = 1; float ratio = 1.0* w/h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, w, h); gluPerspective(45, ratio, 1, 1000); glMatrixMode(GL_MODELVIEW); }float time = 0; void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor4f(1.0, 0.0, 0.0, 1.0); //初始化了gl_Color值,可给着色器使用glLoadIdentity(); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glUniform1f(loc, time); //给uniform属性loc所指地址赋值 time+=0.01; glutSolidTeapot(1); //绘制茶壶glutSwapBuffers(); }//着色器:自己处理渲染管线中的顶点着色器和片段着色器阶段 void setShaders() { char *vs = NULL, *fs = NULL, *fs2 = NULL; /*第一阶段*/ //创建着色器对象(类似C中的函数,可以复用) v = glCreateShader(GL_VERTEX_SHADER); //顶点着色器 f = glCreateShader(GL_FRAGMENT_SHADER); //片段着色器 f2 = glCreateShader(GL_FRAGMENT_SHADER); vs = textFileRead("/Users/app05/Desktop/opengl/opengl/minimal.vert"); fs = textFileRead("/Users/app05/Desktop/opengl/opengl/minimal.frag"); const char *vv = vs; const char *ff = fs; //将着色器代码添加到创建的着色器容器中 glShaderSource(v, 1, &vv, NULL); glShaderSource(f, 1, &ff, NULL); free(vs); free(fs); //编译着色器源代码 glCompileShader(v); glCompileShader(f); /*第二阶段*/ p = glCreateProgram(); //创建着色器程序 glAttachShader(p, v); //将着色器对象关联到这个着色器程序 glAttachShader(p, f); glLinkProgram(p); //链接着色器程序glUseProgram(p); //使用着色器//得到着色器程序中unifrom属性的time变量地址,以便外面修改它 loc = glGetUniformLocation(p,"time"); }int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(320,320); glutCreateWindow("OpenGL Shader 入门"); glutDisplayFunc(renderScene); glutIdleFunc(renderScene); glutReshapeFunc(changeSize); glEnable(GL_DEPTH_TEST); glClearColor(1.0,1.0,1.0,1.0); //glEnable(GL_CULL_FACE); glewInit(); setShaders(); glutMainLoop(); return 0; }

//顶点着色器程序(minimal.vert)
uniform float time; //uniform属性的变量值可以由opengl程序传进来void main() { //顶点颜色 gl_FrontColor = gl_Color; //模型矩阵变换,将3D坐标投影到2D屏幕坐标 //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; //gl_Position = ftransform(); //实例:顶点z值正旋变化 vec4 v = vec4(gl_Vertex); v.z = sin(5.0 * v.x + time) * 0.5; gl_Position = gl_ModelViewProjectionMatrix * v; }

//片段着色器程序(minimal.frag)
void main() { /*gl_FragColor:是设置片段的颜色,gl_Color:是外部glColor()默认初始化的uniform值*/ gl_FragColor = gl_Color; }

OpenGL|OpenGL--shader入门
文章图片

【OpenGL|OpenGL--shader入门】OpenGL|OpenGL--shader入门
文章图片

    推荐阅读