前言
回顾OpenGL绘制简单模型:3D立方体。(今天又学到了一丢丢markdown用法,居然可以用html进行图片排版)
缓冲区和顶点属性
要想绘制一个对象,需要将该对象的顶点数据发送给顶点着色器。通常要把顶点数据在C++端放入一个缓冲区(所谓的VBO),并将该缓冲区和着色器中声明的顶点属性相关联。例如:以绘制一个三维空间立方体传递数据为例。
GLuint vao,vbo;
glGenVertexArrays(1,&vao); //管理顶点缓冲对象,必须有
glBindVertexArray(vao);
glGenBuffers(1,&vbo); //创建缓冲区对象
glBindBuffers(GL_ARRAY_BUFFER,vbo); //将该缓冲区标记为“活跃”
glBufferData(GL_ARRAY_BUFFER,sizeof(data),data,GL_STATIC_DRAW); //将数据复制到缓冲区
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0); //将该缓冲区和顶点属性相关联
glEnableVertexAttribArray(0); //激活该顶点属性:layout(location) in vec3 vPos;
glDrawArrays(GL_TRIANGLES,0,sizeof(data)); //绘制对象
调用glDrawArrays函数后,数据流入管线,进行后续处理。
统一变量uniform
对象的顶点数据(坐标、颜色等)使用缓冲区发送到着色器的对应属性,而使得场景呈现出三维效果所构建的变换矩阵通常从C++/OpenGL应用程序发送给着色器的统一变量。
//shader code
uniform mat4 mv_matrix;
//C++/OpenGL
int mvLoc=glGetUniformLocation(renderingProgram,"mv_matrix");
glUniformMatrix4fv(mvLoc,1,GL_FALSE,value_ptr(mvMat));
其中,renderingProgram是着色器程序的引用ID,mvMat是自定义的模型-视图矩阵,mvLoc是统一变量在着色器程序中的位置。
统一变量类似于一个常量,在每次顶点着色器调用中都保持不变。
顶点属性插值
事实上,C++/OpenGL应用程序只给OpenGL管线发送了36个顶点坐标(包含重复顶点),这些顶点定义了构成立方体的图元(三角形),经过顶点着色器处理之后,沿着管线流动,在光栅化阶段,会对这些顶点属性进行线性插值,从而生成满足屏幕输出的像素位置。指定以GL_TRIANGLES进行绘制,则光栅化是逐三角形进行的:首先沿着连接顶点的线进行插值,插值精度和像素显示密度相关;其次沿着连接边缘像素的水平线插值填充三角形内部空间的像素。
练习截图
|
|
|
|
总之,C++/OpenGL应用程序将数据存储到缓冲区中,然后发送给OpenGL渲染管线,最终输出到屏幕上。在这个过程中,将构建好的变换矩阵应用到模型上,从而使得二维屏幕中的对象展现出三维效果。