shading-cluster-additive.chunk 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
  2. #pragma define CLUSTERS_X 16u
  3. #pragma define CLUSTERS_Y 8u
  4. #pragma define CLUSTERS_Z 24u
  5. #pragma define MAX_LIGHTS_PER_CLUSTER 200u
  6. #pragma rate b_ccLightsBuffer pass
  7. #pragma glBinding(0)
  8. layout(std430) readonly buffer b_ccLightsBuffer { vec4 b_ccLights[]; };
  9. #pragma rate b_clusterLightIndicesBuffer pass
  10. #pragma glBinding(1)
  11. layout(std430) readonly buffer b_clusterLightIndicesBuffer { uint b_clusterLightIndices[]; };
  12. #pragma rate b_clusterLightGridBuffer pass
  13. #pragma glBinding(2)
  14. layout(std430) readonly buffer b_clusterLightGridBuffer { uvec4 b_clusterLightGrid[]; };
  15. struct CCLight
  16. {
  17. vec4 cc_lightPos;
  18. vec4 cc_lightColor;
  19. vec4 cc_lightSizeRangeAngle;
  20. vec4 cc_lightDir;
  21. vec4 cc_lightBoundingSizeVS;
  22. };
  23. struct Cluster
  24. {
  25. vec3 minBounds;
  26. vec3 maxBounds;
  27. };
  28. struct LightGrid
  29. {
  30. uint offset;
  31. uint ccLights;
  32. };
  33. float screen2EyeDepth(float depth, float near, float far)
  34. {
  35. float ndc = 2.0 * depth - 1.0;
  36. float eye = 2.0 * far * near / (far + near + ndc * (near - far));
  37. return eye;
  38. }
  39. CCLight getCCLight(uint i)
  40. {
  41. CCLight light;
  42. light.cc_lightPos = b_ccLights[5u * i + 0u];
  43. light.cc_lightColor = b_ccLights[5u * i + 1u];
  44. light.cc_lightSizeRangeAngle = b_ccLights[5u * i + 2u];
  45. light.cc_lightDir = b_ccLights[5u * i + 3u];
  46. light.cc_lightBoundingSizeVS = b_ccLights[5u * i + 4u];
  47. return light;
  48. }
  49. LightGrid getLightGrid(uint cluster)
  50. {
  51. uvec4 gridvec = b_clusterLightGrid[cluster];
  52. LightGrid grid;
  53. grid.offset = gridvec.x;
  54. grid.ccLights = gridvec.y;
  55. return grid;
  56. }
  57. uint getGridLightIndex(uint start, uint offset)
  58. {
  59. return b_clusterLightIndices[start + offset];
  60. }
  61. uint getClusterZIndex(vec4 worldPos)
  62. {
  63. float scale = float(CLUSTERS_Z) / log(cc_nearFar.y / cc_nearFar.x);
  64. float bias = -(float(CLUSTERS_Z) * log(cc_nearFar.x) / log(cc_nearFar.y / cc_nearFar.x));
  65. float eyeDepth = -(cc_matView * worldPos).z;
  66. uint zIndex = uint(max(log(eyeDepth) * scale + bias, 0.0));
  67. return zIndex;
  68. }
  69. uint getClusterIndex(vec4 fragCoord, vec4 worldPos)
  70. {
  71. uint zIndex = getClusterZIndex(worldPos);
  72. float clusterSizeX = ceil(cc_viewPort.z / float(CLUSTERS_X));
  73. float clusterSizeY = ceil(cc_viewPort.w / float(CLUSTERS_Y));
  74. uvec3 indices = uvec3(uvec2(fragCoord.xy / vec2(clusterSizeX, clusterSizeY)), zIndex);
  75. uint cluster = (CLUSTERS_X * CLUSTERS_Y) * indices.z + CLUSTERS_X * indices.y + indices.x;
  76. return cluster;
  77. }
  78. vec4 CCClusterShadingAdditive (StandardSurface s, vec4 shadowPos) {
  79. // Calculate diffuse & specular
  80. vec3 diffuse = s.albedo.rgb * (1.0 - s.metallic);
  81. vec3 specular = mix(vec3(0.04), s.albedo.rgb, s.metallic);
  82. vec3 diffuseContrib = diffuse / PI;
  83. vec3 position;
  84. HIGHP_VALUE_FROM_STRUCT_DEFINED(position, s.position);
  85. vec3 N = normalize(s.normal);
  86. vec3 V = normalize(cc_cameraPos.xyz - position);
  87. float NV = max(abs(dot(N, V)), 0.001);
  88. specular = BRDFApprox(specular, s.roughness, NV);
  89. vec3 finalColor = vec3(0.0);
  90. uint cluster = getClusterIndex(gl_FragCoord, vec4(position, 1.0));
  91. LightGrid grid = getLightGrid(cluster);
  92. uint numLights = grid.ccLights;
  93. for (uint i = 0u; i < MAX_LIGHTS_PER_CLUSTER; i++) {
  94. if (i >= numLights) break;
  95. uint lightIndex = getGridLightIndex(grid.offset, i);
  96. CCLight light = getCCLight(lightIndex);
  97. vec3 SLU = light.cc_lightPos.xyz - position;
  98. vec3 SL = normalize(SLU);
  99. vec3 SH = normalize(SL + V);
  100. float SNL = max(dot(N, SL), 0.001);
  101. float SNH = max(dot(N, SH), 0.0);
  102. float distSqr = dot(SLU, SLU);
  103. float litRadius = light.cc_lightSizeRangeAngle.x;
  104. float litRadiusSqr = litRadius * litRadius;
  105. float illum = PI * (litRadiusSqr / max(litRadiusSqr , distSqr));
  106. float attRadiusSqrInv = 1.0 / max(light.cc_lightSizeRangeAngle.y, 0.01);
  107. attRadiusSqrInv *= attRadiusSqrInv;
  108. float att = GetDistAtt(distSqr, attRadiusSqrInv);
  109. vec3 lspec = specular * CalcSpecular(s.roughness, SNH, SH, N);
  110. if (IS_SPOT_LIGHT(light.cc_lightPos.w)) {
  111. float cosInner = max(dot(-light.cc_lightDir.xyz, SL), 0.01);
  112. float cosOuter = light.cc_lightSizeRangeAngle.z;
  113. float litAngleScale = 1.0 / max(0.001, cosInner - cosOuter);
  114. float litAngleOffset = -cosOuter * litAngleScale;
  115. att *= GetAngleAtt(SL, -light.cc_lightDir.xyz, litAngleScale, litAngleOffset);
  116. }
  117. vec3 lightColor = light.cc_lightColor.rgb;
  118. float shadow = 1.0;
  119. #if CC_RECEIVE_SHADOW && CC_SHADOW_TYPE == CC_SHADOW_MAP
  120. if (IS_SPOT_LIGHT(light.cc_lightPos.w) && light.cc_lightSizeRangeAngle.w > 0.0) {
  121. shadow = CCSpotShadowFactorBase(shadowPos, position, s.shadowBias);
  122. }
  123. #endif
  124. lightColor *= shadow;
  125. finalColor += SNL * lightColor * light.cc_lightColor.w * illum * att * (diffuseContrib + lspec);
  126. }
  127. return vec4(finalColor, 0.0);
  128. }