Compute shader: instance culling

finally i’ve got it !! :wink:

#version 460 core

layout (local_size_x = 1024,  local_size_y = 1, local_size_z = 1) in;


/* argument type buffered in GL_DRAW_INDIRECT_BUFFER */
struct DrawElementsIndirectCommand
{
	uint Count;
	uint InstanceCount;
	uint FirstIndex;
	uint BaseVertex;
	uint BaseInstance;
};


layout (std430, binding = 1) buffer MV_BSphere_Block {
	vec4 bspheres[];
};

layout (std430, binding = 2) buffer CMD_Block {
	DrawElementsIndirectCommand cmd[]; // the indirect buffer containing draw call parameters
};


layout (location = 0) uniform float FieldOfView = 0.0f;
layout (location = 1) uniform float AspectRatio = 0.0f;
layout (location = 2) uniform float ZNear = 0.0f;
layout (location = 3) uniform float ZFar = 0.0f;


void main()
{
	uint index = gl_GlobalInvocationID.x;
	if (index >= bspheres.length())
		return;
	if (index >= cmd.length())
		return;

	// invisible by default
	cmd[index].InstanceCount = 0;

	// bsphere position (in view space)
	vec3 position = bspheres[index].xyz;
	float radius = bspheres[index].w;

	// behind ZNear
	if ((position.z - radius ) > ZNear)
		return;

	// beyond ZFar
	if ((position.z + radius ) < ZFar)
		return;

	// bsphere is within the z-range of frustum ...

	float x0 = -position.z * tan(FieldOfView * AspectRatio / 2);
	float y0 = -position.z * tan(FieldOfView / 2);

	// upper/lower plane
	float dy = abs(position.y) - y0;
	float d1 = dy / cos(FieldOfView / 2);
	if (d1 > radius)
		return;

	// bsphere is within the z-range and y-range of frustum ...

	// left/right plane
	float dx = abs(position.x) - x0;
	float d2 = dx / cos(FieldOfView * AspectRatio / 2);
	if (d2 > radius)
		return;

	// visible
	cmd[index].InstanceCount = 1;
}

and the cpp part:

	glUseProgram(Program_Model_InstanceCulling);

	glUniform1f(0, camera.FieldOfView);
	glUniform1f(1, aspectratio);
	glUniform1f(2, -camera.ZNear);
	glUniform1f(3, -camera.ZFar);

	glDispatchCompute(1 + drawcount / 1024, 1, 1);

	//glUseProgram(0);

	glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

the frustum points to the negative z direction, the bounding spheres are transformed into view-space. there are “drawcount” elements in each SSBO.

thanks again for the links above, visualizing the problem makes it mch easier than thinking a hole in your brain ^^