You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.3 KiB

пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
  1. #version 330
  2. in vec3 fragPosition;
  3. in vec2 fragTexCoord;
  4. in vec4 fragColor;
  5. in vec3 fragNormal;
  6. out vec4 finalColor;
  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 int lightsCount;
  30. uniform Light lights[maxLights];
  31. vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s)
  32. {
  33. vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
  34. vec3 surfaceToLight = l.position - surfacePos;
  35. // Diffuse shading
  36. float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);
  37. float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;
  38. // Specular shading
  39. float spec = 0.0;
  40. if (diff > 0.0)
  41. {
  42. vec3 h = normalize(-l.direction + v);
  43. spec = pow(dot(n, h), 3 + glossiness)*s;
  44. }
  45. return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
  46. }
  47. vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)
  48. {
  49. vec3 lightDir = normalize(-l.direction);
  50. // Diffuse shading
  51. float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
  52. // Specular shading
  53. float spec = 0.0;
  54. if (diff > 0.0)
  55. {
  56. vec3 h = normalize(lightDir + v);
  57. spec = pow(dot(n, h), 3 + glossiness)*s;
  58. }
  59. // Combine results
  60. return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);
  61. }
  62. vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)
  63. {
  64. vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
  65. vec3 lightToSurface = normalize(surfacePos - l.position);
  66. vec3 lightDir = normalize(-l.direction);
  67. // Diffuse shading
  68. float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
  69. // Spot attenuation
  70. float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);
  71. attenuation = dot(lightToSurface, -lightDir);
  72. float lightToSurfaceAngle = degrees(acos(attenuation));
  73. if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;
  74. float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;
  75. // Combine diffuse and attenuation
  76. float diffAttenuation = diff*attenuation;
  77. // Specular shading
  78. float spec = 0.0;
  79. if (diffAttenuation > 0.0)
  80. {
  81. vec3 h = normalize(lightDir + v);
  82. spec = pow(dot(n, h), 3 + glossiness)*s;
  83. }
  84. return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
  85. }
  86. void main()
  87. {
  88. // Calculate fragment normal in screen space
  89. // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale)
  90. mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
  91. vec3 normal = normalize(normalMatrix*fragNormal);
  92. // Normalize normal and view direction vectors
  93. vec3 n = normalize(normal);
  94. vec3 v = normalize(viewDir);
  95. // Calculate diffuse texture color fetching
  96. vec4 texelColor = texture(texture0, fragTexCoord);
  97. vec3 lighting = colAmbient.rgb;
  98. // Calculate normal texture color fetching or set to maximum normal value by default
  99. if (useNormal == 1)
  100. {
  101. n *= texture(texture1, fragTexCoord).rgb;
  102. n = normalize(n);
  103. }
  104. // Calculate specular texture color fetching or set to maximum specular value by default
  105. float spec = 1.0;
  106. if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);
  107. for (int i = 0; i < lightsCount; i++)
  108. {
  109. // Check if light is enabled
  110. if (lights[i].enabled == 1)
  111. {
  112. // Calculate lighting based on light type
  113. switch (lights[i].type)
  114. {
  115. case 0: lighting += CalcPointLight(lights[i], n, v, spec); break;
  116. case 1: lighting += CalcDirectionalLight(lights[i], n, v, spec); break;
  117. case 2: lighting += CalcSpotLight(lights[i], n, v, spec); break;
  118. default: break;
  119. }
  120. }
  121. }
  122. // Calculate final fragment color
  123. finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a);
  124. }