# 延迟渲染与前向渲染

2020/05/22 08:35

The basic idea behind deferred shading is to perform all visibility testing before performing any lighting computations.

-RealTimeRendering 3rd

General goal of the approaches is to reduce the amount

## 前向渲染的问题：

Today most GPUs support a hardware feature called early depth testing. Early depth testing allows the depth test to run before the fragment shader runs. Wherever it is clear a fragment is never going to be visible (it is behind other objects) we can prematurely discard the fragment.

Fragment shaders are usually quite expensive so wherever we can avoid running them we should. A restriction on the fragment shader for early depth testing is that you shouldn’t write to the fragment’s depth value. If a fragment shader would write to its depth value, early depth testing is impossible; OpenGL won’t be able to figure out the depth value beforehand.

)

RT0, ARGB32 format: Diffuse color (RGB), occlusion (A).

RT1, ARGB32 format: Specular color (RGB), roughness (A).

RT2, ARGB2101010 format: World space normal (RGB), unused (A).

RT3, ARGB2101010 (non-HDR) or ARGBHalf (HDR) format: Emission + lighting + lightmaps

+ reflection probes

buffer.

Depth+Stencil buffer

So the default g-buffer layout is 160 bits/pixel (non-HDR) or 192 bits/pixel (HDR).

RT4, ARGB32 format: Light occlusion values (RGBA).

## 延迟渲染的问题：

1.需要显卡支持SM3.0的API和MRT等

2.占用更多显存

3.增加带宽

4.对半透明物体依然是前向渲染

5.不能使用MSAA(硬件AA)

## 关于Light pass

Hidden/Internal-DeferredShadinghalf4 CalculateLight (unity_v2f_deferred i){float3 wpos;float2 uv;float atten, fadeDist;UnityLight light;UNITY_INITIALIZE_OUTPUT(UnityLight, light);UnityDeferredCalculateLightParams (i, wpos, uv, light.dir, atten, fadeDist);light.color = _LightColor.rgb * atten;// unpack Gbufferhalf4 gbuffer0 = tex2D (_CameraGBufferTexture0, uv);half4 gbuffer1 = tex2D (_CameraGBufferTexture1, uv);half4 gbuffer2 = tex2D (_CameraGBufferTexture2, uv);UnityStandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);float3 eyeVec = normalize(wpos-_WorldSpaceCameraPos);half oneMinusReflectivity = 1 - SpecularStrength(data.specularColor.rgb);UnityIndirect ind;UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind);ind.diffuse = 0;ind.specular = 0;half4 res = UNITY_BRDF_PBS (data.diffuseColor, data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, -eyeVec, light, ind);return res;}

1.当相机进入光的体积，光的背面被剔除，这个光就不能被渲染

2.如果光很小什么都没照到(体积内没有物体)，这个体积也要绘制一遍

1.因为画过GBuffer，所以有深度贴图可以进行深度测试

2.进制写入depth buffer，现在开始depth buffer为只读

3.禁止背面剔除，因为需要光体积的正面和背面进行判断

4. Set the stencil test to always succeed(清空为0)

5.在画背面的时候，如果深度测试失败，就增加stencil buffer的值。如果深度测试或模板测试成功就不变

6.在画正面的时候，如果深度测试失败，就减少stencil buffer的值。如果深度测试或模板测试成功就不变

7.渲染光体积

A物体部分光体积，前面没有通过深度测试，将stencil-1,背面也没通过深度测试，将stencil+1,此时stencil = 0,光体积不渲染

C物体部分光体积，前面深度测试成功stencil不变，背面深度测试成功stencil不变,此时stencil = 0,光体积不渲染

B物体部分光体积，前面深度测试成功stencil不变，背面深度测试失败，将stencil+1,此时stencil = 1,光体积渲染

We render the geometry into the G buffer, setup the stencil test/operation according to the above and then render the bounding sphere of each light into the stencil buffer. The peculiar stencil setup that we saw guarantees that only the pixels in the stencil buffer covered by objects inside the bounding sphere will have a value greater than zero. We call this step the Stencil Pass and since we are only interested in writing into the stencil buffer we use a null fragment shader.Next we render the sphere again using the lighting fragment shader but this time we configure the stencil test to pass only when the stencil value of the pixel is different from zero. All the pixels of objects outside the light volume will fail the stencil test and we will calculate lighting on a very small subset of the pixels that are actually covered by the light sphere.

Unity文档中也说https://docs.unity3d.com/Manual/SL-Stencil.html

Stencil functionality for objects rendered in the deferred rendering path

is somewhat limited, as during the base pass and lighting pass the stencil buffer is used for other purposes. During those two stages stencil state defined in the shader will be ignored and only taken into account during the final pass. Because of that it’s not possible to mask out these objects based on a stencil test, but they can still modify the buffer contents, to be used by objects rendered later in the frame. Objects rendered in the forward rendering

path following the deferred path (e.g. transparent objects or objects without a surface shader) will set their stencil state normally again.

spotLight的光照体积：

pointlight的光照体积：

Direct light的光照是一个DrawGL，全屏绘制：

HDR会加到浮点Buffer

RT3, ARGB2101010 (non-HDR) or ARGBHalf (HDR) format: Emission + lighting + lightmaps

+ reflection probes

buffer.

// Pass 1: Lighting pass

// LDR case – Lighting encoded into a subtractive ARGB8 buffer

// HDR case – Lighting additively blended into floating point buffer Pass

#ifndef UNITY_HDR_ONemissiveColor.rgb = exp2(-emissiveColor.rgb);#endif

half4 c = CalculateLight(i);#ifdef UNITY_HDR_ONreturn c;#elsereturn exp2(-c);#endif

// Pass 2: Final decode pass.

// Used only with HDR off, to decode the logarithmic buffer into the main RT

return -log2(tex2D(_LightBuffer, i.texcoord));

OpenGL：

http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html

Deferred lighting approaches

Unity：

https://catlikecoding.com/unity/tutorials/rendering/part-13/Rendering-13.pdf

http://aes.jypc.org/?p=39438

——–by wolf96

More：【微信公众号】 u3dnotes

0
0 收藏

0 评论
0 收藏
0