lighting.frag 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* lighting.frag -- Fragment shader for applying direct lighting for deferred shading
  2. *
  3. * Copyright (c) 2025-2026 Le Juez Victor
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * For conditions of distribution and use, see accompanying LICENSE file.
  7. */
  8. #version 330 core
  9. /* === Extensions === */
  10. #extension GL_ARB_texture_cube_map_array : enable
  11. /* === Includes === */
  12. #include "../include/math.glsl"
  13. #include "../include/pbr.glsl"
  14. /* === Varyings === */
  15. noperspective in vec2 vTexCoord;
  16. /* === Uniforms === */
  17. uniform sampler2D uAlbedoTex;
  18. uniform sampler2D uNormalTex;
  19. uniform sampler2D uDepthTex;
  20. uniform sampler2D uOrmTex;
  21. uniform sampler2DArrayShadow uShadowDirTex;
  22. uniform sampler2DArrayShadow uShadowSpotTex;
  23. uniform samplerCubeArrayShadow uShadowOmniTex;
  24. /* === Blocks === */
  25. #include "../include/blocks/light.glsl"
  26. #include "../include/blocks/shadow.glsl"
  27. #include "../include/blocks/view.glsl"
  28. /* === Fragments === */
  29. layout(location = 0) out vec4 FragDiffuse;
  30. layout(location = 1) out vec4 FragSpecular;
  31. /* === Main === */
  32. void main()
  33. {
  34. /* Sample albedo and ORM texture and extract values */
  35. vec3 albedo = texelFetch(uAlbedoTex, ivec2(gl_FragCoord).xy, 0).rgb;
  36. vec3 orm = texelFetch(uOrmTex, ivec2(gl_FragCoord).xy, 0).rgb;
  37. float roughness = orm.g;
  38. float metalness = orm.b;
  39. /* Compute F0 (reflectance at normal incidence) based on the metallic factor */
  40. vec3 F0 = PBR_ComputeF0(metalness, 0.5, albedo);
  41. /* Get position and normal in world space */
  42. vec3 position = V_GetWorldPosition(uDepthTex, ivec2(gl_FragCoord.xy));
  43. vec3 N = V_GetWorldNormal(uNormalTex, ivec2(gl_FragCoord.xy));
  44. /* Compute view direction and the dot product of the normal and view direction */
  45. vec3 V = normalize(uView.position - position);
  46. float NdotV = dot(N, V);
  47. float cNdotV = max(NdotV, 1e-4); // Clamped to avoid division by zero
  48. /* Compute light direction and the dot product of the normal and light direction */
  49. vec3 L = (uLight.type == LIGHT_DIR) ? -uLight.direction : normalize(uLight.position - position);
  50. float NdotL = max(dot(N, L), 0.0);
  51. float cNdotL = min(NdotL, 1.0); // Clamped to avoid division by zero
  52. /* Compute the halfway vector between the view and light directions */
  53. vec3 H = normalize(V + L);
  54. float LdotH = max(dot(L, H), 0.0);
  55. float cLdotH = min(LdotH, 1.0);
  56. float NdotH = max(dot(N, H), 0.0);
  57. float cNdotH = min(NdotH, 1.0);
  58. /* Compute light color energy */
  59. vec3 lightColE = uLight.color * uLight.energy;
  60. /* Compute diffuse lighting */
  61. vec3 diffuse = L_Diffuse(cLdotH, cNdotV, cNdotL, roughness);
  62. diffuse *= albedo * lightColE * (1.0 - metalness);
  63. /* Compute specular lighting */
  64. vec3 specular = L_Specular(F0, cLdotH, cNdotH, cNdotV, cNdotL, roughness);
  65. specular *= lightColE * uLight.specular;
  66. /* Apply shadow factor if the light casts shadows */
  67. float shadow = 1.0;
  68. if (uLight.shadowLayer >= 0) {
  69. switch (uLight.type) {
  70. case LIGHT_DIR: shadow = S_SampleShadowDir(uLight.viewProj * vec4(position, 1.0), cNdotL); break;
  71. case LIGHT_SPOT: shadow = S_SampleShadowSpot(uLight.viewProj * vec4(position, 1.0), cNdotL); break;
  72. case LIGHT_OMNI: shadow = S_SampleShadowOmni(position, cNdotL); break;
  73. }
  74. }
  75. /* Apply attenuation based on the distance from the light */
  76. if (uLight.type != LIGHT_DIR)
  77. {
  78. float dist = length(uLight.position - position);
  79. float atten = 1.0 - clamp(dist / uLight.range, 0.0, 1.0);
  80. shadow *= atten * uLight.attenuation;
  81. }
  82. /* Apply spotlight effect if the light is a spotlight */
  83. if (uLight.type == LIGHT_SPOT)
  84. {
  85. float theta = dot(L, -uLight.direction);
  86. float epsilon = (uLight.innerCutOff - uLight.outerCutOff);
  87. shadow *= smoothstep(0.0, 1.0, (theta - uLight.outerCutOff) / epsilon);
  88. }
  89. /* Compute final lighting contribution */
  90. FragDiffuse = vec4(diffuse * shadow, 1.0);
  91. FragSpecular = vec4(specular * shadow, 1.0);
  92. }