mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-30 23:04:57 +01:00
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:
parent
39b2508d02
commit
47b6648681
2 changed files with 63 additions and 26 deletions
|
@ -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 depth;
|
||||
if (_flw_cullData.useMin == 0) {
|
||||
depth = max(max(depth00, depth01), max(depth10, depth11));
|
||||
} else {
|
||||
depth = min(min(depth00, depth01), min(depth10, depth11));
|
||||
}
|
||||
|
||||
float depthSphere = 1. + _flw_cullData.znear / (center.z + radius);
|
||||
|
||||
isVisible = isVisible && depthSphere <= depth;
|
||||
}
|
||||
|
||||
float depthSphere = 1. + _flw_cullData.znear / (center.z + radius);
|
||||
|
||||
isVisible = isVisible && depthSphere <= depth;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,9 +308,8 @@ public final class TextVisual {
|
|||
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
|
||||
|
@ -344,6 +343,36 @@ public final class TextVisual {
|
|||
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 {
|
||||
|
|
Loading…
Reference in a new issue