summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/37-gpudrivenrendering/cs_gdr_occlude_props.sc
blob: 2648eb4d07567a9dd6ed8a6cb362d8e5e9736eb2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * 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) );

#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;
}