1 管线(pipeline)简介
上图中一个顶点(Vertex )是一组属性,包括位置,颜色,纹理坐标等。
1.1顶点转换模块(Vertex Transformation)
在此模块实现功能:
顶点位置转换
为每个顶点计算光照
纹理坐标的生成与转换
1.2图元安装和光栅化处理模块(Primitive Assembly and Rasterization)
此阶段的输入是转换后的数据和连接信息。连接信息告诉管线顶点是如何连接为图元的。光栅化决定了片断和像素位置。片断是一组用于更新桢缓存中像素的数据。片断包括颜色,纹理坐标等。
在此模块输出包括:
桢缓存中片断的位置
在顶点阶段计算的属性的每一片断的插值
1.3 片断纹理和颜色模块(Fragment Texturing and Coloring)
此模块的输入是插值处理后的片断。在这个阶段一个颜色元素可以绑定到一个纹理元素,雾化处理也在这个阶段。通常这个阶段的输出值是一个颜色值和一个片断的深度。
1.4光栅操作模块(Raster Operations)
此阶段的输入:
像素位置
片断深度和颜色值
在这个阶段对片断进行一系列的测试,包括:
剪取测试
Alpha测试
模版测试
深度测试
如果测试成功,则根据当前的混合模式用片断信息来更新像素值。
1.5总结:
上面的过程可以用下面的图形象进行概括:
2 顶点处理器
顶点处理器用来运行顶点着色程序。顶点着色程序的输入是顶点数据,即颜色,位置等。
下面这段代码为每个顶点发送给顶点处理器一个颜色和一个顶点的位置。
glBegin(...);
glColor3f(0.2,0.4,0.6);
glVertex3f(-1.0,1.0,2.0);
glColor3f(0.2,0.4,0.8);
glVertex3f(1.0,-1.0,2.0);
glEnd();
在一个顶点着色程序中,你可以写代码实现功能如:
顶点位置转换
规范化处理
纹理坐标的生成和转化
为顶点计算光照
颜色计算
顶点着色程序至少要写入一个变量,如gl_Position,用于矩阵转换。
3 片断处理器
片断处理器负责下面的操作:
为每个像素计算颜色,纹理坐标
纹理应用
雾化计算
若想为每个像素进行光照则进行规范化
此阶段的输入是先前阶段进行的差值,包括顶点的颜色,位置等。像顶点处理器一样,我们写得片断着色程序将代替所有固定的函数。所以我们必须对实际应用的所有要求全部在着色程序中编码实现。片断处理器只能对一个片断进行处理,没有此片断相邻片断的信息。
重要的一点是一个片断着色器不能改变像素坐标。这与顶点着色器是不同的,在顶点着色器中,模型和映射矩阵用于顶点变换。片断着色程序可以访问屏幕上像素的位置,但不能改变它。
片断着色器有两个输出:
丢弃片断,什么也不输出
要么计算最终的片断颜色gl_FragColor 要么计算多重目标着色的 gl_FragData
注意片断着色程序不能访问桢缓存。这意味着混合操作只能发生在片断着色器运行后。
4 GLSL安装
在这部分,假设你已经有了一对着色程序,顶点着色程序和片段着色程序,你想把他们应用到OPENGL程序中。
每个着色程序就像C模块一样,它必须被单独编译,然后链接到一个程序中。
在这里我们使用两种方法来进行说明:ARB扩展和opengl2.0程序。GLEW使得扩展使用起来非常方便。如果要使用扩展部分,而你不支持opengl2.0,那么下面两个扩展要用到:
GL_ARB_fragment_shader
GL_ARB_vertex_shader
下面代码是一个简单的例子检查扩展是否可用:
#include
#include
void main(int argc, char **argv)
{
glutInit(&argc, argv);
...
glewInit();
if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
printf("Ready for GLSL/n");
else {
printf("Not totally ready :( /n");
exit(1);
}
setShaders();
glutMainLoop();
}
下面代码是一个简单的例子检查opengl2.0是否可用:
#include
#include
void main(int argc, char **argv)
{
glutInit(&argc, argv);
...
glewInit();
if (glewIsSupported("GL_VERSION_2_0"))
printf("Ready for OpenGL 2.0/n");
else
{
printf("OpenGL 2.0 not supported/n");
exit(1);
}
setShaders();
glutMainLoop();
}
下面图片是opengl程序和着色程序的关系:
5 建立一个着色程序(Creating a shader)
建立着色程序共需要三步:
第一种方法: opengl2.0
GLuint glCreateShader(GLenum shaderType);
shaderType - GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);
shader - the handler to the shader.
numOfStrings - the number of strings in the array.
strings - the array of strings.
lenOfStrings - an array with the length of each string, or NULL, meaning that the strings are NULL terminated
void glCompileShader(GLuint shader);
Parameters:
shader - the handler to the shader.
第二种方法:ARB扩展
GLhandleARB glCreateShaderObjectARB(GLenum shaderType);
Parameter:
shaderType - GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB.
void glShaderSourceARB(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings);
Parameters:
shader - the handler to the shader.
numOfStrings - the number of strings in the array.
strings - the array of strings.
lenOfStrings - an array with the length of each string, or NULL, meaning that the strings are NULL terminated.
void glCompileShaderARB(GLhandleARB shader);
Parameters:
shader - the handler to the shader.
6 编写一个程序
下图是编写一个程序的步骤:
第一种方法: opengl2.0
GLuint glCreateProgram(void);
void glAttachShader(GLuint program, GLuint shader);
Parameters:
program - the handler to the program.
shader - the handler to the shader you want to attach.
void glLinkProgram(GLuint program);
Parameters:
program - the handler to the program.
void glUseProgram(GLuint prog);
Parameters:
prog - the handler to the program you want to use, or zero to return to fixed functionality
示例:
void setShaders() {
char *vs,*fs;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("toon.vert");
fs = textFileRead("toon.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);
}
第二种方法:ARB扩展
GLhandleARB glCreateProgramObjectARB(void);
void glAttachObjectARB(GLhandleARB program, GLhandleARB shader);
Parameters:
program - the handler to the program.
shader - the handler to the shader you want to attach.
void glLinkProgramARB(GLhandleARB program);
Parameters:
program - the handler to the program.
void glUseProgramObjectARB(GLhandleARB prog);
Parameters:
prog - the handler to the program you want to use, or zero to return to fixed functionality
void setShaders()
{
char *vs,*fs;
v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
vs = textFileRead("toon.vert");
fs = textFileRead("toon.frag");
const char * vv = vs;
const char * ff = fs;
glShaderSourceARB(v, 1, &vv,NULL);
glShaderSourceARB(f, 1, &ff,NULL);
free(vs);free(fs);
glCompileShaderARB(v);
glCompileShaderARB(f);
p = glCreateProgramObjectARB();
glAttachObjectARB(p,v);
glAttachObjectARB(p,f);
glLinkProgramARB(p);
glUseProgramObjectARB(p);