20/20 vision

- Calculate actual bounding sphere for glyph meshes
- Cull objects that are less than a pixel on the screen
This commit is contained in:
Jozufozu 2024-10-05 21:54:18 -07:00
parent 39b2508d02
commit 47b6648681
2 changed files with 63 additions and 26 deletions

View file

@ -87,10 +87,17 @@ bool _flw_isVisible(uint instanceIndex, uint modelIndex) {
transformBoundingSphere(flw_view, center, radius); transformBoundingSphere(flw_view, center, radius);
vec4 aabb; vec4 aabb;
if (projectSphere(center, radius, _flw_cullData.znear, _flw_cullData.P00, _flw_cullData.P11, aabb)) if (projectSphere(center, radius, _flw_cullData.znear, _flw_cullData.P00, _flw_cullData.P11, aabb)) {
{ vec2 size = aabb.zw - aabb.xy;
float width = (aabb.z - aabb.x) * _flw_cullData.pyramidWidth;
float height = (aabb.w - aabb.y) * _flw_cullData.pyramidHeight; vec2 sizeInPixels = size * flw_viewportSize;
// Cull objects that are less than a pixel in size. Could probably make this configurable.
isVisible = isVisible && any(greaterThan(sizeInPixels, vec2(1.)));
if (isVisible) {
float width = size.x * _flw_cullData.pyramidWidth;
float height = size.y * _flw_cullData.pyramidHeight;
int level = clamp(int(ceil(log2(max(width, height)))), 0, _flw_cullData.pyramidLevels); int level = clamp(int(ceil(log2(max(width, height)))), 0, _flw_cullData.pyramidLevels);
@ -121,6 +128,7 @@ bool _flw_isVisible(uint instanceIndex, uint modelIndex) {
isVisible = isVisible && depthSphere <= depth; isVisible = isVisible && depthSphere <= depth;
} }
} }
}
return isVisible; return isVisible;
} }

View file

@ -308,9 +308,8 @@ public final class TextVisual {
private static final float[] X = new float[] { 0, 0, 1, 1 }; private static final float[] X = new float[] { 0, 0, 1, 1 };
private static final float[] Y = new float[] { 0, 1, 1, 0 }; 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) { 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 @Override
@ -344,6 +343,36 @@ public final class TextVisual {
public Vector4fc boundingSphere() { public Vector4fc boundingSphere() {
return 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 { private record GlyphEffectMesh() implements QuadMesh {