Environment mapping

This project implements environment mapping

The key to environment mapping is to claculate the reflection vector and then use the reflection vector to lookup a cube map.

HLSL has an intrinsic function to calculate the reflection vector. This is done for each vertex.

  // compute the reflection vector in model space
  float3 reflect= reflect(inPos-obj_eye,inNormal);
   
   // transform reflection vector to world space (apply model transformations)
   // use TEXCOOD0 to pass this vector to the pixel shader
   Out.Reflect=mul(world_matrix,reflect);

 

the reflection vector is passed to the pixel shader using on of the texture coordinate registers and interpolated for each pixel. The environment colour is obtained from a cube map and mixed with the color calculated using regular lighting.

float4 ps_main_Reflect(float4 inColor: COLOR0,float3 inReflect: TEXCOORD0) : COLOR 
{
	// use texCUBE to lookup environment map
  // acheive a balance between basic lighting and reflection
  
	 return inColor*0.3+texCUBE(textureSampler,inReflect)*0.7;
   

}

Rendering a model with custom effect

Each part of an XNA model is assigned an effect, which is applied when the object is drawn. The default effect is BasicEffect. In order to apply a custom effect, we must set the effect property of each part of the model to the custom effect

//c# code 
// need to set the environment effect of each part of the mesh
            foreach (ModelMesh m in teapot.Meshes)
            {               
                foreach (ModelMeshPart mmp in m.MeshParts)
                {
                    mmp.Effect = effect;
                }
                
                m.Draw();
            }

Complete Shader Code

float4x4 view_proj_matrix;
float4 Light_Ambient;
float4 Light1_Position;
float3 view_position;
float4x4 inv_world_matrix;
float4x4 world_matrix;
uniform extern texture Texture;


sampler textureSampler = sampler_state
{
   Texture = ;
   MAGFILTER = LINEAR;
   MINFILTER = LINEAR;
   MIPFILTER = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP; 
};


struct VS_OUTPUT 
{
   float4 Pos:    	POSITION;
   float3 Color:		COLOR0;
   float3 Reflect:	TEXCOORD0;
};


VS_OUTPUT vs_main_Reflect(float4 inPos: POSITION, float3 inNormal: NORMAL,float2 inTxr: TEXCOORD0)
{
   VS_OUTPUT Out=(VS_OUTPUT)0;

   // Compute the projected position and send out the texture coordinates
   Out.Pos = mul(inPos,view_proj_matrix );
   
   
   inNormal=normalize(inNormal);
   
   // Output the ambient color
   float4 Color =Light_Ambient;


   
   
   // Determine the eye and light vectors in model space
   vector obj_eye=mul(view_position,inv_world_matrix);
   vector EyeDir = normalize(obj_eye-inPos);

   vector obj_light=mul(Light1_Position,inv_world_matrix);
   vector LightDir = normalize(obj_light - inPos);


   // Compute half vector
   vector HalfVect = normalize(LightDir+EyeDir);

   

   // Specular
   float SpecularAttn =  max(0,pow(  dot(inNormal, HalfVect),32));


   // Diffuse
   float AngleAttn = max(0, dot(inNormal, LightDir) );

 
   // Compute final lighting
   
   Color *=  (SpecularAttn+AngleAttn);

   

   // Output Final Color
   Out.Color=Color;
   
   // compute the reflection vector in model space
   vector reflect= reflect(inPos-obj_eye,inNormal);
   
   // transform reflection vector to world space (apply model transformations)
   // use TEXCOOD0 to pass this vector to the pixel shader
   Out.Reflect=mul(world_matrix,reflect);

   return Out;
}

float4 ps_main_Reflect(float4 inColor: COLOR0,float3 inReflect: TEXCOORD0) : COLOR 
{
	// use texCUBE to lookup environment map
    // acheive a balance between basic lighting and reflection
   return inColor*0.3+texCUBE(textureSampler,inReflect)*0.7;
   

}


technique EnvReflect{
	pass P0
	{
        ZENABLE = TRUE;
		CULLMODE = CCW;
	    vertexShader = compile vs_2_0 vs_main_Reflect();
        pixelShader = compile ps_2_0 ps_main_Reflect();

	}
}