Table of Contents

Normal Map Normalizer

This shader takes one texture (a normal map) passed from the TV3D render call and performs a process I’ve lovingly named normal-map-normalization. This process does not normalize the RGB values of the pixels themselves, but instead normalizes the lighting vectors being represented by each pixel in the normal map. This is useful for making sure a normal map is as accurate as possible after performing modifications to it in code. A normalized vector is a happy vector!

Terms of Use

Have at it! You’re welcome to use this in your commercial or private projects, free of charge. You’re also welcome to redistribute the shader as long as all my commenting stays in tact. Accreditation is appreciated, but let’s be honest, it’s not like this was a terribly complicated shader to make. ;D

Download

Source

////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//	NORMALIZENORMALMAP.FX
//	by Justin "Fex" Smith
//	fex@fex-online.com
//
//	SHADER DESCRIPTION
//	-----------------
//	This shader takes one texture (a normal map) passed from the TV3D render call and performs a process
//	I've lovingly named normal-map-normalization. This process does not normalize the RGB values of
//	the pixels themselves, but instead normalizes the lighting vectors being represented by 
//	each pixel in the normal map. This is useful for making sure a normal map is as accurate as possible
//	after performing modifications to it in code. A normalized vector is a happy vector!
//	
//	SPECIAL THANKS
//	-----------------
//	A million thanks to Zaknafein for his excellent tutorials on the TV3D Wiki,
//	and Sylvain + Zaknafein for their very helpful example shaders. :D
//
////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////
//	TEXTURE
//	-----------------
//	"texture1" (which should be  a normal map) is sent from the TV3D render function as shown here:
//	tvSCREEN.Draw_FullscreenQuadWithShader(thisShader, 0, 0, 1, 1, getTex("texture1"))
////////////////////////////////////////////////////////////////////////////////////////////////////////

sampler texture1 : register(s0);	// "texture1" is a texture sampler object that is registered to "s0": the first texture ID we passed from the TV3D render call

////////////////////////////////////////////////////////////////////////////////////////////////////////
//	STRUCTURES
//	-----------------
//	The VS_INPUT stucture defines what information is sent into the vertex shader.
//	Since we do not do anything terribly complicated in the vertex shader,
//	we only need to send it some basic information: the pre-transformed position of
//	the vertex, and the texture coordinates of the vertex.
////////////////////////////////////////////////////////////////////////////////////////////////////////

struct VS_INPUT
{
	float4 Position : POSITION;	// The position of the vertex, already transformed by TV3D before being sent to this shader
	float2 TexCoord : TEXCOORD0;	// The texture coordinate of the vertex, sent from TV3D
};

////////////////////////////////////////////////////////////////////////////////////////////////////////
//	STRUCTURE CLONES
//	-----------------
//	Since this very simple shader passes the same set of information types all the way
//	down to the pixel shader, we can just clone our VS_INPUT structure a couple of times
//	to get our VS_OUTPUT and PS_INPUT stuctures.
////////////////////////////////////////////////////////////////////////////////////////////////////////

#define VS_OUTPUT VS_INPUT
#define PS_INPUT VS_INPUT

////////////////////////////////////////////////////////////////////////////////////////////////////////
//	VERTEX SHADER
//	-----------------
//	We don't do anything special in the vertex shader: just take the information we
//	recieved and pass it down to the pixel shader.
////////////////////////////////////////////////////////////////////////////////////////////////////////

VS_OUTPUT VS_Main(VS_INPUT input)
{
	VS_OUTPUT output;			// Declare our output structure
   
	output.Position = input.Position;	// Fill our output structure with the input we recieved
	output.TexCoord = input.TexCoord;

	return output;				// Send our happy little output structure to the pixel shader
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
//	PIXEL SHADER
//	-----------------
//	The pixel shader is where the magic happens. Here, we'll use the information we were
//	sent from the vertex shader to sample our texture and get our initial RGB value. Then,
//	we'll put that RGB value through the normal-map-normalization process, and send it out
//	to be rendered. :D
////////////////////////////////////////////////////////////////////////////////////////////////////////

float4 PS_Main(VS_OUTPUT input) : COLOR
{
	float4 pixelColor = tex2D(texture1, input.TexCoord);	// First, we sample our texture to see what our starting RGB value is

	pixelColor = pixelColor - float4(0.5f.xxx,0);		// The normal-map-normalization process begins by making our RGB values relative to RGB(0.5,0.5,0.5), since RGB(0.5,0.5,0.5) = vector(0,0,0) in a normal map.
	float3 adjustedPixel = pixelColor.rgb;
	pixelColor = float4(normalize(adjustedPixel),1);	// With the RGB values adjusted, we can normalize
	pixelColor = pixelColor / float4(2,2,2,1);
	pixelColor = pixelColor + float4(0.5f.xxx,0);		// And all that's left to do is to return our RGB values so they're relative to RGB(0,0,0) once again

	return pixelColor;					// The normal-map-normalization process is complete: send our happy pixel off to be rendered!
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
//	TECHNIQUE
//	-----------------
//	The Normalize() function is only available in SM2.0 and higher
////////////////////////////////////////////////////////////////////////////////////////////////////////

technique FullscreenTech
{
   pass FullscreenPass0
   {
       VertexShader = compile vs_2_0 VS_Main();
       PixelShader = compile ps_2_0 PS_Main();
   }
}
 
sta_shader/normal_map_normalizer.txt · Last modified: 2013/11/22 13:31