// This is C5E7_attenuateLighting from "The Cg Tutorial" (Addison-Wesley, ISBN // 0321194969) by Randima Fernando and Mark J. Kilgard. See page 135. // From page 128 struct Material { float3 Ke; float3 Ka; float3 Kd; float3 Ks; float shininess; }; // From page 138 struct Light { float3 position; float3 color; float kC; float kL; float kQ; float3 direction; float cosInnerCone; float cosOuterCone; }; // From page 135 float C5E6_attenuation(float3 P, Light light) { float d = distance(P, light.position); return 1 / (light.kC + light.kL * d + light.kQ * d * d); } // From page 139 float C5E9_dualConeSpotlight(float3 P, Light light) { float3 V = normalize(P - light.position); float cosOuterCone = light.cosOuterCone; float cosInnerCone = light.cosInnerCone; float cosDirection = dot(V, light.direction); //float cosDirection = dot(V, normalize(light.direction)); return smoothstep(cosOuterCone, cosInnerCone, cosDirection); } // From page 139 void C5E10_spotAttenLighting(Light light, float3 P, float3 N, float3 eyePosition, float shininess, out float3 diffuseResult, out float3 specularResult) { // Compute attenuation float attenuationFactor = C5E6_attenuation(P, light); // Compute spotlight effect float spotEffect = C5E9_dualConeSpotlight(P, light); //spotEffect = 1; // Compute the diffuse lighting float3 L = normalize(light.position - P); float diffuseLight = max(dot(N, L), 0); diffuseResult = attenuationFactor * spotEffect * light.color * diffuseLight; // Compute the specular lighting float3 V = normalize(eyePosition - P); float3 H = normalize(L + V); float specularLight = pow(max(dot(N, H), 0), shininess); if (diffuseLight <= 0) specularLight = 0; specularResult = attenuationFactor * spotEffect * light.color * specularLight; } // Based on C5E4v_twoLights (page 131) but for just one per-fragment light void oneLight(float4 position : TEXCOORD0, float3 normal : TEXCOORD1, out float4 color : COLOR, uniform float3 eyePosition, uniform float3 globalAmbient, uniform Light lights[1], uniform Material material) { // Calculate emissive and ambient terms float3 emissive = material.Ke; float3 ambient = material.Ka * globalAmbient; // Loop over diffuse and specular contributions for each light float3 diffuseLight; float3 specularLight; float3 diffuseSum = 0; float3 specularSum = 0; for (int i = 0; i < 1; i++) { C5E10_spotAttenLighting(lights[i], position.xyz, normal, eyePosition, material.shininess, diffuseLight, specularLight); diffuseSum += diffuseLight; specularSum += specularLight; } // Now modulate diffuse and specular by material color float3 diffuse = material.Kd * diffuseSum; float3 specular = material.Ks * specularSum; color.xyz = emissive + ambient + diffuse + specular; //color.xyz = 0.2 * diffuseSum; color.w = 1; }