• Deferred Shading


    本篇博客说一下学习延迟渲染中遇到的问题。


     学习延迟渲染的过程中主要给了我疑惑的是深度测试的问题,在Learn OpenGL的相关代码中,我并没有看到G-buffer有根据片段深度对片段进行消隐或者显示。这是我一直疑惑的地方。如果在fragment shader中不经过深度测试就将片段输出至G-buffer相对应的纹理附件上的话,我认为会出现一些问题(因为纹理附件是2D的,在纹理附件上的一点不可能产生2个RGB值,这就说明我们需要在fragment shader中进行深度测试)。

    言归正传,先来说说延迟渲染的概念。

    在讲解延迟渲染之前,我们首先要知道到目前为止用的渲染都是正向渲染(forward rendering或者forward shading),即对于一个有多个物体以及一个光源的场景,我们会一个物体一个物体(无序)地去渲染(计算光照)。对于一个光源来说这可能没什么问题(事实上之前的学习中用到的光源不超过10个),然而如果是多个光源的话,问题就大了:由于多个光源下要进行的计算量很大(要逐个片段计算光照,然后还得将各个光源的光照效果结合起来),如果我们还是一个物体一个物体地去渲染,那么就有可能因为片段遮挡(片段深度测试)的问题导致一些计算白白浪费掉;并且因为计算量大,帧率也会下降。

    于是乎就出现了延迟渲染(deferred shading),延迟渲染改掉了“先光照计算,再深度测试”的顺序,变成了“先深度测试,再进行光照计算”。伪码如下:

    Pass 1 {
        //第一个Pass不进行光照计算,仅存储光照计算所需信息到G缓冲中
        
        for (each primitive in this model) {
             for (each fragment covered by this primitive) {
                 if (failed in depth test) {
                     discard;//若没有通过深度测试,则该片元不可见
                 }
                 else {
                     //若该片元可见,则进行光照计算,则将相关信息存储到G缓冲中
                     writeBuffer(materialInfo, pos, normal, lightDir, viewDir);
                 }
             }
        }
    }
    Pass 2 {
    	//利用G缓冲中的信息进行真正的光照计算
    	
    	for (each pixel in the screen) {
    		if (the pixel is valid) {
            	//若该像素有效,则读取其G缓冲中的信息
            	readBuffer(pixel, materialInfo, pos, normal, lightDir, viewDir);
            	
            	//根据读取到的信息进行光照计算
            	float4 color = Shading(materialInfo, pos, normal, lightDir, viewDir);
            	//更新帧缓冲
            	writeFrameBuffer(pixel, color);
                    }
            }
    }

    这样子就能避免不必要的光照计算了。值得一提的是,当光源数目不多的时候,有可能正向渲染的开销要小于延迟渲染,并且延迟渲染不能使用MSAA和Blending

    延迟渲染的优点是可以在大量渲染光照的时候不消耗大量的内存,然而并不能认为这它可以无限制地渲染光照,更多情况下,(由于光线衰弱等原因)我们会计算光照的“作用半径”,也就是光能到达的范围,称之为光体积(light volumes),来从根本上节省光照计算的开销。

    具体如何操作这里就不写了,详情参照Learn OpenGL的相关章节即可。

    参考资料:

    [1]【《Real-Time Rendering 3rd》 提炼总结】(七) 第七章续 · 延迟渲染(Deferred Rendering)的前生今世

    [2] Deferred Rendering基础篇(一)

    以上

    原来人类的悲欢并不相通, 我只觉得他们吵闹。
  • 相关阅读:
    js 简单getByClass得封装
    微信红包的随机算法
    js 淘宝评分
    HDU 1023 Train Problem II( 大数卡特兰 )
    HDU 1576 A/B( 逆元水 )
    HDU 5533 Dancing Stars on Me( 有趣的计算几何 )
    POJ 1664 放苹果( 递推关系 )
    HDU 2095 find your present (2)( 位运算 )
    POJ 3517 And Then There Was One( 约瑟夫环模板 )
    POJ 1988 Cube Stacking( 带权并查集 )*
  • 原文地址:https://www.cnblogs.com/zhlabcd/p/11972694.html
Copyright © 2020-2023  润新知