6.OpenGL--shader入门

来源:互联网 发布:河南省大数据产业园 编辑:程序博客网 时间:2024/06/06 20:29
  • 理论基础 
    着色器:opengl渲染管线分为固定管线和可编程管线,3.1版本后固定管线已经废除了。可编程管线主要是包括顶点着色器和片段着色器,而我们所讲的shader其实就是说我们可以自己控制这两个阶段的操作。本质其实和固定管线一样,还是走那套流程,只是现在更灵活些而已。 
    下面是着色器编程的步骤示意图:

这里写图片描述

  • 实例代码

//源程序

#include "GLTools.h"#include "GLShaderManager.h"#ifdef __APPLE__#include <glut/glut.h>#else#define FREEGLUT_STATIC#include <GL/glut.h>#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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141

//顶点着色器程序(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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

//片段着色器程序(minimal.frag)

void main(){    /*gl_FragColor:是设置片段的颜色,gl_Color:是外部glColor()默认初始化的uniform值*/    gl_FragColor = gl_Color;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

这里写图片描述

0 0