// Copyright (c) 2023 Xiamen Yaji Software Co., Ltd. CCEffect %{ techniques: - name: opaque passes: - compute: cluster-main pass: cluster-build-cs }% CCProgram cluster-main %{ #include precision highp float; #define LOCAL_SIZE_X 16u #define LOCAL_SIZE_Y 8u #define LOCAL_SIZE_Z 1u layout (local_size_x = LOCAL_SIZE_X, local_size_y = LOCAL_SIZE_Y, local_size_z = LOCAL_SIZE_Z) in; #pragma rate CCConst pass layout(std140) uniform CCConst { vec4 cc_nearFar; vec4 cc_viewPort; vec4 cc_workGroup; mat4 cc_matView; mat4 cc_matProjInv; }; #pragma rate b_clustersBuffer pass layout(std430) buffer b_clustersBuffer { vec4 b_clusters[]; }; vec4 screen2Eye(vec4 coord) { vec3 ndc = vec3( 2.0 * (coord.x - cc_viewPort.x) / cc_viewPort.z - 1.0, 2.0 * (coord.y - cc_viewPort.y) / cc_viewPort.w - 1.0, 2.0 * coord.z - 1.0); CC_HANDLE_SAMPLE_NDC_FLIP_STATIC(ndc.y); vec4 eye = ((cc_matProjInv) * (vec4(ndc, 1.0))); eye = eye / eye.w; return eye; } void main () { uint clusterIndex = gl_GlobalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + gl_GlobalInvocationID.y * gl_WorkGroupSize.x + gl_GlobalInvocationID.x; float clusterSizeX = ceil(cc_viewPort.z / cc_workGroup.x); float clusterSizeY = ceil(cc_viewPort.w / cc_workGroup.y); vec4 minScreen = vec4(vec2(gl_GlobalInvocationID.xy) * vec2(clusterSizeX, clusterSizeY), 1.0, 1.0); vec4 maxScreen = vec4(vec2(gl_GlobalInvocationID.xy + uvec2(1, 1)) * vec2(clusterSizeX, clusterSizeY), 1.0, 1.0); vec3 minEye = screen2Eye(minScreen).xyz; vec3 maxEye = screen2Eye(maxScreen).xyz; float clusterNear = -cc_nearFar.x * pow(cc_nearFar.y / cc_nearFar.x, float(gl_GlobalInvocationID.z) / cc_workGroup.z); float clusterFar = -cc_nearFar.x * pow(cc_nearFar.y / cc_nearFar.x, float(gl_GlobalInvocationID.z + 1u) / cc_workGroup.z); vec3 minNear = minEye * clusterNear / minEye.z; vec3 minFar = minEye * clusterFar / minEye.z; vec3 maxNear = maxEye * clusterNear / maxEye.z; vec3 maxFar = maxEye * clusterFar / maxEye.z; vec3 minBounds = min(min(minNear, minFar), min(maxNear, maxFar)); vec3 maxBounds = max(max(minNear, minFar), max(maxNear, maxFar)); b_clusters[2u * clusterIndex + 0u] = vec4(minBounds, 1.0); b_clusters[2u * clusterIndex + 1u] = vec4(maxBounds, 1.0); } }%