渲染
把三维场景绘制成二维图片的模型成像过程。
在OpenGL中,任何事物都是在3D空间中,而屏幕和窗口却是2D像素数组。OpenGL的图形渲染管线,通过将3D坐标转成适应屏幕的2D像素来统一进行管理。其主要分为两部分:第一部分把3D坐标转换成2D坐标,第二部分是把2D坐标转变成实际的有颜色的像素。
图形渲染管线可以理解为一条流水线,数据从流水线上各个工位流过进行加工,每个工位都只执行特定的工作,它不关心下一步和上一步做什么,只要接受到上一部传入的数据,处理完后传下去而已。显卡上有成千上万的小处理核心,他们在GPU上都有自己的工位,以便并行快速的处理数据。这些流水线上的工作,可以称为着色器,不同阶段的流水线运行不同的着色器。
可以把渲染管线(流水线)抽象为以下几个阶段。蓝色部分是暴露给我们可以自定义着色器的部分(自己安排)。
CPU将顶点数据传给GPU,进入图形渲染管线的第一部分——顶点着色器,它接收单独的顶点作为输入,同时允许对顶点属性记性一些基本处理。
图元装配会把顶点着色器的输出的所有顶点作为输入,根据渲染类型绘制出图元的形状。(图元是绘制模型的基本组成,包括:点、线、三角形、四边形、多边形)。
图元装配阶段的输出(一系列顶点的集合)会给到几何着色器。几何着色器可以通过产生新顶点构造出新的或其他的图元来生成其他形状。
几何着色器的输出会被传入光栅化阶段,在这里会把图元映射为最终屏幕上对应的像素,生成供片段做色漆使用的片段(Fragment)。并裁切(Clipping)超出视图以外的所有像素。(片段(Fragment)是OpenGL渲染一个像素所需的所有数据)
片段着色器的主要目的是计算一个像素的最终颜色,包含3D场景的数据,比如光照、阴影等,用来计算最终像素的颜色。
最后一个阶段Apha测试和混合(Blending)阶段,检测片段对应的深度,来判断在其他物体前面还是后面,是否需要丢弃。检查alpha值,对物体进行混合。
在大多数情况下,我们只要配置顶点和片段藕色器就行了,几何着色器是可选的,通常使用它默认的着色器就行了。
顶点输入
OpenGL只处理在三个坐标轴上-1.0到1.0范围内的值,叫做“标准化设备坐标”,范围内的值才会现实在屏幕上。所以第一步就是将顶点数据进行标准化到-1.0到1.0之间。(OpenGL使用的是左手坐标系,Z轴的正方向是垂直屏幕向内的)
标准化设备坐标数据会通过CPU发送到显卡内存中(一次发送大量数据,过程较慢),顶点着色器可以快速访问这部分内存得到顶点数据。OpenGL通过顶点缓冲对象(Vertex Buffer Objects,VBO)管理这个内存,这是一个OpenGL对象。
unsigned int VBO;
glGenBuffers(1,&VB0); //使用此函数和一个缓冲ID生成一个VBO对象
//将新创建的缓冲绑定到GL_ARRAY_BUFFER目标上
glBindBuffer(GL_ARRAY_BUFFER,VBO);
//把之前定义的顶点数据vertices复制到缓冲内存中,GL_STATIC_DRAW表示数据不会或几乎不会改变
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
顶点着色器(Vertex Shader)–处理顶点数据
顶点着色器是流水线上我们遇到的第一个可编程着色器,而且需要我们至少设置一个顶点着色器。
//一个简单的GLSL着色器代码
#version 330 core //对应OpenGL3.3,GLSL420对应OpenGL4.2。且使用核心模式
layout (localization = 0) in vec3 aPos; //in关键字声明aPos是输入的顶点属性。layout (location = 0)设定了变量的位置值从0开始
void main()
{
gl_Posiion = vec4(aPos.x, aPos.y, aPos.z, 1.0); //gl_Position是预定义变量,vec4类型。是该顶点着色器的输出
}
如何创建编译一个着色器
const char *vertexShaderSource = "#version 330 core\n"
"layout (localization = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Posiion = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0"; //硬编码,以便在运行时动态编译
unsigned int vertexShader; //声明一个着色器对象,以ID来引用
vertexShader = glCreateShader(GL_VERTEX_SHADER); //创建一个着色器,着色器类型:GL_VERTEX_SHADER-顶点着色器。
//将(着色器对象,源码字符串数量,源码,NUll)作为参数,绑定源码和着色器对象
glShaderSource(vertexShader, 1,