#version 420 core
#ifdef GL_VERTEX_SHADER
in vec4 attrib_row1; // xyz=axisX, w=translationX
in vec4 attrib_row2; // xyz=axisY, w=translationY
in vec4 attrib_row3; // xyz=axisZ, w=translationZ
in vec4 attrib_bsphere; // bounding sphere xyz=centre, w=radius
out vec4 vsRow1;
out vec4 vsRow2;
out vec4 vsRow3;
flat out int vsVisible;
uniform vec4 uni_frustum[6]; // the 6 world space frustum planes
void main() {
vsRow1 = attrib_row1;
vsRow2 = attrib_row2;
vsRow3 = attrib_row3;
vsVisible = 1;
// is instance in frustum?
for (int i=0; i<6; ++i) {
float d = dot(uni_frustum[i], vec4(attrib_bsphere.xyz, 1.0));
if (d <= -attrib_bsphere.w) {
vsVisible = 0;
break;
}
}
}
#endif
#ifdef GL_GEOMETRY_SHADER
layout(points) in;
layout(points, max_vertices = 1) out;
uniform vec3 uni_camPos; // xyz=world space camera position
uniform vec4 uni_lodDist; // lod distances for x=lod0, y=lod1, z=lod2, w=lod3
in vec4 vsRow1[1];
in vec4 vsRow2[1];
in vec4 vsRow3[1];
flat in int vsVisible[1];
layout(stream=0) out vec4 gsOut0Row1;
layout(stream=0) out vec4 gsOut0Row2;
layout(stream=0) out vec4 gsOut0Row3;
layout(stream=1) out vec4 gsOut1Row1;
layout(stream=1) out vec4 gsOut1Row2;
layout(stream=1) out vec4 gsOut1Row3;
layout(stream=2) out vec4 gsOut2Row1;
layout(stream=2) out vec4 gsOut2Row2;
layout(stream=2) out vec4 gsOut2Row3;
layout(stream=3) out vec4 gsOut3Row1;
layout(stream=3) out vec4 gsOut3Row2;
layout(stream=3) out vec4 gsOut3Row3;
layout(binding = 0, offset = 4) uniform atomic_uint LodCount0;
layout(binding = 0, offset = 24) uniform atomic_uint LodCount1;
layout(binding = 0, offset = 44) uniform atomic_uint LodCount2;
layout(binding = 0, offset = 64) uniform atomic_uint LodCount3;
void main() {
if (vsVisible[0]==1) {
float dist = distance(vec3(vsRow1[0].w, vsRow2[0].w, vsRow3[0].w), uni_camPos);
if (dist < uni_lodDist.x) {
gsOut0Row1 = vsRow1[0];
gsOut0Row2 = vsRow2[0];
gsOut0Row3 = vsRow3[0];
atomicCounterIncrement(LodCount0);
EmitStreamVertex(0);
}
else if (dist < uni_lodDist.y) {
gsOut1Row1 = vsRow1[0];
gsOut1Row2 = vsRow2[0];
gsOut1Row3 = vsRow3[0];
atomicCounterIncrement(LodCount1);
EmitStreamVertex(1);
}
else if (dist < uni_lodDist.z) {
gsOut2Row1 = vsRow1[0];
gsOut2Row2 = vsRow2[0];
gsOut2Row3 = vsRow3[0];
atomicCounterIncrement(LodCount2);
EmitStreamVertex(2);
}
else if (dist < uni_lodDist.w)
{
gsOut3Row1 = vsRow1[0];
gsOut3Row2 = vsRow2[0];
gsOut3Row3 = vsRow3[0];
atomicCounterIncrement(LodCount3);
EmitStreamVertex(3);
}
}
}
#endif