forward.frag 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* forward.frag -- Fragment shader used for forward 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. smooth in vec3 vPosition;
  16. smooth in vec2 vTexCoord;
  17. flat in vec3 vEmission;
  18. smooth in vec4 vColor;
  19. smooth in mat3 vTBN;
  20. in vec4 vPosLightSpace[NUM_FORWARD_LIGHTS];
  21. /* === Uniforms === */
  22. uniform sampler2D uAlbedoMap;
  23. uniform sampler2D uEmissionMap;
  24. uniform sampler2D uNormalMap;
  25. uniform sampler2D uOrmMap;
  26. uniform sampler2DArrayShadow uShadowDirTex;
  27. uniform sampler2DArrayShadow uShadowSpotTex;
  28. uniform samplerCubeArrayShadow uShadowOmniTex;
  29. uniform samplerCubeArray uIrradianceTex;
  30. uniform samplerCubeArray uPrefilterTex;
  31. uniform sampler2D uBrdfLutTex;
  32. uniform float uNormalScale;
  33. uniform float uOcclusion;
  34. uniform float uRoughness;
  35. uniform float uMetalness;
  36. uniform vec3 uViewPosition;
  37. #if defined(PROBE)
  38. uniform bool uProbeInterior;
  39. #endif // PROBE
  40. /* === Blocks === */
  41. #include "../include/blocks/light.glsl"
  42. #include "../include/blocks/shadow.glsl"
  43. #include "../include/blocks/env.glsl"
  44. /* === Fragments === */
  45. layout(location = 0) out vec4 FragColor;
  46. /* === User override === */
  47. #include "../include/user/scene.frag"
  48. /* === Main function === */
  49. void main()
  50. {
  51. /* Sample material maps */
  52. SceneFragment(vTexCoord, vTBN, 0.0);
  53. vec3 ORM = vec3(OCCLUSION, ROUGHNESS, METALNESS);
  54. mat3 TBN = mat3(TANGENT, BITANGENT, NORMAL);
  55. float dielectric = (1.0 - METALNESS);
  56. /* Compute F0 (reflectance at normal incidence) and diffuse coefficient */
  57. vec3 F0 = PBR_ComputeF0(METALNESS, 0.5, ALBEDO);
  58. vec3 kD = dielectric * ALBEDO;
  59. /* Sample normal and compute view direction vector */
  60. vec3 N = normalize(TBN * M_NormalScale(texture(uNormalMap, vTexCoord).rgb * 2.0 - 1.0, uNormalScale));
  61. if (!gl_FrontFacing) N = -N; // Flip for back facing triangles with double sided meshes
  62. vec3 V = normalize(uViewPosition - vPosition);
  63. /* Compute the dot product of the normal and view direction */
  64. float NdotV = dot(N, V);
  65. float cNdotV = max(NdotV, 1e-4); // Clamped to avoid division by zero
  66. /* Loop through all light sources accumulating diffuse and specular light */
  67. vec3 diffuse = vec3(0.0);
  68. vec3 specular = vec3(0.0);
  69. for (int i = 0; i < uNumLights; i++)
  70. {
  71. Light light = uLights[i];
  72. /* Compute light direction */
  73. vec3 L = vec3(0.0);
  74. if (light.type == LIGHT_DIR) L = -light.direction;
  75. else L = normalize(light.position - vPosition);
  76. /* Compute the dot product of the normal and light direction */
  77. float NdotL = dot(N, L);
  78. if (NdotL <= 0.0) continue;
  79. float cNdotL = min(NdotL, 1.0); // clamped NdotL
  80. /* Compute the halfway vector between the view and light directions */
  81. vec3 H = normalize(V + L);
  82. float LdotH = max(dot(L, H), 0.0);
  83. float cLdotH = min(LdotH, 1.0);
  84. float NdotH = max(dot(N, H), 0.0);
  85. float cNdotH = min(NdotH, 1.0);
  86. /* Compute light color energy */
  87. vec3 lightColE = light.color * light.energy;
  88. /* Compute diffuse lighting */
  89. vec3 diffLight = L_Diffuse(cLdotH, cNdotV, cNdotL, ROUGHNESS);
  90. diffLight *= lightColE * dielectric;
  91. /* Compute specular lighting */
  92. vec3 specLight = L_Specular(F0, cLdotH, cNdotH, cNdotV, cNdotL, ROUGHNESS);
  93. specLight *= lightColE * light.specular;
  94. /* Apply shadow factor if the light casts shadows */
  95. float shadow = 1.0;
  96. if (light.shadowLayer >= 0) {
  97. switch (light.type) {
  98. case LIGHT_DIR: shadow = S_SampleShadowDir(i, vPosLightSpace[i], cNdotL); break;
  99. case LIGHT_SPOT: shadow = S_SampleShadowSpot(i, vPosLightSpace[i], cNdotL); break;
  100. case LIGHT_OMNI: shadow = S_SampleShadowOmni(i, vPosition, cNdotL); break;
  101. }
  102. }
  103. /* Apply attenuation based on the distance from the light */
  104. if (light.type != LIGHT_DIR) {
  105. float dist = length(light.position - vPosition);
  106. float atten = 1.0 - clamp(dist / light.range, 0.0, 1.0);
  107. shadow *= atten * light.attenuation;
  108. }
  109. /* Apply spotlight effect if the light is a spotlight */
  110. if (light.type == LIGHT_SPOT) {
  111. float theta = dot(L, -light.direction);
  112. float epsilon = (light.innerCutOff - light.outerCutOff);
  113. shadow *= smoothstep(0.0, 1.0, (theta - light.outerCutOff) / epsilon);
  114. }
  115. /* Accumulate the diffuse and specular lighting contributions */
  116. diffuse += diffLight * shadow;
  117. specular += specLight * shadow;
  118. }
  119. /* Compute ambient */
  120. #if defined(PROBE)
  121. if (uProbeInterior) E_ComputeAmbientColor(diffuse, kD, OCCLUSION);
  122. else E_ComputeAmbientOnly(diffuse, specular, kD, ORM, F0, vPosition, N, V, cNdotV);
  123. #else
  124. E_ComputeAmbientAndProbes(diffuse, specular, kD, ORM, F0, vPosition, N, V, cNdotV);
  125. #endif
  126. /* Compute the final fragment color */
  127. FragColor = vec4(ALBEDO * diffuse + specular + EMISSION, ALPHA);
  128. }