SamplerState gSampleState : SampleState; RasterizerState gRasterizerState : RastState; float4x4 gWorldViewProj : WorldViewProjection; float4x4 gWorldMatrix : WorldMatrix; texture2D gDiffuseMap : DiffuseMap; texture2D gNormalMap : Normal; texture2D gSpecularMap : Specular; texture2D gGlossMap : Gloss; float3 gLightDirection : LightDirection; float3 gLightColor : LightColor; float3 gCameraPosition : CameraPosition; bool gUseNormal : UseNormal; static const float3 gAmbient = float3(.03f, .03f, .03f); static const float gLightIntensity = 7.f; static const float PI = 3.14159f; static const float gSpecularReflectance = 1.f; static const float gShininess = 25.f; //Input output struct VS_INPUT { float3 Position : POSITION; float2 TexCoord : TEXCOORD; float3 Normal : NORMAL; float3 Tangent : TANGENT; float4 InstanceWorld0 : INSTANCEWORLD0; float4 InstanceWorld1 : INSTANCEWORLD1; float4 InstanceWorld2 : INSTANCEWORLD2; float4 InstanceWorld3 : INSTANCEWORLD3; float4 InstanceColor : INSTANCECOLOR; }; struct VS_OUTPUT { float4 Position : SV_POSITION; float4 WorldPosition : WORLDPOSITION; float2 TexCoord : TEXCOORD; float3 Normal : NORMAL; float3 Tangent : TANGENT; float4 Color : COLOR; // Pass instance color to the pixel shader }; //---------------------- // Rasterizer state //---------------------- // RasterizerState gRasterizerState // { // CullMode = none; // FrontCounterClockwise = false; //default // }; //Vertex shader VS_OUTPUT VS(VS_INPUT input) { VS_OUTPUT output; // Reconstruct the world matrix from instance data float4x4 instanceWorld = float4x4( input.InstanceWorld0, input.InstanceWorld1, input.InstanceWorld2, input.InstanceWorld3 ); // Transform the position to world space and then to clip space float4 worldPosition = mul(float4(input.Position, 1.0f), instanceWorld); output.Position = mul(worldPosition, gWorldViewProj); // Transform to clip space using gViewProjMatrix output.WorldPosition = worldPosition; // Pass through the // // Extract the 3x3 upper portion of the world matrix for normal and tangent transformations float3x3 instanceWorld3x3 = (float3x3)instanceWorld; // Extract upper 3x3 matrix output.Normal = normalize(mul(input.Normal, instanceWorld3x3)); // Transform and normalize the normal output.Tangent = normalize(mul(input.Tangent, instanceWorld3x3)); // Transform and normalize the tangent // Pass through texture coordinates output.TexCoord = input.TexCoord; // Pass through the instance color output.Color = input.InstanceColor; return output; } float3 Phong(float ks, float exp, float3 l, float3 v, float3 n) { float3 reflected = reflect(l, n); float cosAngle = dot(reflected, v); return ks * pow(max(0.f, cosAngle), exp) * gLightColor; } float3 Lambert(float kd, float3 cd) { return (kd * cd) / PI; } float3 Shade(VS_OUTPUT input) { // Sample diffuse, specular, and gloss maps float3 diffuseSample = gDiffuseMap.Sample(gSampleState, input.TexCoord).rgb; float3 specularSample = gSpecularMap.Sample(gSampleState, input.TexCoord).rgb; float glossSample = gGlossMap.Sample(gSampleState, input.TexCoord).x; float3 normalSample = gNormalMap.Sample(gSampleState, input.TexCoord).rgb; // Compute inversed view and light directions float3 invViewDirection = normalize(gCameraPosition - input.WorldPosition.xyz); float3 invLightDirection = -gLightDirection; // Compute tangent space axes if normal mapping is used float3 normal = input.Normal; if (gUseNormal) { float3 binormal = cross(input.Normal, input.Tangent); float3x3 tangentSpaceAxis = float3x3(input.Tangent, binormal, input.Normal); // Sample and transform normal map normal = float3(2.f * normalSample.x - 1.f, 2.f * normalSample.y - 1.f, 2.f * normalSample.z - 1.f); normal = mul(normal, tangentSpaceAxis); } // Compute Lambert diffuse lighting float3 diffuse = Lambert(gLightIntensity, diffuseSample); // Compute Phong specular lighting float ks = (specularSample.x + specularSample.y + specularSample.z) / 3.f; float3 specular = Phong(ks, glossSample * gShininess, invLightDirection, invViewDirection, normal); // Compute observed area based on the cosine of the light angle float cosAngle = dot(invLightDirection, normal); float3 observedArea = float3(cosAngle, cosAngle, cosAngle); // Combine lighting components float3 color = saturate(diffuse * observedArea + specular + gAmbient * cosAngle); return color; } float4 PS(VS_OUTPUT input) : SV_TARGET { // Normalize vectors float3 norm = normalize(input.Normal); float3 lightDir = normalize(gLightDirection); float3 viewDir = normalize(gCameraPosition - input.WorldPosition.xyz); // Compute ambient lighting float3 ambient = gAmbient * gLightColor; // Compute diffuse lighting float diff = max(dot(norm, lightDir), 0.0f); // Ensure clamping to non-negative values float3 diffuse = diff * gLightColor; // Compute specular lighting float3 reflectDir = reflect(-lightDir, norm); // Reflect light direction around normal float spec = pow(max(dot(reflectDir, viewDir), 0.0f), gShininess); // Apply shininess exponent float3 specular = gSpecularReflectance * spec * gLightColor; // Combine the lighting components with input color float3 finalColor = ambient + diffuse + specular; // return float4(finalColor * input.Color.rgb, input.Color.a); // Multiply by vertex color return gDiffuseMap.Sample(gSampleState, input.TexCoord); } float4 PSNormal(VS_OUTPUT input) : SV_TARGET { // Normalize the input normal float3 norm = normalize(input.Normal); // Map the normal from [-1, 1] to [0, 1] float3 normalColor = 0.5f * (norm + 1.0f); // Output the normal as RGB color return float4(normalColor, 1.0f); // Alpha is set to 1 for full opacity } DepthStencilState gDepthStencilState { //enable DepthEnable = true; DepthWriteMask = ALL; DepthFunc = LESS; //stencil StencilEnable = true; }; technique11 DefaultTechnique { pass P0 { SetDepthStencilState(gDepthStencilState, 0); SetRasterizerState(gRasterizerState); SetVertexShader(CompileShader(vs_5_0, VS())); SetGeometryShader(NULL); SetPixelShader(CompileShader(ps_5_0, PS())); } }