图形渲染管线可以被划分为两个主要部分:
第一部分把你的3D坐标转换为2D坐标,第二部分是把2D坐标转变为实际的有颜色的像素。
着色器(Shader):
图形渲染管线接受一组3D坐标,然后把它们转变为你屏幕上的有色2D像素输出。图形渲染管线可以被划分为几个阶段,每个阶段将会把前一个阶段的输出作为输入。所有这些阶段都是高度专门化的(它们都有一个特定的函数),并且很容易并行执行。正是由于它们具有并行执行的特性,当今大多数显卡都有成千上万的小处理核心,它们在GPU上为每一个(渲染管线)阶段运行各自的小程序,从而在图形渲染管线中快速处理你的数据。
图形渲染管线的每个阶段的抽象展示:
(注意蓝色部分代表的是我们可以注入自定义的着色器的部分)
图形渲染管线包含很多部分,每个部分都将在转换顶点数据到最终像素这一过程中处理各自特定的阶段。
伪代码理解:
/**
* 关于对渲染管线的理解
*/
int main()
{
//顶点数据
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
VertexShader(vertices);
return 0;
}
//1. 顶点着色
void VertexShader(float* vertices)
{
/**
*把一个单独的顶点作为输入。顶点着色器主要的目的是把3D坐标转为另一种3D坐标,同时顶点着色器允许我们对顶点属性进行一些基本处理。
*/
ShapeAssembly();
}
//2. 图元装配
void ShapeAssembly()
{
/**
*将顶点着色器输出的所有顶点作为输入,并把所有的点装配成指定图元的形状
*/
GeometryShader();
}
//3. 几何着色器
void GeometryShader()
{
/**
*把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其他形状
*/
Rasterization();
}
//4. 光栅化
void Rasterization()
{
/**
*这里它会把图元映射为最终屏幕上相应的像素,生成供片段着色器(Fragment Shader)使用的片段(Fragment)。
*在片段着色器运行之前会执行裁切(Clipping)。
*裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。
*/
FragmentShader();
}
//5. 片元着色器
void FragmentShader()
{
/**
*这里主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。
*通常,片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。
*/
TestAndBlending();
}
//6. 测试与混合
void TestAndBlending()
{
/**
*Alpha测试和混合(Blending)阶段
*这个阶段检测片段的对应的深度(和模板(Stencil))值,用它们来判断这个像素是其它物体的前面还是后面,决定是否应该丢弃。
*这个阶段也会检查alpha值(alpha值定义了一个物体的透明度)并对物体进行混合(Blend)。
*所以,即使在片段着色器中计算出来了一个像素输出的颜色,在渲染多个三角形的时候最后的像素颜色也可能完全不同。
*/
}
扫描二维码关注公众号,回复:
16713486 查看本文章