Shader

Simple Hemispheric Lighting

Hemispheric Lighting is a simple way to add some realism to your ambient scene light. Hemispheric lighting will simulate the effect of light or sunlight coming from above the model and light that would be reflected from the ground below the model. It takes two colors, a sky color and a ground color, and linearly interpolates that light across the mesh based on the world space normals of the mesh. This gives the effect of the top-facing faces of the model being lit by the sky color and bottom-facing normals being lit by the ground color.

Image of Simple Hemispheric Lighting

Intro

This beginners tutorial will walk through creating a simple hemispheric lighting shader in Luster.

Related Files

The Shader File

The Simple Hemispheric Lighting shader has two programs in it: the vertex program and the fragment program. Both of these programs are quite simple.

It is in the vertex program that we calculate the lighting on a per-vertex basis.

// Hemispheric Lighting (Vertex Program)
void HemisphericLighting_VP(
	// Scene values to take in
	float4 inPosition		: POSITION,
	float4 inNormal			: NORMAL,
	float4 inTex			: TEXCOORD0,
	
	// Values passed in from our material file
	uniform float4x4 worldviewproj,
	uniform float4 skyColor,
	uniform float4 groundColor,
	
	// Values to go out to our Pixel Shader
	out float4 outPos		: POSITION,
	out float4 outDiff		: TEXCOORD0,
	out float2 outTex		: TEXCOORD1)
{
	// Transform the position and output the texture coordinate
	outPos = mul(worldviewproj, inPosition);
	outTex = inTex;
	
	// Determine our blending (sky/ground) factor
	float factor = dot(inNormal, float3(0,-1,0))+1.0/2.0;
	
	// Determine the final lighting color
	outDiff = lerp(skyColor, groundColor, factor);
	outDiff.a = 1.0;
}

In this function, we take two parameters that are unique to the hemispheric shader: The skyColor and the groundColor. For each vertex, using the factor variable, we take the dot product of the normal of the vertex to a vector that is pointing straight down. In the end, factor is going to represent floating point value between 0 and 1, where 0 is pointing directly down and 1 is pointing directly up. We calculate a color by linearly interpolating between the ground and sky and pass this to the pixel shader.

The pixel shader function is even simpler. In the pixel shader, we simply combine the ambient term with the texture and output the value.

void HemisphericLighting_FP(
	float4 inDiff		: TEXCOORD0,
	float2 inTex		: TEXCOORD1,
	
	uniform sampler2D texture,
	
	out float4 outColor	: COLOR)
{
	// Combine our ambient hemispheric lighting color with our texture color
	outColor = inDiff * tex2D(texture, inTex);
}

Material File

The material file for this shader is one of the simpler examples of using shaders in Luster. In the material pass, we simply reference our vertex program, fragment program, and texture. In the vertex program definition, we point to the file as always and pass in our auto parameters and custom parameters.

// Define our vertex program, which is a CG shader
vertex_program HemisphericLighting_VP cg
{
	// Point to the file
	source Shaders/HemisphericLighting.cg
	
	default_params
	{
		// worldViewProjection matrix, to be received as float4x4 as worldviewproj
		param_named_auto worldviewproj worldviewproj_matrix 
		// The parameter skyColor in our shader, which is a four channel color value
		param_named skyColor float4 0.576 0.6 0.6 1.0
		// The parameter groundColor in our shader, which is a four channel color value
		param_named groundColor float4 0.20 0.254 0.105 1.0 
	}

	// Point to the function name
	entry_point HemisphericLighting_VP
	
	// Define the profile to be used. For more information on profiles, see: http://www.ogre3d.org/docs/manual/manual_18.html#SEC104
	profiles vs_1_1 arbvp1 
}

// Define our fragment (pixel) program, which is a CG shader
fragment_program HemisphericLighting_FP cg
{
	source Shaders/HemisphericLighting.cg

	entry_point HemisphericLighting_FP
	profiles ps_2_0 arbfp1
}

material HemisphericLighting
{
	technique
	{
		pass
		{
			// Reference the vertex program above
			vertex_program_ref HemisphericLighting_VP
			{
			}
			// Reference the fragment program above
			fragment_program_ref HemisphericLighting_FP
			{
			}
			// Reference the texture
			texture_unit
			{
				texture Textures/Checkers.jpg
			}
		}
	}
}

Download the entire project at the top of the page.