LumixEngine/data/pipelines/instancing.shd

214 lines
5.4 KiB
Text
Raw Normal View History

2022-01-21 17:40:00 +01:00
include "pipelines/common.glsl"
compute_shader [[
struct Indirect {
uint vertex_count;
uint instance_count;
uint first_index;
uint base_vertex;
uint base_instance;
};
struct OutputData {
2022-01-23 23:09:15 +01:00
vec4 rot_lod;
2022-01-21 17:40:00 +01:00
vec4 pos_scale;
};
struct InputData {
vec4 rot_lod;
vec4 pos_scale;
};
layout(local_size_x = 256, local_size_y = 1) in;
#ifdef UPDATE_LODS
layout(binding = 0, std430) buffer InData {
InputData b_input[];
};
#else
layout(binding = 0, std430) readonly buffer InData {
InputData b_input[];
};
#endif
2022-01-22 21:49:44 +01:00
layout(binding = 1, std430) buffer OutData {
2022-01-21 17:40:00 +01:00
uvec4 b_batch_offset;
uvec4 b_lod_count;
uvec4 b_lod_offset;
OutputData b_output[];
};
layout(binding = 2, std430) writeonly buffer OutData2 {
Indirect b_indirect[];
};
layout(std140, binding = 4) uniform UniformData {
vec4 u_camera_offset;
vec4 u_lod_distances;
ivec4 u_lod_indices;
uint u_indirect_offset;
float u_radius;
2022-01-27 23:22:49 +01:00
vec2 padding;
2022-01-21 17:40:00 +01:00
vec4 u_camera_planes[6];
uvec4 u_indices_count[32];
};
2022-01-27 23:22:49 +01:00
layout(std140, binding = 5) uniform UniformData2 {
uint u_from_instance;
uint u_instance_count;
};
2022-01-21 17:40:00 +01:00
shared uint group_count[5];
uint getLOD(uint id) {
vec3 p = b_input[id].pos_scale.xyz + u_camera_offset.xyz;
float d = dot(p, p);
if (d > u_lod_distances.w) return 4;
else if (d > u_lod_distances.z) return 3;
else if (d > u_lod_distances.y) return 2;
else if (d > u_lod_distances.x) return 1;
return 0;
}
bool cull(uint id) {
float scale = b_input[id].pos_scale.w;
vec4 cullp = vec4(b_input[id].pos_scale.xyz + u_camera_offset.xyz, 1);
for (int i = 0; i < 6; ++i) {
if (dot(u_camera_planes[i], cullp) < -u_radius * scale) {
return false;
}
}
return true;
}
void main() {
uint id = gl_GlobalInvocationID.y * gl_WorkGroupSize.x + gl_GlobalInvocationID.x;
#ifdef PASS0
if (id == 0) {
2022-01-22 21:49:44 +01:00
b_batch_offset.x += uint(dot(b_lod_count, vec4(1)));
2022-01-21 17:40:00 +01:00
b_lod_offset = uvec4(b_batch_offset.x);
b_lod_count = uvec4(0);
}
#elif defined PASS1
bool master = gl_LocalInvocationID.x == 0;
if (master) {
group_count[0] = 0;
group_count[1] = 0;
group_count[2] = 0;
group_count[3] = 0;
}
groupMemoryBarrier();
barrier();
2022-01-27 23:22:49 +01:00
if (id < u_instance_count) {
id += u_from_instance;
2022-01-21 17:40:00 +01:00
#ifdef UPDATE_LODS
float dst_lod = getLOD(id);
float src_lod = b_input[id].rot_lod.w;
float d = dst_lod - src_lod;
float td = Global.frame_time_delta * 2;
float lod = abs(d) < td ? dst_lod : src_lod + td * sign(d);
b_input[id].rot_lod.w = lod;
#else
float lod = b_input[id].rot_lod.w;
#endif
2022-01-27 23:22:49 +01:00
if (lod <= 3 && cull(id)) {
2022-01-21 17:40:00 +01:00
float t = fract(lod);
uint ilod = uint(lod);
atomicAdd(group_count[ilod], 1);
if (t > 0.01) {
atomicAdd(group_count[ilod + 1], 1);
}
}
}
groupMemoryBarrier();
barrier();
if (master) {
atomicAdd(b_lod_count.x, group_count[0]);
atomicAdd(b_lod_count.y, group_count[1]);
atomicAdd(b_lod_count.z, group_count[2]);
atomicAdd(b_lod_count.w, group_count[3]);
atomicAdd(b_lod_offset.y, group_count[0]);
atomicAdd(b_lod_offset.z, group_count[1] + group_count[0]);
atomicAdd(b_lod_offset.w, group_count[2] + group_count[1] + group_count[0]);
}
#elif defined PASS2
int iid = int(id);
if (iid > u_lod_indices.w) return;
if (iid <= u_lod_indices.x) {
b_indirect[id + u_indirect_offset].instance_count = b_lod_count.x;
b_indirect[id + u_indirect_offset].base_instance = b_lod_offset.x;
}
else if (iid <= u_lod_indices.y) {
b_indirect[id + u_indirect_offset].instance_count = b_lod_count.y;
b_indirect[id + u_indirect_offset].base_instance = b_lod_offset.y;
}
else if (iid <= u_lod_indices.z) {
b_indirect[id + u_indirect_offset].instance_count = b_lod_count.z;
b_indirect[id + u_indirect_offset].base_instance = b_lod_offset.z;
}
else {
b_indirect[id + u_indirect_offset].instance_count = b_lod_count.w;
b_indirect[id + u_indirect_offset].base_instance = b_lod_offset.w;
}
b_indirect[id + u_indirect_offset].base_vertex = 0;
b_indirect[id + u_indirect_offset].first_index = 0;
b_indirect[id + u_indirect_offset].vertex_count = u_indices_count[id].x;
#elif defined PASS3
2022-01-27 23:22:49 +01:00
if (id >= u_instance_count) return;
2022-01-21 17:40:00 +01:00
2022-01-27 23:22:49 +01:00
id += u_from_instance;
2022-01-21 17:40:00 +01:00
InputData inp = b_input[id];
float lod = inp.rot_lod.w;
uint idx;
2022-01-27 23:22:49 +01:00
if (lod > 3 || !cull(id)) return;
2022-01-21 17:40:00 +01:00
float t = fract(lod);
uint ilod = uint(lod);
if (ilod == 0) {
idx = atomicAdd(b_lod_offset.x, 1);
}
else if (ilod == 1) {
idx = atomicAdd(b_lod_offset.y, 1);
}
else if (ilod == 2) {
idx = atomicAdd(b_lod_offset.z, 1);
}
else if (ilod == 3) {
idx = atomicAdd(b_lod_offset.w, 1);
}
else return;
2022-01-23 23:09:15 +01:00
b_output[idx].rot_lod.xyz = inp.rot_lod.xyz;
b_output[idx].rot_lod.w = t;
2022-01-21 17:40:00 +01:00
b_output[idx].pos_scale = inp.pos_scale + vec4(u_camera_offset.xyz, 0);
if (t > 0.01) {
if (ilod == 0) {
idx = atomicAdd(b_lod_offset.y, 1);
}
else if (ilod == 1) {
idx = atomicAdd(b_lod_offset.z, 1);
}
else if (ilod == 2) {
idx = atomicAdd(b_lod_offset.w, 1);
}
2022-01-23 23:09:15 +01:00
b_output[idx].rot_lod.xyz = inp.rot_lod.xyz;
b_output[idx].rot_lod.w = t - 1;
2022-01-21 17:40:00 +01:00
b_output[idx].pos_scale = inp.pos_scale + vec4(u_camera_offset.xyz, 0);
}
2022-01-27 23:22:49 +01:00
#elif defined UPDATE_LODS
if (id < u_instance_count) {
id += u_from_instance;
2022-01-31 23:07:10 +01:00
b_input[id].rot_lod.w = getLOD(id);
2022-01-27 23:22:49 +01:00
}
2022-01-21 17:40:00 +01:00
#endif
}
]]