bgfx/examples/37-gpudrivenrendering/cs_gdr_occlude_props.sc

116 lines
3.1 KiB
Python

/*
* Copyright 2018 Kostas Anagnostou. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#include "bgfx_compute.sh"
SAMPLER2D(s_texOcclusionDepth, 0);
BUFFER_RO(instanceDataIn, vec4, 1);
BUFFER_RW(drawcallInstanceCount, uint, 2);
BUFFER_WR(instancePredicates, bool, 3);
uniform vec4 u_inputRTSize;
uniform vec4 u_cullingConfig;
NUM_THREADS(64, 1, 1)
void main()
{
bool predicate = false;
//make sure that we not processing more instances than available
if (gl_GlobalInvocationID.x < uint(u_cullingConfig.x) )
{
//get the bounding box for this instance
vec4 bboxMin = instanceDataIn[2 * gl_GlobalInvocationID.x] ;
vec3 bboxMax = instanceDataIn[2 * gl_GlobalInvocationID.x + 1].xyz;
int drawcallID = int(bboxMin.w);
//Adapted from http://blog.selfshadow.com/publications/practical-visibility/
vec3 bboxSize = bboxMax.xyz - bboxMin.xyz;
vec3 boxCorners[] = {
bboxMin.xyz,
bboxMin.xyz + vec3(bboxSize.x,0,0),
bboxMin.xyz + vec3(0, bboxSize.y,0),
bboxMin.xyz + vec3(0, 0, bboxSize.z),
bboxMin.xyz + vec3(bboxSize.xy,0),
bboxMin.xyz + vec3(0, bboxSize.yz),
bboxMin.xyz + vec3(bboxSize.x, 0, bboxSize.z),
bboxMin.xyz + bboxSize.xyz
};
float minZ = 1.0;
vec2 minXY = vec2(1.0, 1.0);
vec2 maxXY = vec2(0.0, 0.0);
UNROLL
for (int i = 0; i < 8; i++)
{
//transform World space aaBox to NDC
vec4 clipPos = mul( u_viewProj, vec4(boxCorners[i], 1) );
#if BGFX_SHADER_LANGUAGE_GLSL
clipPos.z = 0.5 * ( clipPos.z + clipPos.w );
#endif
clipPos.z = max(clipPos.z, 0);
clipPos.xyz = clipPos.xyz / clipPos.w;
clipPos.xy = clamp(clipPos.xy, -1, 1);
clipPos.xy = clipPos.xy * vec2(0.5, -0.5) + vec2(0.5, 0.5);
minXY = min(clipPos.xy, minXY);
maxXY = max(clipPos.xy, maxXY);
minZ = saturate(min(minZ, clipPos.z));
}
vec4 boxUVs = vec4(minXY, maxXY);
// Calculate hi-Z buffer mip
ivec2 size = ivec2( (maxXY - minXY) * u_inputRTSize.xy);
float mip = ceil(log2(max(size.x, size.y)));
mip = clamp(mip, 0, u_cullingConfig.z);
// Texel footprint for the lower (finer-grained) level
float level_lower = max(mip - 1, 0);
vec2 scale = vec2_splat(exp2(-level_lower) );
vec2 a = floor(boxUVs.xy*scale);
vec2 b = ceil(boxUVs.zw*scale);
vec2 dims = b - a;
// Use the lower level if we only touch <= 2 texels in both dimensions
if (dims.x <= 2 && dims.y <= 2)
mip = level_lower;
#if BGFX_SHADER_LANGUAGE_GLSL
boxUVs.y = 1.0 - boxUVs.y;
boxUVs.w = 1.0 - boxUVs.w;
#endif
//load depths from high z buffer
vec4 depth =
{
texture2DLod(s_texOcclusionDepth, boxUVs.xy, mip).x,
texture2DLod(s_texOcclusionDepth, boxUVs.zy, mip).x,
texture2DLod(s_texOcclusionDepth, boxUVs.xw, mip).x,
texture2DLod(s_texOcclusionDepth, boxUVs.zw, mip).x,
};
//find the max depth
float maxDepth = max( max(depth.x, depth.y), max(depth.z, depth.w) );
if ( minZ <= maxDepth )
{
predicate = true;
//increase instance count for this particular prop type
atomicAdd(drawcallInstanceCount[ drawcallID ], 1);
}
}
instancePredicates[gl_GlobalInvocationID.x] = predicate;
}