Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Where is the lighting code of the deferred shader?

Discussion in 'Shaders' started by Middle-earth, May 17, 2019.

  1. Middle-earth

    Middle-earth

    Joined:
    Jan 23, 2018
    Posts:
    77
    I read the deferred pass of standard shader.As we know,there are two parts of a deferred rendering,one is calculating GBuffer,which can be found in standard shader:
    #pragma vertex vertDeferred
    #pragma fragment fragDeferred
    another is lighting,behaving like the postprocessing.But I don't know where is the lighting code to finish the rendering of the standard shader.Does anybody know that?And if possible,please tell me which C# file calls that shader to calculating lighting.
     
  2. Middle-earth

    Middle-earth

    Joined:
    Jan 23, 2018
    Posts:
    77
    I doubt lighting code is in Internal-DeferredShading.shader.However,first,I have no proof.Second,it's strange that there is no emissive calculation in it.But standard shader output 4 GBuffer include emissive.
     
  3. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,983
    It's scattered in some .cginc files, you probably need to look in UnityPBSLighting.cginc.
     
  4. Middle-earth

    Middle-earth

    Joined:
    Jan 23, 2018
    Posts:
    77
    Thanks,but it seems not right.The lighting code which I mention above should be called after getting GBuffer,so the 4 GBuffer which outputted by fragDeferred in build-in standard shader should be the input value of the lighting code.I've seen the function LightingStandardSpecular_Deferred in UnityPBSLighting.cginc,it is to create the 4 GBuffer,which is not I want.
     
  5. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,983
    Internal-DeferredShading.shader has a function CalculateLight, which decompresses the GBuffer and passes it on to UNITY_BRDF_PBS, which is then expanded into a specific BRDF using a macro. This expansion happens in UnityPBSLighting.cginc. The actual BRDF functions are in UnityStandardBRDF.cginc
     
  6. Middle-earth

    Middle-earth

    Joined:
    Jan 23, 2018
    Posts:
    77
    One question is the about emissive.This is the fs of standard shader:
    void fragDeferred (
    VertexOutputDeferred i,
    out half4 outGBuffer0 : SV_Target0,
    out half4 outGBuffer1 : SV_Target1,
    out half4 outGBuffer2 : SV_Target2,
    out half4 outEmission : SV_Target3 // RT3: emission (rgb), --unused-- (a)
    #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
    ,out half4 outShadowMask : SV_Target4 // RT4: shadowmask (rgba)
    #endif
    )
    {
    }

    This is CalculateLight in Internal-DeferredShading.shader:
    half4 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 Gbuffer
    half4 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;
    }

    We can find there is no _CameraGBufferTexture3 in CalculateLight,which stores emissive information outputted by "out half4 outEmission : SV_Target3".
    So where is the code to decompresses the emissive GBuffer?
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    First, please use code tags.

    The “emission” render target is also what ambient and baked lighting is rendered to during the gbuffer rendering. After that it continues to be the render target for deferred reflections, deferred lighting, and eventually the skybox and everything else. It’s never “decoded” in the sense that it’s bound as a gbuffer for something else to sample from as it simply becomes the target everything else renders to.

    If you want to access it directly, you’d need to copy it to another render texture with a command buffer. But if you need just the emissive with out any ambient lighting, you’d need to render that out separately with a replacement shader pass or similar.
     
  8. Middle-earth

    Middle-earth

    Joined:
    Jan 23, 2018
    Posts:
    77
    Thank you very much!That's what I want to know.By the way thanks also for letting me know the code tag function.

    One more question,the GI result in emissive GBuffer which is outputted by fragDeferred of standard shader in UnityStandardCore.cginc has already multiplied ambient occlusion(AO).And in the following lighting code,AO is useless any more.However,when standard shader output GBuffers,it use a alpha channel of the first GBuffer to store AO,the code can be found in UnityGBuffer.cginc as below:

    Code (CSharp):
    1. void UnityStandardDataToGbuffer(UnityStandardData data, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
    2. {
    3.     // RT0: diffuse color (rgb), occlusion (a) - sRGB rendertarget
    4.     outGBuffer0 = half4(data.diffuseColor, data.occlusion);
    5.  
    6.     // RT1: spec color (rgb), smoothness (a) - sRGB rendertarget
    7.     outGBuffer1 = half4(data.specularColor, data.smoothness);
    8.  
    9.     // RT2: normal (rgb), --unused, very low precision-- (a)
    10.     outGBuffer2 = half4(data.normalWorld * 0.5f + 0.5f, 1.0f);
    11. }
    But I search the lighting code and find no code use AO in Internal-DeferredShading.shader.
    So my question is why fragDeferred of standard shader still output AO information to GBuffer?
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    It’s not useless. It’s used for deferred reflections. Original the diffuse alpha gbuffer was unused. They used to do reflections as part of the gbuffer pass, which did reflections the same as forward (which uses a single pre-blended reflection probe, or blends between two reflection probes uniformly across the entire object), so it could apply the per object AO then and didn’t need to keep it around. However it’s nice to have it because it means you can do custom “faux ambient” lights that are affected by AO.

    One unfortunate side effect of putting all of these into the same buffer is screen space AO applies to ambient lighting, baked lighting, and emissive alike as it runs after the initial gbuffer and deferred reflections are rendered, but before real time lights. Unity uses another trick when you’re using the shadowmask baked shadows mode in that “baked” lights are really just baked shadows, and are otherwise rendered as real time deferred lights. This has a number of benefits, one of the smallest of which is that SSAO doesn’t affect those lights like it does when using other baked shadow modes.
     
    Middle-earth likes this.
  10. henkvik

    henkvik

    Joined:
    Mar 1, 2017
    Posts:
    1
    I have encountered a problem I am not sure how to solve which I think is related to this discussion,
    we are using deferred decals with the default render and have decals that write to GBuffer0 and GBuffer2 at CommandBuffer.BeforeReflections but since our scene is mostly lit by indirect lighting the decals become invisible when the lightning in the scene gets too low, I have tracked the issue to RenderDeferred.ReflectionsToEmissive where I see that the "TempBuffer 55" does not contain the decals only the terrain color, but I don't know what to do with this information.

    I don't know how to solve this, help would be very appreciated.
     
    Last edited: Mar 13, 2020