standard.fs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #version 100
  2. precision mediump float;
  3. varying vec3 fragPosition;
  4. varying vec2 fragTexCoord;
  5. varying vec4 fragColor;
  6. varying vec3 fragNormal;
  7. uniform sampler2D texture0;
  8. uniform sampler2D texture1;
  9. uniform sampler2D texture2;
  10. uniform vec4 colAmbient;
  11. uniform vec4 colDiffuse;
  12. uniform vec4 colSpecular;
  13. uniform float glossiness;
  14. uniform int useNormal;
  15. uniform int useSpecular;
  16. uniform mat4 modelMatrix;
  17. uniform vec3 viewDir;
  18. struct Light {
  19. int enabled;
  20. int type;
  21. vec3 position;
  22. vec3 direction;
  23. vec4 diffuse;
  24. float intensity;
  25. float radius;
  26. float coneAngle;
  27. };
  28. const int maxLights = 8;
  29. uniform Light lights[maxLights];
  30. vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
  31. {
  32. vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));
  33. vec3 surfaceToLight = l.position - surfacePos;
  34. // Diffuse shading
  35. float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0);
  36. float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;
  37. // Specular shading
  38. float spec = 0.0;
  39. if (diff > 0.0)
  40. {
  41. vec3 h = normalize(-l.direction + v);
  42. spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
  43. }
  44. return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
  45. }
  46. vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
  47. {
  48. vec3 lightDir = normalize(-l.direction);
  49. // Diffuse shading
  50. float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;
  51. // Specular shading
  52. float spec = 0.0;
  53. if (diff > 0.0)
  54. {
  55. vec3 h = normalize(lightDir + v);
  56. spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
  57. }
  58. // Combine results
  59. return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);
  60. }
  61. vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
  62. {
  63. vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
  64. vec3 lightToSurface = normalize(surfacePos - l.position);
  65. vec3 lightDir = normalize(-l.direction);
  66. // Diffuse shading
  67. float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;
  68. // Spot attenuation
  69. float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0);
  70. attenuation = dot(lightToSurface, -lightDir);
  71. float lightToSurfaceAngle = degrees(acos(attenuation));
  72. if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;
  73. float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;
  74. // Combine diffuse and attenuation
  75. float diffAttenuation = diff*attenuation;
  76. // Specular shading
  77. float spec = 0.0;
  78. if (diffAttenuation > 0.0)
  79. {
  80. vec3 h = normalize(lightDir + v);
  81. spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
  82. }
  83. return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
  84. }
  85. void main()
  86. {
  87. // Calculate fragment normal in screen space
  88. // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale)
  89. mat3 normalMatrix = mat3(modelMatrix);
  90. vec3 normal = normalize(normalMatrix*fragNormal);
  91. // Normalize normal and view direction vectors
  92. vec3 n = normalize(normal);
  93. vec3 v = normalize(viewDir);
  94. // Calculate diffuse texture color fetching
  95. vec4 texelColor = texture2D(texture0, fragTexCoord);
  96. vec3 lighting = colAmbient.rgb;
  97. // Calculate normal texture color fetching or set to maximum normal value by default
  98. if (useNormal == 1)
  99. {
  100. n *= texture2D(texture1, fragTexCoord).rgb;
  101. n = normalize(n);
  102. }
  103. // Calculate specular texture color fetching or set to maximum specular value by default
  104. float spec = 1.0;
  105. if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;
  106. for (int i = 0; i < maxLights; i++)
  107. {
  108. // Check if light is enabled
  109. if (lights[i].enabled == 1)
  110. {
  111. // Calculate lighting based on light type
  112. if(lights[i].type == 0) lighting += ComputeLightPoint(lights[i], n, v, spec);
  113. else if(lights[i].type == 1) lighting += ComputeLightDirectional(lights[i], n, v, spec);
  114. else if(lights[i].type == 2) lighting += ComputeLightSpot(lights[i], n, v, spec);
  115. // NOTE: It seems that too many ComputeLight*() operations inside for loop breaks the shader on RPI
  116. }
  117. }
  118. // Calculate final fragment color
  119. gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a);
  120. }