Skip to content

Commit

Permalink
Merge pull request #127 from Themaister/hiz
Browse files Browse the repository at this point in the history
Sketch out HiZ 2-phase occlusion culling system.
  • Loading branch information
Themaister authored Dec 30, 2023
2 parents 53cd3a0 + ac965b3 commit d87ea7c
Show file tree
Hide file tree
Showing 17 changed files with 1,127 additions and 188 deletions.
83 changes: 83 additions & 0 deletions assets/shaders/inc/meshlet_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,32 @@ layout(set = MESHLET_RENDER_DESCRIPTOR_SET, binding = MESHLET_RENDER_TRANSFORM_B
mat4 data[];
} transforms;

#ifdef MESHLET_RENDER_HIZ_BINDING
layout(set = MESHLET_RENDER_DESCRIPTOR_SET, binding = MESHLET_RENDER_HIZ_BINDING)
uniform texture2D uHiZDepth;
#endif

layout(set = MESHLET_RENDER_DESCRIPTOR_SET, binding = MESHLET_RENDER_FRUSTUM_BINDING, std140) uniform Frustum
{
vec4 planes[6];
mat4 view;
vec4 viewport_scale_bias;
ivec2 hiz_resolution;
int hiz_max_lod;
} frustum;

layout(set = MESHLET_RENDER_DESCRIPTOR_SET, binding = MESHLET_RENDER_TASKS_BINDING, std430) readonly buffer Tasks
{
TaskInfo data[];
} task_info;

#ifdef MESHLET_RENDER_OCCLUDER_BINDING
layout(set = MESHLET_RENDER_DESCRIPTOR_SET, binding = MESHLET_RENDER_OCCLUDER_BINDING, std430) buffer OccluderState
{
uint data[];
} occluders;
#endif

bool frustum_cull(vec3 lo, vec3 hi)
{
bool ret = true;
Expand All @@ -66,6 +82,18 @@ bool frustum_cull(vec3 lo, vec3 hi)
return ret;
}

vec2 project_sphere_flat(float view_xy, float view_z, float radius)
{
float len = length(vec2(view_xy, view_z));
float sin_xy = radius / len;

float cos_xy = sqrt(1.0 - sin_xy * sin_xy);
vec2 rot_lo = mat2(cos_xy, sin_xy, -sin_xy, cos_xy) * vec2(view_xy, view_z);
vec2 rot_hi = mat2(cos_xy, -sin_xy, +sin_xy, cos_xy) * vec2(view_xy, view_z);

return vec2(rot_lo.x / rot_lo.y, rot_hi.x / rot_hi.y);
}

bool cluster_cull(mat4 M, Bound bound, vec3 camera_pos)
{
vec3 bound_center = (M * vec4(bound.center_radius.xyz, 1.0)).xyz;
Expand Down Expand Up @@ -93,6 +121,61 @@ bool cluster_cull(mat4 M, Bound bound, vec3 camera_pos)
if (dot(vec4(bound_center, 1.0), p) < -effective_radius)
ret = false;
}

#ifdef MESHLET_RENDER_HIZ_BINDING
if (ret)
{
vec3 view = (frustum.view * vec4(bound_center, 1.0)).xyz;
// Rearrange -Z to +Z.
// Apply Y flip here.
view.yz = -view.yz;

// Ensure there is no clipping against near plane.
// If the sphere is close enough, we accept it.
if (view.z > effective_radius + 0.1)
{
// Have to project in view space since the sphere is still a sphere.
vec2 range_x = project_sphere_flat(view.x, view.z, effective_radius);
vec2 range_y = project_sphere_flat(view.y, view.z, effective_radius);

// Viewport scale first applies any projection scale in X/Y (without Y flip).
// The scale also does viewport size / 2 and then offsets into integer window coordinates.
range_x = range_x * frustum.viewport_scale_bias.x + frustum.viewport_scale_bias.z;
range_y = range_y * frustum.viewport_scale_bias.y + frustum.viewport_scale_bias.w;

ivec2 ix = ivec2(range_x);
ivec2 iy = ivec2(range_y);

ix.x = clamp(ix.x, 0, frustum.hiz_resolution.x - 1);
ix.y = clamp(ix.y, ix.x, frustum.hiz_resolution.x - 1);
iy.x = clamp(iy.x, 0, frustum.hiz_resolution.y - 1);
iy.y = clamp(iy.y, iy.x, frustum.hiz_resolution.y - 1);

// We need to sample from a LOD where where there is at most one texel delta
// between lo/hi values.
int max_delta = max(ix.y - ix.x, iy.y - iy.x);
int lod = min(findMSB(max_delta - 1) + 1, frustum.hiz_max_lod);
ivec2 lod_max_coord = max(frustum.hiz_resolution >> lod, ivec2(1)) - 1;
ix = min(ix >> lod, lod_max_coord.xx);
iy = min(iy >> lod, lod_max_coord.yy);

ivec2 hiz_coord = ivec2(ix.x, iy.x);

float d = texelFetch(uHiZDepth, hiz_coord, lod).x;
bool nx = ix.y != ix.x;
bool ny = iy.y != iy.x;
if (nx)
d = max(d, texelFetchOffset(uHiZDepth, hiz_coord, lod, ivec2(1, 0)).x);
if (ny)
d = max(d, texelFetchOffset(uHiZDepth, hiz_coord, lod, ivec2(0, 1)).x);
if (nx && ny)
d = max(d, texelFetchOffset(uHiZDepth, hiz_coord, lod, ivec2(1, 1)).x);

ret = view.z - effective_radius < d;
}
}
#endif

return ret;
}

Expand Down
5 changes: 3 additions & 2 deletions assets/shaders/inc/meshlet_render_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ struct TaskInfo
{
uint aabb_instance;
uint node_instance;
uint node_count_material_index; // Skinning
uint material_index;
uint mesh_index_count;
uint occluder_state_offset;
};

struct CompactedDrawInfo
{
uint meshlet_index;
uint node_offset;
uint node_count_material_offset;
uint material_offset;
};

#ifdef MESHLET_RENDER_TASK_HIERARCHICAL
Expand Down
Loading

0 comments on commit d87ea7c

Please sign in to comment.