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; }
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(); }
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(); } }