Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Confusion re: built-in mixed lighting / baked ambient occlusion.

Discussion in 'General Graphics' started by art_ganymede, Oct 3, 2023.

  1. art_ganymede

    art_ganymede

    Joined:
    Nov 7, 2021
    Posts:
    13
    I've been trying to wrap my head around the exact setup of the baked ambient occlusion, and the way it interacts with mixed lights for a while.

    One thing I've noticed is that baked AO seems to be "erased" or "overpowered" whenever lit:

    Dark scene

    Lit Scene

    I understand this is more accurate to IRL lighting, but this isn't entirely what I want, I'd like the AO to remain even when directly illuminated, for a more stylised look (emulating something like the vertex-colour based AO in retro games). Essentially as a pseudo-shader function:

    Code (CSharp):
    1. finalColour = textureColour * mixedLighting * bakedAO
    Essentially the baked lighting being an AO map that gets multiplied over the scene. Is this possible to accomplish by tweaking the shader itself, or its META pass?

    Unity's documentation seems to suggest that the "Direct" property should be increased for the bake, but this doesn't really seem to change anything significantly: Documentation.

    Unfortunately the documentation page on mixed lighting is quite sparse: Documentation

    Apologies for any English mistakes.
     
  2. art_ganymede

    art_ganymede

    Joined:
    Nov 7, 2021
    Posts:
    13
    Still looking for more info on this.
    I've found you can access lightmap data by writing a hlsl shader manually like this:
    Code (CSharp):
    1. half4 frag(v2f i) : COLOR
    2. {
    3. half4 main_color = tex2D(_MainTex, i.uv0);
    4. main_color.rgb *= DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1));
    5. return main_color;
    6. }
    But, I'm not too familiar with this (only have written surface shaders). And the setup does not seem to allow lighting to interact with the material using it.

    Full shader:

    Code (CSharp):
    1. // Upgrade NOTE: commented out 'float4 unity_LightmapST', a built-in variable
    2. // Upgrade NOTE: commented out 'sampler2D unity_Lightmap', a built-in variable
    3. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    4. // Upgrade NOTE: replaced tex2D unity_Lightmap with UNITY_SAMPLE_TEX2D
    5.  
    6. Shader "Diffuse Lightmap" {
    7.  
    8.   Properties {
    9.     _MainTex ("Texture 1", 2D) = "white" {}
    10.   }
    11.  
    12.   SubShader {
    13.     Tags { "RenderType" = "Opaque" }
    14.  
    15.     Pass {
    16.       // Disable lighting, we're only using the lightmap
    17.       Lighting Off
    18.  
    19.       CGPROGRAM
    20.       // Must be a vert/frag shader, not a surface shader: the necessary variables
    21.       // won't be defined yet for surface shaders.
    22.       #pragma vertex vert
    23.       #pragma fragment frag
    24.  
    25.       #include "UnityCG.cginc"
    26.  
    27.       struct v2f {
    28.         float4 pos : SV_POSITION;
    29.         float2 uv0 : TEXCOORD0;
    30.         float2 uv1 : TEXCOORD1;
    31.       };
    32.  
    33.       struct appdata_lightmap {
    34.         float4 vertex : POSITION;
    35.         float2 texcoord : TEXCOORD0;
    36.         float2 texcoord1 : TEXCOORD1;
    37.       };
    38.  
    39.       // These are prepopulated by Unity
    40.       // sampler2D unity_Lightmap;
    41.       // float4 unity_LightmapST;
    42.  
    43.       sampler2D _MainTex;
    44.       float4 _MainTex_ST; // Define this since its expected by TRANSFORM_TEX; it is also pre-populated by Unity.
    45.  
    46.       v2f vert(appdata_lightmap i) {
    47.         v2f o;
    48.         o.pos = UnityObjectToClipPos(i.vertex);
    49.  
    50.         // UnityCG.cginc - Transforms 2D UV by scale/bias property
    51.         // #define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
    52.         o.uv0 = TRANSFORM_TEX(i.texcoord, _MainTex);
    53.  
    54.         // Use `unity_LightmapST` NOT `unity_Lightmap_ST`
    55.         o.uv1 = i.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
    56.         return o;
    57.       }
    58.  
    59.       half4 frag(v2f i) : COLOR {
    60.         half4 main_color = tex2D(_MainTex, i.uv0);
    61.  
    62.         // Decodes lightmaps:
    63.         // - doubleLDR encoded on GLES
    64.         // - RGBM encoded with range [0;8] on other platforms using surface shaders
    65.         // inline fixed3 DecodeLightmap(fixed4 color) {
    66.         // #if defined(SHADER_API_GLES) && defined(SHADER_API_MOBILE)
    67.           // return 2.0 * color.rgb;
    68.         // #else
    69.           // return (8.0 * color.a) * color.rgb;
    70.         // #endif
    71.         // }
    72.  
    73.         main_color.rgb *= DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1));
    74.         return main_color;
    75.       }
    76.       ENDCG
    77.     }
    78.   }
    79. }
     
  3. art_ganymede

    art_ganymede

    Joined:
    Nov 7, 2021
    Posts:
    13
    Still looking for answers on this one - The documentation also just implies that mixed lights bakes indirect lighting only. But that seems to imply a little more than "just" AO being baked, as the produced maps look a little skybox-tinted.