// 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 129 struct Light { float3 position; float3 color; float kC, kL, kQ; // Extra constant, linear, and quadric attenuation factors }; // 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); } void C5E7_attenuateLighting(Light light, float3 P, float3 N, float3 eyePosition, float shininess, out float3 diffuseResult, out float3 specularResult) { // Compute attenuation float attenuation = C5E6_attenuation(P, light); // Compute the diffuse lighting float3 L = normalize(light.position - P); float diffuseLight = max(dot(L, N), 0); diffuseResult = attenuation * light.color * diffuseLight; // Compute the specular lighting float3 V = normalize(eyePosition - P); float3 H = normalize(L + V); float specularLight = pow(max(dot(H, N), 0), shininess); if (diffuseLight <= 0) specularLight = 0; specularResult = attenuation * 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++) { C5E7_attenuateLighting(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.w = 1; }