Search Unity

my approach to an hdri compensation shader

Discussion in 'Shaders' started by Mike, Apr 21, 2007.

  1. Mike

    Mike

    Joined:
    Dec 1, 2006
    Posts:
    118
    Hi!

    I'm working on a modified Lightmapped Vertex Lit shader.

    The special things on my version are:

    Unity lights don't brighten the object - they just add a specular highlight.

    The lightmapped is QUAD multiplied:
    I render my lightmaps as 96 bit HDR files, lower their exposure while converting to 24 bit PSD files (to retain nuances in overexposed areas like sunlight falling through a window on the floor).



    Code (csharp):
    1. Shader "Lightmapped/justSpec" {
    2. Properties {
    3.    
    4.     _SpecColor ("Spec Color", Color) = (1,1,1,1)
    5.     _Shininess ("Shininess", Range (0.01, 1)) = 0.7
    6.     _MainTex ("Base (RGB)", 2D) = "white" {}
    7.     _LightMap ("LightMap (RGB)", 2D) = "black" {}
    8.     _BumpMap ("Bumpmap (RGB)", 2D) = "bump" {}
    9.    
    10. }
    11.  
    12.  
    13.  
    14. SubShader {
    15.      
    16.   // Ambient pass
    17.     Pass {
    18.         Name "BASE"
    19.         Tags {"LightMode" = "PixelOrNone"}
    20.         BindChannels {
    21.             Bind "Vertex", vertex
    22.             Bind "normal", normal
    23.             Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
    24.             Bind "texcoord", texcoord1 // main uses 1st uv
    25.         }
    26.         SetTexture [_LightMap]  {combine texture}
    27.         SetTexture [_MainTex] {
    28.         combine texture * previous quad, texture * constant
    29.         }
    30.         }
    31.  
    32.   // Specular Pass
    33.     Pass {
    34.         Name "BASE"
    35.         Tags {"LightMode" = "Vertex"}
    36.         Material {
    37.             Shininess [_Shininess]
    38.             Specular [_SpecColor]
    39.         }
    40.  
    41.         Lighting On
    42.         SeperateSpecular On
    43.        
    44.             BindChannels {
    45.             Bind "Vertex", vertex
    46.             Bind "normal", normal
    47.             Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
    48.             Bind "texcoord1", texcoord1 // lightmap uses 2nd uv
    49.             Bind "texcoord", texcoord2 // main uses 1st uv
    50.         }
    51.         SetTexture [_LightMap]  {combine texture}
    52.         SetTexture [_MainTex] {
    53.         combine texture * previous quad, texture * constant
    54.         }
    55.         }
    56.     }
    57. }
    58.  


    Now I need to add the bump effect.
    But when I add the grabpass command
    Code (csharp):
    1. UsePass " Bumped/PPL"
    the shader gets super bright.

    What's the better / correct way to add the bumpmap to my shader?

    Maye some of the shaderlab heroes out there can help me a little?

    :D
     
  2. David-Helgason

    David-Helgason

    Moderator

    Joined:
    Mar 29, 2005
    Posts:
    1,104
    The thing is: Pulling in bumped/PPL will get you both diffuse and specular lighting. Since you don't have a _Color property, that will get its default value (which is white).

    The easy way is to just add the _Color property and set it to black. The proper way is to take a look at the built-in shaders, find the bumped specular shader and copy/paste the code in. Then remove the parts of the calculation where _Color gets multiplied in.

    Oh, and you probably want to UsePass " Bumped Specular/PPL" to get the specular stuff. Bumped is just diffuse lighting. (I'm not sure about the exact name, but take a look in the shader dropdown).
     
  3. Mike

    Mike

    Joined:
    Dec 1, 2006
    Posts:
    118
    Thanks for your reply David !

    I guess I need some more help on that. Maybe you or someone else would be so kind ...

    That's the code for the bump effect:

    Code (csharp):
    1. // Pixel lights
    2.         Pass { 
    3.             Name "PPL"
    4.             Tags {
    5.                 "LightMode" = "Pixel"  
    6.                 "LightTexCount" = "012"
    7.             }
    8.                
    9. CGPROGRAM
    10. // profiles arbfp1
    11. // fragment frag
    12. // fragmentoption ARB_fog_exp2
    13. // fragmentoption ARB_precision_hint_fastest
    14.  
    15. // vertex vert
    16. // autolight 7
    17. #include "UnityCG.cginc"
    18. #include "AutoLight.cginc"
    19.  
    20. struct v2f {
    21.     V2F_POS_FOG;
    22.     float2  uv          : TEXCOORD0;
    23.     float2  uv2         : TEXCOORD1;
    24.     float3  lightDirT   : TEXCOORD2;
    25.     V2F_LIGHT_COORDS(TEXCOORD3);
    26. };
    27. struct v2f2 {
    28.     V2F_POS_FOG;
    29.     float2  uv          : TEXCOORD0;
    30.     float2  uv2         : TEXCOORD1;
    31.     float3  lightDirT   : TEXCOORD2;
    32. };
    33.  
    34.  
    35. v2f vert (appdata_tan v)
    36. {
    37.     v2f o;
    38.     PositionFog( v.vertex, o.pos, o.fog );
    39.     o.uv = TRANSFORM_UV(1);
    40.     o.uv2 = TRANSFORM_UV(0);
    41.    
    42.     TANGENT_SPACE_ROTATION;
    43.     o.lightDirT = mul( rotation, ObjSpaceLightDir( v.vertex ) );   
    44.    
    45.     PASS_LIGHT_COORDS(2);
    46.     return o;
    47. }
    48.  
    49. uniform sampler2D _BumpMap : register(s0);
    50. uniform sampler2D _MainTex : register(s1);
    51.  
    52. float4 frag (v2f2 i, LIGHTDECL(TEXUNIT2)) : COLOR
    53. {
    54.     float4 texcol = tex2D(_MainTex,i.uv);
    55.    
    56.     // get normal from the normal map
    57.     float3 normal = tex2D(_BumpMap, i.uv2).xyz * 2 - 1;
    58.    
    59.     return DiffuseLight( i.lightDirT, normal, texcol, LIGHTATT );
    60. }
    61. ENDCG  
    62.             SetTexture [_BumpMap] {combine texture}
    63.             SetTexture [_MainTex] {combine texture}
    64.             SetTexture [_LightTexture0] {combine texture}
    65.             SetTexture [_LightTextureB0] {combine texture}
    66.         }

    How would I modify the code so that light sources only cause the bumps but do NOT make the diffuse texture brighter?

    Is that possible somehow?
     
  4. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Just to check if I understood your needs correctly: you want a 4x brightened lightmap, and only the bumpmapped specular (no diffuse) lighting on top?
     
  5. Mike

    Mike

    Joined:
    Dec 1, 2006
    Posts:
    118
    Yes that's right.

    The lightmapped MainTex should not be affected by diffuse light.

    I only want the bump and gloss effect on top of my lightmapped texture.
     
  6. Mike

    Mike

    Joined:
    Dec 1, 2006
    Posts:
    118
    PS: I copied and pasted the glossy pass from the builtin shaders and it works well as there's no additional brightness caused by light sources - just the specular.

    But I guess the bumpmap part kicks in diffuse light so there's some brightness at all that can actually be affected by the bump effect (darkened/brightened).

    My shader should work like:

    - multiply Lightmap with MainTex
    - brighten up 4 times
    - add specular highlight on top
    - add bump effect to all that's been calculated so far
     
  7. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    The thing is that bump effect is not something "added on top", it's the integral part of lighting calculations (bumpmap is the surface normal used for lighting).

    So for the lightmap, the only sensible way is to make bumps-that-affect-lighting into the lightmap itself. Then if you turn off diffuse completely, the bumpmap will only affect the specular highlights. Is that what you want?

    In other words: you want actual lights to produce the specular highlights only. That would mean the bumpmap only affects the highlights, as bump-mapping effect can't be done properly without a light. So the lighting process would look like:
    - multiply Lightmap with MainTex, and brighten up 4 times
    - for each light: add bumped specular highlight on top
     
  8. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Here's my attempt at the shader. Set Main Color to be black so that bump-mapping won't produce any diffuse illumination.

    Basically it's nothing fancy, just tweaked standard Lightmapped/VertexLit (took away color, and made do a 4x multiply), and a UsePass thrown at the end.

    Code (csharp):
    1. Shader "Lightmapped/Specular 4x" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (0,0,0,0)
    4.     _SpecColor ("Spec Color", Color) = (1,1,1,1)
    5.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    6.     _MainTex ("Base (RGB)", 2D) = "white" {}
    7.     _BumpMap ("Bump (RGB)", 2D) = "bump" {}
    8.     _LightMap ("Lightmap (RGB)", 2D) = "black" {}
    9. }
    10.  
    11. SubShader {
    12.     Blend AppSrcAdd AppDstAdd
    13.     Fog { Color [_AddFog] }
    14.  
    15.     // Ambient pass
    16.     Pass {
    17.         Name "BASE"
    18.         Tags {"LightMode" = "PixelOrNone"}
    19.         Color [_PPLAmbient]
    20.         BindChannels {
    21.             Bind "Vertex", vertex
    22.             Bind "normal", normal
    23.             Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
    24.             Bind "texcoord", texcoord1 // main uses 1st uv
    25.         }
    26.         SetTexture [_LightMap] {
    27.             combine texture
    28.         }
    29.         SetTexture [_MainTex] {
    30.             combine texture * previous QUAD, texture
    31.         }
    32.     }
    33.    
    34.     // Vertex lights
    35.     Pass {
    36.         Name "BASE"
    37.         Tags {"LightMode" = "Vertex"}
    38.         Material {
    39.             Diffuse [_Color]
    40.             Shininess [_Shininess]
    41.             Specular [_SpecColor]
    42.         }
    43.  
    44.         Lighting On
    45.         SeperateSpecular On
    46.  
    47.         BindChannels {
    48.             Bind "Vertex", vertex
    49.             Bind "normal", normal
    50.             Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
    51.             Bind "texcoord", texcoord1 // main uses 1st uv
    52.         }
    53.        
    54.         SetTexture [_LightMap] {
    55.             combine texture
    56.         }
    57.         SetTexture [_MainTex] {
    58.             combine texture * previous QUAD, texture
    59.         }
    60.     }
    61.    
    62.     UsePass " BumpedSpecular/PPL"
    63. }
    64.  
    65. Fallback " VertexLit", 2
    66.  
    67. }
     
  9. Mike

    Mike

    Joined:
    Dec 1, 2006
    Posts:
    118
    Thanks for the shader - now I see what I've missed when writing my version :wink:

    I really appreciate that !

    Let me try to understand this:

    Obviously when I set "_Color" to black I get the bump effect only on the specular highlight.

    I have to set "_Color" to any value above black to get the bumpmapping effect working everywhere on the surface of my object - right?
    Since without any diffuse light precalculated, there's no "light information" that bumpmapping can actually affect?


    Now what I thought of as a possible solution is to turn on diffuse lighting, add the bump effect and finally make the whole texture darker to compensate the diffuse lighting that was added at the beginning.

    Do I have to add another pass for that? Or can that be done in the CG script?
     
  10. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Yes, you'll get bumpmapping everywhere where the light does shine (attenuated by diffuse - i.e. angle between surface and the light of course).

    That could be done I guess... just make your lightmap darker and increase the diffuse you get from lights.

    However I think what you'd ideally want is some sort of Half-Life 2 lighting model, where they do cunning tricks to combine lightmaps with bump-mapping. That requires a special lightmapper though (one that can bake incoming light accross three directions). Then it does not need any actual lights to display the bumps, because the lightmap is "directional" already (so to speak). The shaders for that are pretty simple, the only trouble is that most existing lightmappers out there can't compute the data HL2 lighting requires.