summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/41-tess/cs_terrain_lod.sc
blob: eb6b24f287aeb82de2ca9f1b422a834b92bcfba8 (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
////////////////////////////////////////////////////////////////////////////////
// Implicit Subdivision Shader for Terrain Rendering
//

#include "terrain_common.sh"
#include "fcull.sh"

BUFFER_RO(u_SubdBufferIn, uint, 8);
BUFFER_RW(u_CulledSubdBuffer, uint, 2);
BUFFER_RO(u_VertexBuffer, vec4, 6);
BUFFER_RO(u_IndexBuffer, uint, 7);

/**
 * Compute LoD Shader
 *
 * This compute shader is responsible for updating the subdivision
 * buffer and visible buffer that will be sent to the rasterizer.
 */

NUM_THREADS(COMPUTE_THREAD_COUNT, 1u, 1u)
void main()
{
	// get threadID (each key is associated to a thread)
	uint threadID = gl_GlobalInvocationID.x;

	if (threadID >= u_AtomicCounterBuffer[2])
	{
		return;
	}

	// get coarse triangle associated to the key
	uint primID = u_SubdBufferIn[threadID*2];

	vec4 v_in[3];
	v_in[0] = u_VertexBuffer[u_IndexBuffer[primID * 3    ]];
	v_in[1] = u_VertexBuffer[u_IndexBuffer[primID * 3 + 1]];
	v_in[2] = u_VertexBuffer[u_IndexBuffer[primID * 3 + 2]];

	// compute distance-based LOD
	uint key = u_SubdBufferIn[threadID*2+1];

	vec4 v[3];
	vec4 vp[3];

	subd(key, v_in, v, vp);

	uint targetLod; uint parentLod;

	if (u_freeze == 0)
	{
		targetLod = uint(computeLod(v));
		parentLod = uint(computeLod(vp));
	}
	else
	{
		targetLod = parentLod = findMSB_(key);
	}

	updateSubdBuffer(primID, key, targetLod, parentLod);

	// Cull invisible nodes
	mat4 mvp = u_modelViewProj;
	vec4 bmin = min(min(v[0], v[1]), v[2]);
	vec4 bmax = max(max(v[0], v[1]), v[2]);

	// account for displacement in bound computations
	bmin.z = 0;
	bmax.z = u_DmapFactor;

	// update CulledSubdBuffer
	if (u_cull == 0
	||  frustumCullingTest(mvp, bmin.xyz, bmax.xyz) )
	{
		// write key
		uint idx = 0;
		atomicFetchAndAdd(u_AtomicCounterBuffer[1], 2, idx);
		u_CulledSubdBuffer[idx] = primID;
		u_CulledSubdBuffer[idx+1] = key;
	}
}