1、概念
图形渲染管线:简而言之就是接受一组3D坐标,然后把他们转变为屏幕上有色的2D像素输出。
着色器:运行在GPU每个处理核心上的小程序,opengl就是一种着色器的编程语言
图形渲染管线的各个模块;
(坐标输入顶点数据->顶点着色器->图元装配->几何着色器->光栅化阶段->片段着色器->测试&混合)
对应到编程阶段我们只需要编写顶点着色器和片段着色器即可,其他都有默认程序。
顶点着色器相关:处理顶点数据并告知如何解析,并指定如何发送给显卡,其中还有其他几个概念
顶点缓存对象:VB0它会在显存中存储大量顶点数据并按批量发送给显卡。
链接顶点属性:用于传输给顶点着色器的顶点属性以任何形式输入,给其很大的灵活性
顶点数组对象:VAO 随后的顶点属性调用会存储在这个VAO中,便于属性绑定。绘制物体的时候我们可以先绑定VA0就可以绘制了,如果要取消就可以取消VAO的绑定
顶点着色器程序:使用opengl的语法编写的着色器,在程序中会去编译链接的
向量:GLSL中的一个向量数据类信息,最多包含4个分量。
片段着色器相关:计算像素做最后的输出。
2、编写步骤
2.1、顶点着色器编写加载编译
gl_Position 被赋值之后,将通过渲染管线传给后面的阶段,在图元装配的时候,将顶点连接起来。在光栅化图元的时候,将两个顶点之间的线段分解成大量的小片段,varying数据在这个过程中计算生成,记录在每个片段中,之后传递给片段着色器。
//编写顶点着色器代码
char vShaderStr[] =
"#version 300 es \n"
"layout(location = 0) in vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
//程序中加载编译链接顶点着色器
GLuint vertexShaderHandle = 0;
vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
glShaderSource(vertexShaderHandle, 1, reinterpret_cast<const GLchar *const *>(&vShaderStr), NULL);//绑定源码
glCompileShader(vertexShaderHandle);//编译
GLint compiled = 0;
glGetShaderiv(vertexShaderHandle, GL_COMPILE_STATUS, &compiled);//检查编译是否成功
if (!compiled)
{
}
2.2、片段着色器编写加载编译
//编写顶点着色器代码
char fShaderStr[] =
"#version 300 es \n"
"precision mediump float; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"
"} \n";
//程序中加载编译链接顶点着色器
GLuint fragShaderHandle = 0;
fragShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);//创建顶点着色器
glShaderSource(fragShaderHandle, 1, reinterpret_cast<const GLchar *const *>(&fShaderStr), NULL);//绑定源码
glCompileShader(fragShaderHandle);//编译
GLint compiled = 0;
glGetShaderiv(fragShaderHandle, GL_COMPILE_STATUS, &compiled);//检查编译是否成功
if (!compiled)
{
}
2.3、创建程序添加链接着色器
GLuint program = 0;
program = glCreateProgram();//创建程序
if (program)
{
glAttachShader(program, vertexShaderHandle);//添加顶点着色器
glAttachShader(program, fragShaderHandle);//添加片段着色器
glLinkProgram(program);//链接
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);//检查链接是否成功
if (linkStatus != GL_TRUE)
{
}
//成功之后可以解绑着色器并删除调,使用完则删除内存
glDetachShader(program, vertexShaderHandle);
glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
glDetachShader(program, fragShaderHandle);
glDeleteShader(fragShaderHandle);
fragShaderHandle = 0;
}
2.4、传入顶点画图形
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);//创建一个顶点数组 与顶点属性相绑定
glGenBuffers(1, &VBO);//创建顶点缓冲对象
glBindVertexArray(VAO);//绑定顶点数组
glBindBuffer(GL_ARRAY_BUFFER, VBO);//将GL_ARRAY_BUFFER类型的缓存与VBO绑定
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//之前定义的顶点数据复制到缓冲的内存
/*
0;指定我们要配置的顶点属性 就是顶点着色器里面location那个
*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void *)0);
glEnableVertexAttribArray(0);//以顶点属性位置值0作为参数,启用顶点属性
glBindBuffer(GL_ARRAY_BUFFER, 0);//VBO 已经与顶点属性数组VAO进行绑定了 那么GL_ARRAY_BUFFER就可以解除绑定
glBindVertexArray(0);//您可以在之后解除绑定VAO,这样其他VAO调用就不会意外地修改这个VAO
描绘
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //设置状态函数
glClear(GL_COLOR_BUFFER_BIT);//使用状态函数
glUseProgram(shaderProgram);//使用着色器程序
glBindVertexArray(VAO);//绑定顶点数组 就是使用顶点属性
/*
我们希望绘制的是一个三角形,这里传递GL_TRIANGLES给它。
第二个参数指定了顶点数组的起始索引,我们这里填0。
最后一个参数指定我们打算绘制多少个顶点,这里是3
(我们只从我们的数据中渲染一个三角形,它只有3个顶点长)
*/
glDrawArrays(GL_TRIANGLES, 0, 3);
释放内存
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);