my approach to an hdri compensation shader

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).

Shader "Lightmapped/justSpec" {
Properties {
	
	_SpecColor ("Spec Color", Color) = (1,1,1,1)
	_Shininess ("Shininess", Range (0.01, 1)) = 0.7
	_MainTex ("Base (RGB)", 2D) = "white" {}
	_LightMap ("LightMap (RGB)", 2D) = "black" {}
    _BumpMap ("Bumpmap (RGB)", 2D) = "bump" {}
	
}



SubShader {
     
  // Ambient pass
	Pass {
		Name "BASE"
		Tags {"LightMode" = "PixelOrNone"}
		BindChannels {
			Bind "Vertex", vertex
			Bind "normal", normal
			Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
			Bind "texcoord", texcoord1 // main uses 1st uv
		}
		SetTexture [_LightMap]  {combine texture}
		SetTexture [_MainTex] {
		combine texture * previous quad, texture * constant
		}
		}
  
  // Specular Pass
	Pass {
		Name "BASE"
		Tags {"LightMode" = "Vertex"}
		Material {
			Shininess [_Shininess]
			Specular [_SpecColor]
		}

		Lighting On
		SeperateSpecular On
       
       		BindChannels {
			Bind "Vertex", vertex
			Bind "normal", normal
			Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
			Bind "texcoord1", texcoord1 // lightmap uses 2nd uv
			Bind "texcoord", texcoord2 // main uses 1st uv
		}
		SetTexture [_LightMap]  {combine texture}
		SetTexture [_MainTex] {
		combine texture * previous quad, texture * constant
		}
        }
    }
}

Now I need to add the bump effect.
But when I add the grabpass command 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?

:smile:

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).

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:

// Pixel lights
		Pass {	
			Name "PPL"
			Tags {
				"LightMode" = "Pixel"  
				"LightTexCount" = "012"
			}
				
CGPROGRAM
// profiles arbfp1
// fragment frag
// fragmentoption ARB_fog_exp2
// fragmentoption ARB_precision_hint_fastest

// vertex vert
// autolight 7
#include "UnityCG.cginc"
#include "AutoLight.cginc"

struct v2f { 
	V2F_POS_FOG;
	float2	uv			: TEXCOORD0;
	float2	uv2			: TEXCOORD1;
	float3	lightDirT	: TEXCOORD2;
	V2F_LIGHT_COORDS(TEXCOORD3);
}; 
struct v2f2 { 
	V2F_POS_FOG;
	float2	uv			: TEXCOORD0;
	float2	uv2			: TEXCOORD1;
	float3	lightDirT	: TEXCOORD2;
};


v2f vert (appdata_tan v)
{
	v2f o;
	PositionFog( v.vertex, o.pos, o.fog );
	o.uv = TRANSFORM_UV(1);
	o.uv2 = TRANSFORM_UV(0);
	
	TANGENT_SPACE_ROTATION;
	o.lightDirT = mul( rotation, ObjSpaceLightDir( v.vertex ) );	
	
	PASS_LIGHT_COORDS(2);
	return o;
}

uniform sampler2D _BumpMap : register(s0);
uniform sampler2D _MainTex : register(s1);

float4 frag (v2f2 i, LIGHTDECL(TEXUNIT2)) : COLOR
{
	float4 texcol = tex2D(_MainTex,i.uv);
	
	// get normal from the normal map
	float3 normal = tex2D(_BumpMap, i.uv2).xyz * 2 - 1;
	
	return DiffuseLight( i.lightDirT, normal, texcol, LIGHTATT );
}
ENDCG  
			SetTexture [_BumpMap] {combine texture}
			SetTexture [_MainTex] {combine texture}
			SetTexture [_LightTexture0] {combine texture} 
			SetTexture [_LightTextureB0] {combine texture}
		}

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?

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?

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.

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

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

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.

Shader "Lightmapped/Specular 4x" {
Properties {
    _Color ("Main Color", Color) = (0,0,0,0)
    _SpecColor ("Spec Color", Color) = (1,1,1,1)
    _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _BumpMap ("Bump (RGB)", 2D) = "bump" {}
    _LightMap ("Lightmap (RGB)", 2D) = "black" {}
}

SubShader {
    Blend AppSrcAdd AppDstAdd
    Fog { Color [_AddFog] }

    // Ambient pass
    Pass {
        Name "BASE"
        Tags {"LightMode" = "PixelOrNone"}
        Color [_PPLAmbient]
        BindChannels {
            Bind "Vertex", vertex
            Bind "normal", normal
            Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
            Bind "texcoord", texcoord1 // main uses 1st uv
        }
        SetTexture [_LightMap] {
            combine texture
        }
        SetTexture [_MainTex] {
            combine texture * previous QUAD, texture
        }
    }
    
    // Vertex lights
    Pass {
        Name "BASE"
        Tags {"LightMode" = "Vertex"}
        Material {
            Diffuse [_Color]
            Shininess [_Shininess]
            Specular [_SpecColor]
        }

        Lighting On
        SeperateSpecular On

        BindChannels {
            Bind "Vertex", vertex
            Bind "normal", normal
            Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
            Bind "texcoord", texcoord1 // main uses 1st uv
        }
        
        SetTexture [_LightMap] {
            combine texture
        }
        SetTexture [_MainTex] {
            combine texture * previous QUAD, texture
        }
    }
    
    UsePass " BumpedSpecular/PPL"
}

Fallback " VertexLit", 2

}

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?

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.