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. Unity is excited to announce that we will be sponsoring Global Game Jam 2024 and we invite our amazing community to make games with us! Learn more.
    Dismiss Notice

Custom lightmapping shader

Discussion in 'Shaders' started by jcabeleira, Feb 1, 2011.

  1. jcabeleira

    jcabeleira

    Joined:
    Jan 3, 2011
    Posts:
    13
    Hey, guys. I'm trying to write a custom shader that reads and displays lightmaps generated in Unity. The shader is almost working but I still need to access the light map texture matrix in the shader to get correct lightmap UVs.I know I need this because currently the UVs are not entirely correct, but if I manually copy the offset and tilling from the lightmapping->object>atlas to the material texture properties in the inspector the UVs become fine. So, how can I make Unity feed the shader with the appropriate lightmap texture matrices?

    As you can see in the code, I'm already applying the texture matrix of the light map to the UVs with "o.uv2 = TRANSFORM_TEX (v.texcoord1, _LightMap);" but it has no effect, it seems that the matrix is empty.

    Code (csharp):
    1.  
    2. Shader "Warsoup/Lighting" {
    3. Properties {
    4.     _Color ("Base Color", Color) = (1,1,1,0.5)
    5.     DiffuseTexture ("Diffuse Texture", 2D) = "white" { }
    6.     _LightMap ("LightMap", 2D) = "white" {}
    7. }
    8. SubShader {
    9.     Pass {
    10.  
    11.         CGPROGRAM
    12.         #pragma vertex vert
    13.         #pragma fragment frag
    14.  
    15.         #include "UnityCG.cginc"
    16.  
    17.         float4      _Color;
    18.         sampler2D   DiffuseTexture;
    19.         sampler2D   _LightMap;
    20.        
    21.         float4 DiffuseTexture_ST;
    22.         float4 _LightMap_ST;
    23.  
    24.         struct v2f {
    25.             float4  pos : SV_POSITION;
    26.             float2  uv1;
    27.             float2  uv2;
    28.         };
    29.  
    30.         struct InputVS {
    31.             float4 vertex : POSITION;
    32.             float4 tangent : TANGENT;
    33.             float3 normal : NORMAL;
    34.             float4 texcoord : TEXCOORD0;
    35.             float4 texcoord1 : TEXCOORD1;
    36.         };
    37.        
    38.         v2f vert (InputVS v)
    39.         {
    40.             v2f o;
    41.             o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    42.             o.uv1 = TRANSFORM_TEX (v.texcoord, DiffuseTexture);
    43.             o.uv2 = TRANSFORM_TEX (v.texcoord1, _LightMap);
    44.             return o;
    45.         }
    46.  
    47.         half4 frag (v2f i) : COLOR
    48.         {
    49.             half4 texcol = tex2D (DiffuseTexture, i.uv1);
    50.             half4 lightmap = tex2D (_LightMap, i.uv2);
    51.             return texcol*lightmap;
    52.         }
    53.         ENDCG
    54.  
    55.     }
    56. }
    57. Fallback "VertexLit"
    58. }
    59.  
     
    Last edited: Feb 1, 2011
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    your shaderlab part is missing the channel bindings so I'm unsure UV2 is even fed in correctly
     
  3. jcabeleira

    jcabeleira

    Joined:
    Jan 3, 2011
    Posts:
    13
    I believe shader bindings are not necessary when you use a Cg shader.
    Nevertheless, the UV2 is feed correctly because I can render the lightmaps if I feed the texture matrix by hand. So, now I only need that matrix to be fed correctly.
     
  4. jcabeleira

    jcabeleira

    Joined:
    Jan 3, 2011
    Posts:
    13
    Here is the solution in case any one needs it.

    Input Data:

    sampler2D unity_Lightmap; //Far lightmap.
    sampler2D unity_LightmapInd; //Near lightmap (indirect lighting only).
    float4 unity_LightmapST; //Lightmap atlasing data.

    In the vertex shader, apply the atlasing data like this:

    o.lightmapUV = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;

    PS: thanks to Aras for the solution.
     
    Last edited: Feb 9, 2011
    dog_funtom likes this.
  5. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    sweet, thanks for sharing
     
  6. Slin

    Slin

    Joined:
    Jun 27, 2010
    Posts:
    85
    Hey thanks a lot for that information!

    However, I am trying to realize the same effect as a fixed function effect, but have troubles with the texture coordinates of the lightmap again.
    This is what my code looks like:
    Code (csharp):
    1.  
    2. SubShader
    3.     {
    4.         Pass
    5.         {
    6.             BindChannels
    7.             {
    8.                 Bind "Vertex", vertex
    9.                 Bind "texcoord", texcoord0
    10.                 Bind "texcoord1", texcoord1
    11.             }
    12.              
    13.             Tags {"LightMode" = "Always"}
    14.             SetTexture [_MainTex]
    15.             SetTexture [unity_Lightmap]
    16.             {
    17.                 combine previous*texture
    18.             }
    19.         }
    20.     }
    21.  
    Any ideas on how to solve that would be really great!
    Is it possible to set the texture transformation matrix directly from within the .shader file?
    Like: matrix (unity_LightmapST.x, 0.0, 0.0, unity_LightmapST.z, 0.0, unity_LightmapST.y, 0.0, unity_LightmapST.w, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) How to do something like this correctly, or doesn´t it work at all?
     
    IgorAherne likes this.
  7. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    best thing to do is take a shader with lightmapping, add the debug pragma and let it compile and see what unity adds for lightmapping in the FFP case
     
  8. Slin

    Slin

    Joined:
    Jun 27, 2010
    Posts:
    85
    Thanks, although, it was already enough to just look at one of the built in shaders...
    Strange, I thought that I already looked there :).
     
  9. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
  10. temps

    temps

    Joined:
    Dec 7, 2011
    Posts:
    10
    Hi!

    (Diggin up an old post but this is really relevant.)

    I'm doing the same thing, using the lightmaps only as ambient occlusion. It works great when there's baked lighting but when it isn't the lightmap texture obviously doesn't exist. And it doesn't look good. What I want to do is use the LIGHTMAP_ON ifdef to detect if there are lightmaps for this object but since #pragma nolightmap sets every pass to LIGHTMAP_OFF I can't.

    Does any of you know how I can detect if there are lightmaps for an object and only apply them if they exists?