mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-25 14:36:18 +01:00
The depths of the rabbit hole
- Fix mip levels being half the size they should be - Use the next lowest po2 from the main render target size for mip 0 - Map from dst texel to src texel rather than naively multiply by 2 - Clamp the estimated mip level in the cull shader - Use texel fetches in the cull shader (not sure if necessary?)
This commit is contained in:
parent
01a7936a05
commit
6c1fbf610d
5 changed files with 47 additions and 21 deletions
|
@ -35,8 +35,8 @@ public class DepthPyramid {
|
|||
var mainRenderTarget = Minecraft.getInstance()
|
||||
.getMainRenderTarget();
|
||||
|
||||
int width = mainRenderTarget.width;
|
||||
int height = mainRenderTarget.height;
|
||||
int width = mip0Size(mainRenderTarget.width);
|
||||
int height = mip0Size(mainRenderTarget.height);
|
||||
|
||||
int mipLevels = getImageMipLevels(width, height);
|
||||
|
||||
|
@ -53,15 +53,15 @@ public class DepthPyramid {
|
|||
depthReduceProgram.bind();
|
||||
|
||||
for (int i = 0; i < mipLevels; i++) {
|
||||
int mipWidth = Math.max(1, width >> i);
|
||||
int mipHeight = Math.max(1, height >> i);
|
||||
int mipWidth = mipSize(width, i);
|
||||
int mipHeight = mipSize(height, i);
|
||||
|
||||
int srcTexture = (i == 0) ? depthBufferId : pyramidTextureId;
|
||||
GL46.glBindTexture(GL32.GL_TEXTURE_2D, srcTexture);
|
||||
|
||||
GL46.glBindImageTexture(0, pyramidTextureId, i, false, 0, GL32.GL_WRITE_ONLY, GL32.GL_R32F);
|
||||
|
||||
depthReduceProgram.setUVec2("imageSize", mipWidth, mipHeight);
|
||||
depthReduceProgram.setVec2("imageSize", mipWidth, mipHeight);
|
||||
depthReduceProgram.setInt("lod", Math.max(0, i - 1));
|
||||
|
||||
GL46.glDispatchCompute(MoreMath.ceilingDiv(mipWidth, 8), MoreMath.ceilingDiv(mipHeight, 8), 1);
|
||||
|
@ -85,20 +85,28 @@ public class DepthPyramid {
|
|||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, pyramidTextureId);
|
||||
|
||||
for (int i = 0; i < mipLevels; i++) {
|
||||
int mipWidth = Math.max(1, width >> (i + 1));
|
||||
int mipHeight = Math.max(1, height >> (i + 1));
|
||||
int mipWidth = mipSize(width, i);
|
||||
int mipHeight = mipSize(height, i);
|
||||
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, i, GL32.GL_R32F, mipWidth, mipHeight, 0, GL32.GL_RED, GL32.GL_FLOAT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getImageMipLevels(int width, int height) {
|
||||
public static int mipSize(int mip0Size, int level) {
|
||||
return Math.max(1, mip0Size >> level);
|
||||
}
|
||||
|
||||
public static int mip0Size(int screenSize) {
|
||||
return Integer.highestOneBit(screenSize);
|
||||
}
|
||||
|
||||
public static int getImageMipLevels(int width, int height) {
|
||||
int result = 1;
|
||||
|
||||
while (width > 2 && height > 2) {
|
||||
result++;
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import dev.engine_room.flywheel.api.RenderContext;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
|
||||
import dev.engine_room.flywheel.backend.engine.indirect.DepthPyramid;
|
||||
import dev.engine_room.flywheel.backend.mixin.LevelRendererAccessor;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -17,7 +18,7 @@ import net.minecraft.world.level.Level;
|
|||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public final class FrameUniforms extends UniformWriter {
|
||||
private static final int SIZE = 96 + 64 * 9 + 16 * 5 + 8 * 2 + 8 + 4 * 16;
|
||||
private static final int SIZE = 96 + 64 * 9 + 16 * 5 + 8 * 2 + 8 + 4 * 17;
|
||||
static final UniformBuffer BUFFER = new UniformBuffer(Uniforms.FRAME_INDEX, SIZE);
|
||||
|
||||
private static final Matrix4f VIEW = new Matrix4f();
|
||||
|
@ -182,12 +183,20 @@ public final class FrameUniforms extends UniformWriter {
|
|||
}
|
||||
|
||||
private static long writeCullData(long ptr) {
|
||||
var mc = Minecraft.getInstance();
|
||||
var mainRenderTarget = mc.getMainRenderTarget();
|
||||
|
||||
int pyramidWidth = DepthPyramid.mip0Size(mainRenderTarget.width);
|
||||
int pyramidHeight = DepthPyramid.mip0Size(mainRenderTarget.height);
|
||||
int pyramidDepth = DepthPyramid.getImageMipLevels(pyramidWidth, pyramidHeight);
|
||||
|
||||
ptr = writeFloat(ptr, 0.05F); // zNear
|
||||
ptr = writeFloat(ptr, Minecraft.getInstance().gameRenderer.getDepthFar()); // zFar
|
||||
ptr = writeFloat(ptr, mc.gameRenderer.getDepthFar()); // zFar
|
||||
ptr = writeFloat(ptr, PROJECTION.m00()); // P00
|
||||
ptr = writeFloat(ptr, PROJECTION.m11()); // P11
|
||||
ptr = writeFloat(ptr, Minecraft.getInstance().getMainRenderTarget().width >> 1); // pyramidWidth
|
||||
ptr = writeFloat(ptr, Minecraft.getInstance().getMainRenderTarget().height >> 1); // pyramidHeight
|
||||
ptr = writeFloat(ptr, pyramidWidth); // pyramidWidth
|
||||
ptr = writeFloat(ptr, pyramidHeight); // pyramidHeight
|
||||
ptr = writeInt(ptr, pyramidDepth - 1); // pyramidLevels
|
||||
ptr = writeInt(ptr, 0); // useMin
|
||||
|
||||
return ptr;
|
||||
|
|
|
@ -91,12 +91,18 @@ bool _flw_isVisible(uint instanceIndex, uint modelIndex) {
|
|||
float width = (aabb.z - aabb.x) * _flw_cullData.pyramidWidth;
|
||||
float height = (aabb.w - aabb.y) * _flw_cullData.pyramidHeight;
|
||||
|
||||
float level = floor(log2(max(width, height)));
|
||||
int level = clamp(0, int(ceil(log2(max(width, height)))), _flw_cullData.pyramidLevels);
|
||||
|
||||
float depth01 = textureLod(_flw_depthPyramid, aabb.xw, level).r;
|
||||
float depth11 = textureLod(_flw_depthPyramid, aabb.zw, level).r;
|
||||
float depth10 = textureLod(_flw_depthPyramid, aabb.zy, level).r;
|
||||
float depth00 = textureLod(_flw_depthPyramid, aabb.xy, level).r;
|
||||
ivec2 levelSize = textureSize(_flw_depthPyramid, level);
|
||||
|
||||
ivec4 levelSizePair = ivec4(levelSize, levelSize);
|
||||
|
||||
ivec4 bounds = ivec4(aabb * vec4(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) {
|
||||
|
|
|
@ -3,7 +3,7 @@ layout(local_size_x = 8, local_size_y = 8) in;
|
|||
layout(binding = 0, r32f) uniform writeonly image2D outImage;
|
||||
layout(binding = 1) uniform sampler2D inImage;
|
||||
|
||||
uniform uvec2 imageSize;
|
||||
uniform vec2 imageSize;
|
||||
uniform int lod;
|
||||
|
||||
uniform int useMin = 0;
|
||||
|
@ -11,7 +11,9 @@ uniform int useMin = 0;
|
|||
void main() {
|
||||
uvec2 pos = gl_GlobalInvocationID.xy;
|
||||
|
||||
ivec2 samplePos = ivec2(pos) * 2;
|
||||
// Map the output texel to an input texel. Properly do the division because generating mip0 maps from the actual
|
||||
// full resolution depth buffer and the aspect ratio may be different from our Po2 pyramid.
|
||||
ivec2 samplePos = ivec2(floor(vec2(pos) * vec2(textureSize(inImage, lod)) / imageSize));
|
||||
|
||||
float depth01 = texelFetchOffset(inImage, samplePos, lod, ivec2(0, 1)).r;
|
||||
float depth11 = texelFetchOffset(inImage, samplePos, lod, ivec2(1, 1)).r;
|
||||
|
|
|
@ -16,6 +16,7 @@ struct _FlwCullData {
|
|||
float P11;
|
||||
float pyramidWidth;
|
||||
float pyramidHeight;
|
||||
int pyramidLevels;
|
||||
uint useMin;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue