Skip to content

Commit

Permalink
20/20 vision
Browse files Browse the repository at this point in the history
- Calculate actual bounding sphere for glyph meshes
- Cull objects that are less than a pixel on the screen
  • Loading branch information
Jozufozu committed Oct 6, 2024
1 parent 39b2508 commit 47b6648
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,38 +87,46 @@ bool _flw_isVisible(uint instanceIndex, uint modelIndex) {
transformBoundingSphere(flw_view, center, radius);

vec4 aabb;
if (projectSphere(center, radius, _flw_cullData.znear, _flw_cullData.P00, _flw_cullData.P11, aabb))
{
float width = (aabb.z - aabb.x) * _flw_cullData.pyramidWidth;
float height = (aabb.w - aabb.y) * _flw_cullData.pyramidHeight;
if (projectSphere(center, radius, _flw_cullData.znear, _flw_cullData.P00, _flw_cullData.P11, aabb)) {
vec2 size = aabb.zw - aabb.xy;

int level = clamp(int(ceil(log2(max(width, height)))), 0, _flw_cullData.pyramidLevels);
vec2 sizeInPixels = size * flw_viewportSize;

ivec2 levelSize = textureSize(_flw_depthPyramid, level);
// Cull objects that are less than a pixel in size. Could probably make this configurable.
isVisible = isVisible && any(greaterThan(sizeInPixels, vec2(1.)));

ivec4 levelSizePair = ivec4(levelSize, levelSize);
if (isVisible) {
float width = size.x * _flw_cullData.pyramidWidth;
float height = size.y * _flw_cullData.pyramidHeight;

ivec4 bounds = ivec4(aabb * vec4(levelSizePair));
int level = clamp(int(ceil(log2(max(width, height)))), 0, _flw_cullData.pyramidLevels);

// Clamp to the texture bounds.
// Since we're not going through a sampler out of bounds texel fetches will return 0.
bounds = clamp(bounds, ivec4(0), levelSizePair);
ivec2 levelSize = textureSize(_flw_depthPyramid, level);

float depth01 = texelFetch(_flw_depthPyramid, bounds.xw, level).r;
float depth11 = texelFetch(_flw_depthPyramid, bounds.zw, level).r;
float depth10 = texelFetch(_flw_depthPyramid, bounds.zy, level).r;
float depth00 = texelFetch(_flw_depthPyramid, bounds.xy, level).r;
ivec4 levelSizePair = ivec4(levelSize, levelSize);

float depth;
if (_flw_cullData.useMin == 0) {
depth = max(max(depth00, depth01), max(depth10, depth11));
} else {
depth = min(min(depth00, depth01), min(depth10, depth11));
}
ivec4 bounds = ivec4(aabb * vec4(levelSizePair));

// Clamp to the texture bounds.
// Since we're not going through a sampler out of bounds texel fetches will return 0.
bounds = clamp(bounds, ivec4(0), levelSizePair);

float depth01 = texelFetch(_flw_depthPyramid, bounds.xw, level).r;
float depth11 = texelFetch(_flw_depthPyramid, bounds.zw, level).r;
float depth10 = texelFetch(_flw_depthPyramid, bounds.zy, level).r;
float depth00 = texelFetch(_flw_depthPyramid, bounds.xy, level).r;

float depthSphere = 1. + _flw_cullData.znear / (center.z + radius);
float depth;
if (_flw_cullData.useMin == 0) {
depth = max(max(depth00, depth01), max(depth10, depth11));
} else {
depth = min(min(depth00, depth01), min(depth10, depth11));
}

isVisible = isVisible && depthSphere <= depth;
float depthSphere = 1. + _flw_cullData.znear / (center.z + radius);

isVisible = isVisible && depthSphere <= depth;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,8 @@ private record GlyphMesh(float glyphWidth, float glyphHeight, Vector2fc[] offset
private static final float[] X = new float[] { 0, 0, 1, 1 };
private static final float[] Y = new float[] { 0, 1, 1, 0 };

// FIXME: what is the actual bounding sphere??
public GlyphMesh(float glyphWidth, float glyphHeight, Vector2fc[] offsets) {
this(glyphWidth, glyphHeight, offsets, new Vector4f(0, 0, 0, Math.max(glyphWidth, glyphHeight) * 2 * Mth.SQRT_OF_TWO));
this(glyphWidth, glyphHeight, offsets, boundingSphere(glyphWidth, glyphHeight, offsets));
}

@Override
Expand Down Expand Up @@ -344,6 +343,36 @@ public void write(MutableVertexList vertexList) {
public Vector4fc boundingSphere() {
return boundingSphere;
}

private static Vector4fc boundingSphere(float glyphWidth, float glyphHeight, Vector2fc[] offsets) {
if (offsets.length == 0) {
return new Vector4f(0, 0, 0, 0);
}

float minX = Float.POSITIVE_INFINITY;
float minY = Float.POSITIVE_INFINITY;
float maxX = Float.NEGATIVE_INFINITY;
float maxY = Float.NEGATIVE_INFINITY;
for (Vector2fc offset : offsets) {
for (int j = 0; j < 4; j++) {
var x = offset.x() + (glyphWidth * X[j]);
var y = offset.y() + (glyphHeight * Y[j]);
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
}

float x = (minX + maxX) / 2;
float y = (minY + maxY) / 2;

float sizeX = maxX - minX;
float sizeY = maxY - minY;
float maxSize = Math.max(sizeX, sizeY);

return new Vector4f(x, y, 0, Mth.SQRT_OF_TWO * maxSize / 2);
}
}

private record GlyphEffectMesh() implements QuadMesh {
Expand Down

0 comments on commit 47b6648

Please sign in to comment.