109 lines
2.9 KiB
Python
109 lines
2.9 KiB
Python
/*
|
|
* Copyright 2018 Kostas Anagnostou. All rights reserved.
|
|
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
|
|
*/
|
|
|
|
#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) );
|
|
|
|
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;
|
|
|
|
//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;
|
|
}
|