chunkPhongModel.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package shader
  5. func init() {
  6. AddChunk("phong_model", chunkPhongModel)
  7. }
  8. const chunkPhongModel = `
  9. /***
  10. phong lighting model
  11. Parameters:
  12. position: input vertex position in camera coordinates
  13. normal: input vertex normal in camera coordinates
  14. camDir: input camera directions
  15. matAmbient: input material ambient color
  16. matDiffuse: input material diffuse color
  17. ambdiff: output ambient+diffuse color
  18. spec: output specular color
  19. Uniforms:
  20. AmbientLightColor[]
  21. DiffuseLightColor[]
  22. DiffuseLightPosition[]
  23. PointLightColor[]
  24. PointLightPosition[];
  25. PointLightLinearDecay[];
  26. PointLightQuadraticDecay[];
  27. MatSpecularColor
  28. MatShininess
  29. */
  30. void phongModel(vec4 position, vec3 normal, vec3 camDir, vec3 matAmbient, vec3 matDiffuse, out vec3 ambdiff, out vec3 spec) {
  31. vec3 ambientTotal = vec3(0.0);
  32. vec3 diffuseTotal = vec3(0.0);
  33. vec3 specularTotal = vec3(0.0);
  34. {{if .AmbientLightsMax }}
  35. for (int i = 0; i < {{.AmbientLightsMax}}; i++) {
  36. ambientTotal += AmbientLightColor[i] * matAmbient;
  37. }
  38. {{ end }}
  39. {{if .DirLightsMax }}
  40. for (int i = 0; i < {{.DirLightsMax}}; i++) {
  41. // Diffuse reflection
  42. // DirLightPosition is the direction of the current light
  43. vec3 lightDirection = normalize(DirLightPosition[i]);
  44. // Calculates the dot product between the light direction and this vertex normal.
  45. float dotNormal = max(dot(lightDirection, normal), 0.0);
  46. diffuseTotal += DirLightColor[i] * matDiffuse * dotNormal;
  47. // Specular reflection
  48. // Calculates the light reflection vector
  49. vec3 ref = reflect(-lightDirection, normal);
  50. if (dotNormal > 0.0) {
  51. specularTotal += DirLightColor[i] * MatSpecularColor * pow(max(dot(ref, camDir), 0.0), MatShininess);
  52. }
  53. }
  54. {{ end }}
  55. {{if .PointLightsMax }}
  56. for (int i = 0; i < {{.PointLightsMax}}; i++) {
  57. // Calculates the direction and distance from the current vertex to this point light.
  58. vec3 lightDirection = PointLightPosition[i] - vec3(position);
  59. float lightDistance = length(lightDirection);
  60. // Normalizes the lightDirection
  61. lightDirection = lightDirection / lightDistance;
  62. // Calculates the attenuation due to the distance of the light
  63. float attenuation = 1.0 / (1.0 + PointLightLinearDecay[i] * lightDistance +
  64. PointLightQuadraticDecay[i] * lightDistance * lightDistance);
  65. // Diffuse reflection
  66. float dotNormal = max(dot(lightDirection, normal), 0.0);
  67. diffuseTotal += PointLightColor[i] * matDiffuse * dotNormal * attenuation;
  68. // Specular reflection
  69. // Calculates the light reflection vector
  70. vec3 ref = reflect(-lightDirection, normal);
  71. if (dotNormal > 0.0) {
  72. specularTotal += PointLightColor[i] * MatSpecularColor *
  73. pow(max(dot(ref, camDir), 0.0), MatShininess) * attenuation;
  74. }
  75. }
  76. {{ end }}
  77. {{if .SpotLightsMax }}
  78. for (int i = 0; i < {{.SpotLightsMax}}; i++) {
  79. // Calculates the direction and distance from the current vertex to this spot light.
  80. vec3 lightDirection = SpotLightPosition[i] - vec3(position);
  81. float lightDistance = length(lightDirection);
  82. lightDirection = lightDirection / lightDistance;
  83. // Calculates the attenuation due to the distance of the light
  84. float attenuation = 1.0 / (1.0 + SpotLightLinearDecay[i] * lightDistance +
  85. SpotLightQuadraticDecay[i] * lightDistance * lightDistance);
  86. // Calculates the angle between the vertex direction and spot direction
  87. // If this angle is greater than the cutoff the spotlight will not contribute
  88. // to the final color.
  89. float angle = acos(dot(-lightDirection, SpotLightDirection[i]));
  90. float cutoff = radians(clamp(SpotLightCutoffAngle[i], 0.0, 90.0));
  91. if (angle >= cutoff) {
  92. continue;
  93. }
  94. float spotFactor = pow(dot(-lightDirection, SpotLightDirection[i]), SpotLightAngularDecay[i]);
  95. // Diffuse reflection
  96. float dotNormal = max(dot(lightDirection, normal), 0.0);
  97. diffuseTotal += SpotLightColor[i] * matDiffuse * dotNormal * attenuation * spotFactor;
  98. // Specular reflection
  99. vec3 ref = reflect(-lightDirection, normal);
  100. if (dotNormal > 0.0) {
  101. specularTotal += SpotLightColor[i] * MatSpecularColor * pow(max(dot(ref, camDir), 0.0), MatShininess) * attenuation * spotFactor;
  102. }
  103. }
  104. {{ end }}
  105. // Sets output colors
  106. ambdiff = ambientTotal + MatEmissiveColor + diffuseTotal;
  107. spec = specularTotal;
  108. }
  109. `