phong_model.glsl 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. bool noLights = true;
  27. const float EPS = 0.00001;
  28. float specular;
  29. #if AMB_LIGHTS>0
  30. noLights = false;
  31. // Ambient lights
  32. for (int i = 0; i < AMB_LIGHTS; ++i) {
  33. ambientTotal += AmbientLightColor[i] * matAmbient;
  34. }
  35. #endif
  36. #if DIR_LIGHTS>0
  37. noLights = false;
  38. // Directional lights
  39. for (int i = 0; i < DIR_LIGHTS; ++i) {
  40. vec3 lightDirection = normalize(DirLightPosition(i)); // Vector from fragment to light source
  41. float dotNormal = dot(lightDirection, normal); // Dot product between light direction and fragment normal
  42. if (dotNormal > EPS) { // If the fragment is lit
  43. diffuseTotal += DirLightColor(i) * matDiffuse * dotNormal;
  44. #ifdef BLINN
  45. specular = pow(max(dot(normal, normalize(lightDirection + camDir)), 0.0), MatShininess);
  46. #else
  47. specular = pow(max(dot(reflect(-lightDirection, normal), camDir), 0.0), MatShininess);
  48. #endif
  49. specularTotal += DirLightColor(i) * MatSpecularColor * specular;
  50. }
  51. }
  52. #endif
  53. #if POINT_LIGHTS>0
  54. noLights = false;
  55. // Point lights
  56. for (int i = 0; i < POINT_LIGHTS; ++i) {
  57. vec3 lightDirection = PointLightPosition(i) - vec3(position); // Vector from fragment to light source
  58. float lightDistance = length(lightDirection); // Distance from fragment to light source
  59. lightDirection = lightDirection / lightDistance; // Normalize lightDirection
  60. float dotNormal = dot(lightDirection, normal); // Dot product between light direction and fragment normal
  61. if (dotNormal > EPS) { // If the fragment is lit
  62. float attenuation = 1.0 / (1.0 + lightDistance * (PointLightLinearDecay(i) + PointLightQuadraticDecay(i) * lightDistance));
  63. vec3 attenuatedColor = PointLightColor(i) * attenuation;
  64. diffuseTotal += attenuatedColor * matDiffuse * dotNormal;
  65. #ifdef BLINN
  66. specular = pow(max(dot(normal, normalize(lightDirection + camDir)), 0.0), MatShininess);
  67. #else
  68. specular = pow(max(dot(reflect(-lightDirection, normal), camDir), 0.0), MatShininess);
  69. #endif
  70. specularTotal += attenuatedColor * MatSpecularColor * specular;
  71. }
  72. }
  73. #endif
  74. #if SPOT_LIGHTS>0
  75. noLights = false;
  76. for (int i = 0; i < SPOT_LIGHTS; ++i) {
  77. // Calculates the direction and distance from the current vertex to this spot light.
  78. vec3 lightDirection = SpotLightPosition(i) - vec3(position); // Vector from fragment to light source
  79. float lightDistance = length(lightDirection); // Distance from fragment to light source
  80. lightDirection = lightDirection / lightDistance; // Normalize lightDirection
  81. float angleDot = dot(-lightDirection, SpotLightDirection(i));
  82. float angle = acos(angleDot);
  83. float cutoff = radians(clamp(SpotLightCutoffAngle(i), 0.0, 90.0));
  84. if (angle < cutoff) { // Check if fragment is inside spotlight beam
  85. float dotNormal = dot(lightDirection, normal); // Dot product between light direction and fragment normal
  86. if (dotNormal > EPS) { // If the fragment is lit
  87. float attenuation = 1.0 / (1.0 + lightDistance * (SpotLightLinearDecay(i) + SpotLightQuadraticDecay(i) * lightDistance));
  88. float spotFactor = pow(angleDot, SpotLightAngularDecay(i));
  89. vec3 attenuatedColor = SpotLightColor(i) * attenuation * spotFactor;
  90. diffuseTotal += attenuatedColor * matDiffuse * dotNormal;
  91. #ifdef BLINN
  92. specular = pow(max(dot(normal, normalize(lightDirection + camDir)), 0.0), MatShininess);
  93. #else
  94. specular = pow(max(dot(reflect(-lightDirection, normal), camDir), 0.0), MatShininess);
  95. #endif
  96. specularTotal += attenuatedColor * MatSpecularColor * specular;
  97. }
  98. }
  99. }
  100. #endif
  101. if (noLights) {
  102. diffuseTotal = matDiffuse;
  103. }
  104. // Sets output colors
  105. ambdiff = ambientTotal + MatEmissiveColor + diffuseTotal;
  106. spec = specularTotal;
  107. }