正向渲染和延迟渲染
目前使用光照对场景进行渲染的方案都是基于正向渲染和延迟渲染的。
- 正向渲染(Forward Rendering)
正向渲染是指每执行一次渲染命令,就会对需要渲染的物体进行光照着色,那么当场景中有m个光源,n个需要渲染的物体,那么时间复杂度就是O(m*n)。多光源时不适合使用正向渲染。 - 延迟渲染(Deferred Rendering)
为了解决正向渲染的不足之处,把渲染物体的光照着色分开计算,即先把所有是物体都渲染完成保存至GBuffer中(一个缓存空间),然后对GBuffer中的内容进行光照着色,这样只需要执行O(n)+O(m)次,因此适合处理多光源。
延迟渲染的不足之处
- 显而易见,延迟渲染需要一个临时缓冲区GBuffer,这样就会多浪费空间
- 又因为GBuffer的存在,延迟渲染不适合MSAA抗锯齿算法,因为多重采样需要使用更大的缓存空间,是GBuffer的四倍或更高,这样一般显卡都没办法提供那么大的空间,因此不适应MSAA。
- 延迟渲染无法处理混合,即渲染透明物体,因为G缓冲中所有的数据都是从一个单独的片段中来的,而混合需要对多个片段的组合进行操作。
- 延迟渲染只能对所有模型做统一的光照着色,使用一套光照算法。
延迟渲染的步骤
延迟着色法基于我们延迟(Defer)或推迟(Postpone)大部分计算量非常大的渲染(像是光照)到后期进行处理的想法。它包含两个处理阶段(Pass):在第一个几何处理阶段(Geometry Pass)中,我们先渲染场景一次,之后获取对象的各种几何信息,并储存在一系列叫做G缓冲(G-buffer)的纹理中;想想位置向量(Position Vector)、颜色向量(Color Vector)、法向量(Normal Vector)和/或镜面值(Specular Value)。场景中这些储存在G缓冲中的几何信息将会在之后用来做(更复杂的)光照计算。下面是一帧中G缓冲的内容:

我们会在第二个光照处理阶段(Lighting Pass)中使用G缓冲内的纹理数据。在光照处理阶段中,我们渲染一个屏幕大小的方形,并使用G缓冲中的几何数据对每一个片段计算场景的光照;在每个像素中我们都会对G缓冲进行迭代。我们对于渲染过程进行解耦,将它高级的片段处理挪到后期进行,而不是直接将每个对象从顶点着色器带到片段着色器。光照计算过程还是和我们以前一样,但是现在我们需要从对应的G缓冲而不是顶点着色器(和一些uniform变量)那里获取输入变量了。
延迟渲染伪代码:
while(...) // 游戏循环
{
// 1. 几何处理阶段:渲染所有的几何/颜色数据到G缓冲
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gBufferShader.Use();
for(Object obj : Objects)
{
ConfigureShaderTransformsAndUniforms();
obj.Draw();
}
// 2. 光照处理阶段:使用G缓冲计算场景的光照
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
lightingPassShader.Use();
BindAllGBufferTextures();
SetLightingUniforms();
RenderQuad();
}
创建GBuffer,保存至贴图中:
GLuint gBuffer;
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
GLuint gPosition, gNormal, gColorSpec;
// - 位置颜色缓冲
glGenTextures(1,

最低0.47元/天 解锁文章
266

被折叠的 条评论
为什么被折叠?



