phong_model.glsl 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /***
  2. phong lighting model
  3. Parameters:
  4. position: input vertex position in camera coordinates
  5. normal: input vertex normal in camera coordinates
  6. camDir: input camera directions
  7. matAmbient: input material ambient color
  8. matDiffuse: input material diffuse color
  9. ambdiff: output ambient+diffuse color
  10. spec: output specular color
  11. Uniforms:
  12. AmbientLightColor[]
  13. DiffuseLightColor[]
  14. DiffuseLightPosition[]
  15. PointLightColor[]
  16. PointLightPosition[]
  17. PointLightLinearDecay[]
  18. PointLightQuadraticDecay[]
  19. MatSpecularColor
  20. MatShininess
  21. *****/
  22. void phongModel(vec4 position, vec3 normal, vec3 camDir, vec3 matAmbient, vec3 matDiffuse, out vec3 ambdiff, out vec3 spec) {
  23. vec3 ambientTotal = vec3(0.0);
  24. vec3 diffuseTotal = vec3(0.0);
  25. vec3 specularTotal = vec3(0.0);
  26. #if AMB_LIGHTS>0
  27. // Ambient lights
  28. for (int i = 0; i < AMB_LIGHTS; ++i) {
  29. ambientTotal += AmbientLightColor[i] * matAmbient;
  30. }
  31. #endif
  32. #if DIR_LIGHTS>0
  33. // Directional lights
  34. for (int i = 0; i < DIR_LIGHTS; ++i) {
  35. vec3 lightDirection = normalize(DirLightPosition(i)); // Vector from fragment to light source
  36. float dotNormal = max(dot(lightDirection, normal), 0.0); // Dot product between light direction and fragment normal
  37. if (dotNormal > 0.0) { // If the fragment is lit
  38. diffuseTotal += DirLightColor(i) * matDiffuse * dotNormal;
  39. specularTotal += DirLightColor(i) * MatSpecularColor * pow(max(dot(reflect(-lightDirection, normal), camDir), 0.0), MatShininess);
  40. }
  41. }
  42. #endif
  43. #if POINT_LIGHTS>0
  44. // Point lights
  45. for (int i = 0; i < POINT_LIGHTS; ++i) {
  46. vec3 lightDirection = PointLightPosition(i) - vec3(position); // Vector from fragment to light source
  47. float lightDistance = length(lightDirection); // Distance from fragment to light source
  48. lightDirection = lightDirection / lightDistance; // Normalize lightDirection
  49. float dotNormal = max(dot(lightDirection, normal), 0.0); // Dot product between light direction and fragment normal
  50. if (dotNormal > 0.0) { // If the fragment is lit
  51. float attenuation = 1.0 / (1.0 + PointLightLinearDecay(i) * lightDistance + PointLightQuadraticDecay(i) * lightDistance * lightDistance);
  52. vec3 attenuatedColor = PointLightColor(i) * attenuation;
  53. diffuseTotal += attenuatedColor * matDiffuse * dotNormal;
  54. specularTotal += attenuatedColor * MatSpecularColor * pow(max(dot(reflect(-lightDirection, normal), camDir), 0.0), MatShininess);
  55. }
  56. }
  57. #endif
  58. #if SPOT_LIGHTS>0
  59. for (int i = 0; i < SPOT_LIGHTS; ++i) {
  60. // Calculates the direction and distance from the current vertex to this spot light.
  61. vec3 lightDirection = SpotLightPosition(i) - vec3(position); // Vector from fragment to light source
  62. float lightDistance = length(lightDirection); // Distance from fragment to light source
  63. lightDirection = lightDirection / lightDistance; // Normalize lightDirection
  64. float angleDot = dot(-lightDirection, SpotLightDirection(i));
  65. float angle = acos(angleDot);
  66. float cutoff = radians(clamp(SpotLightCutoffAngle(i), 0.0, 90.0));
  67. if (angle < cutoff) { // Check if fragment is inside spotlight beam
  68. float dotNormal = max(dot(lightDirection, normal), 0.0); // Dot product between light direction and fragment normal
  69. if (dotNormal > 0.0) { // If the fragment is lit
  70. float attenuation = 1.0 / (1.0 + SpotLightLinearDecay(i) * lightDistance + SpotLightQuadraticDecay(i) * lightDistance * lightDistance);
  71. float spotFactor = pow(angleDot, SpotLightAngularDecay(i));
  72. vec3 attenuatedColor = SpotLightColor(i) * attenuation * spotFactor;
  73. diffuseTotal += attenuatedColor * matDiffuse * dotNormal;
  74. specularTotal += attenuatedColor * MatSpecularColor * pow(max(dot(reflect(-lightDirection, normal), camDir), 0.0), MatShininess);
  75. }
  76. }
  77. }
  78. #endif
  79. // Sets output colors
  80. ambdiff = ambientTotal + MatEmissiveColor + diffuseTotal;
  81. spec = specularTotal;
  82. }