I can see you

- Add visibility buffer fbo attachment
- Write instance id to visbuffer
- Move instance id in/out from common to impl shaders
This commit is contained in:
Jozufozu 2024-09-06 15:49:32 -05:00
parent ce51e1f534
commit 77d64aa5a2
9 changed files with 151 additions and 14 deletions

View file

@ -49,6 +49,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
private final MatrixBuffer matrixBuffer; private final MatrixBuffer matrixBuffer;
private final DepthPyramid depthPyramid; private final DepthPyramid depthPyramid;
private final VisibilityBuffer visibilityBuffer;
private boolean needsBarrier = false; private boolean needsBarrier = false;
@ -64,6 +65,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
matrixBuffer = new MatrixBuffer(); matrixBuffer = new MatrixBuffer();
depthPyramid = new DepthPyramid(programs.getDepthReduceProgram()); depthPyramid = new DepthPyramid(programs.getDepthReduceProgram());
visibilityBuffer = new VisibilityBuffer();
} }
@Override @Override
@ -100,6 +102,8 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
matrixBuffer.bind(); matrixBuffer.bind();
Uniforms.bindAll(); Uniforms.bindAll();
visibilityBuffer.attach();
if (needsBarrier) { if (needsBarrier) {
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
needsBarrier = false; needsBarrier = false;
@ -111,6 +115,8 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
MaterialRenderState.reset(); MaterialRenderState.reset();
TextureBinder.resetLightAndOverlay(); TextureBinder.resetLightAndOverlay();
visibilityBuffer.detach();
} }
} }
@ -185,6 +191,10 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
crumblingDrawBuffer.delete(); crumblingDrawBuffer.delete();
programs.release(); programs.release();
depthPyramid.delete();
visibilityBuffer.delete();
} }
public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) { public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) {

View file

@ -0,0 +1,87 @@
package dev.engine_room.flywheel.backend.engine.indirect;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL46;
import com.mojang.blaze3d.platform.GlStateManager;
import dev.engine_room.flywheel.backend.FlwBackend;
import dev.engine_room.flywheel.backend.gl.GlTextureUnit;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
import net.minecraft.client.Minecraft;
public class VisibilityBuffer {
private static final int ATTACHMENT = GL30.GL_COLOR_ATTACHMENT1;
private final int textureId;
private int lastWidth = -1;
private int lastHeight = -1;
private final IntSet attached = new IntArraySet();
public VisibilityBuffer() {
textureId = GL32.glGenTextures();
GlStateManager._bindTexture(textureId);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_EDGE);
GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_EDGE);
}
public void attach() {
// TODO: clear the vis buffer. maybe do this when we read it?
var mainRenderTarget = Minecraft.getInstance()
.getMainRenderTarget();
setupTexture(mainRenderTarget.width, mainRenderTarget.height);
if (attached.add(mainRenderTarget.frameBufferId)) {
GL46.glNamedFramebufferTexture(mainRenderTarget.frameBufferId, ATTACHMENT, textureId, 0);
try {
mainRenderTarget.checkStatus();
} catch (Exception e) {
FlwBackend.LOGGER.error("Error attaching visbuffer", e);
}
}
// Enable writes
GL46.glNamedFramebufferDrawBuffers(mainRenderTarget.frameBufferId, new int[] { GL30.GL_COLOR_ATTACHMENT0, ATTACHMENT });
}
public void detach() {
var mainRenderTarget = Minecraft.getInstance()
.getMainRenderTarget();
// Disable writes
GL46.glNamedFramebufferDrawBuffers(mainRenderTarget.frameBufferId, new int[] { GL30.GL_COLOR_ATTACHMENT0 });
}
public void delete() {
GL32.glDeleteTextures(textureId);
}
private void setupTexture(int width, int height) {
if (lastWidth == width && lastHeight == height) {
return;
}
// Need to rebind to all fbos because an attachment becomes incomplete when it's resized
attached.clear();
lastWidth = width;
lastHeight = height;
GlTextureUnit.T0.makeActive();
GlStateManager._bindTexture(textureId);
// TODO: DSA texture storage?
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R32UI, width, height, 0, GL32.GL_RED_INTEGER, GL32.GL_UNSIGNED_INT, 0);
GlStateManager._bindTexture(0);
}
}

View file

@ -13,9 +13,7 @@ uniform sampler2D _flw_crumblingTex;
in vec2 _flw_crumblingTexCoord; in vec2 _flw_crumblingTexCoord;
#endif #endif
flat in uint _flw_instanceID; layout(location = 0) out vec4 _flw_outputColor;
out vec4 _flw_outputColor;
float _flw_diffuseFactor() { float _flw_diffuseFactor() {
if (flw_material.diffuse) { if (flw_material.diffuse) {
@ -29,7 +27,7 @@ float _flw_diffuseFactor() {
} }
} }
void _flw_main() { void _flw_main(uint instanceID) {
flw_sampleColor = texture(flw_diffuseTex, flw_vertexTexCoord); flw_sampleColor = texture(flw_diffuseTex, flw_vertexTexCoord);
flw_fragColor = flw_vertexColor * flw_sampleColor; flw_fragColor = flw_vertexColor * flw_sampleColor;
flw_fragOverlay = flw_vertexOverlay; flw_fragOverlay = flw_vertexOverlay;
@ -72,7 +70,7 @@ void _flw_main() {
color = vec4(flw_vertexNormal * .5 + .5, 1.); color = vec4(flw_vertexNormal * .5 + .5, 1.);
break; break;
case 2u: case 2u:
color = _flw_id2Color(_flw_instanceID); color = _flw_id2Color(instanceID);
break; break;
case 3u: case 3u:
color = vec4(vec2((flw_fragLight * 15.0 + 0.5) / 16.), 0., 1.); color = vec4(vec2((flw_fragLight * 15.0 + 0.5) / 16.), 0., 1.);

View file

@ -71,9 +71,7 @@ mat4 _flw_modelMatrix;
mat3 _flw_normalMatrix; mat3 _flw_normalMatrix;
#endif #endif
flat out uint _flw_instanceID; void _flw_main(in FlwInstance instance) {
void _flw_main(in FlwInstance instance, in uint stableInstanceID) {
_flw_layoutVertex(); _flw_layoutVertex();
flw_instanceVertex(instance); flw_instanceVertex(instance);
flw_materialVertex(); flw_materialVertex();
@ -92,6 +90,4 @@ void _flw_main(in FlwInstance instance, in uint stableInstanceID) {
flw_distance = fogDistance(flw_vertexPos.xyz, flw_cameraPos, flw_fogShape); flw_distance = fogDistance(flw_vertexPos.xyz, flw_cameraPos, flw_fogShape);
gl_Position = flw_viewProjection * flw_vertexPos; gl_Position = flw_viewProjection * flw_vertexPos;
_flw_instanceID = stableInstanceID;
} }

View file

@ -4,10 +4,16 @@
flat in uvec3 _flw_packedMaterial; flat in uvec3 _flw_packedMaterial;
flat in uint _flw_instanceID;
layout(location = 1) out uint _flw_out_instanceID;
void main() { void main() {
_flw_uberMaterialFragmentIndex = _flw_packedMaterial.x; _flw_uberMaterialFragmentIndex = _flw_packedMaterial.x;
_flw_unpackUint2x16(_flw_packedMaterial.y, _flw_uberFogIndex, _flw_uberCutoutIndex); _flw_unpackUint2x16(_flw_packedMaterial.y, _flw_uberFogIndex, _flw_uberCutoutIndex);
_flw_unpackMaterialProperties(_flw_packedMaterial.z, flw_material); _flw_unpackMaterialProperties(_flw_packedMaterial.z, flw_material);
_flw_main(); _flw_main(_flw_instanceID);
_flw_out_instanceID = _flw_instanceID;
} }

View file

@ -21,8 +21,14 @@ layout(std430, binding = _FLW_MATRIX_BUFFER_BINDING) restrict buffer MatrixBuffe
uniform uint _flw_baseDraw; uniform uint _flw_baseDraw;
// We read the visibility buffer for all culling groups into a single shared buffer.
// This offset is used to know where each culling group starts.
uniform uint _flw_globalInstanceIdOffset = 0;
flat out uvec3 _flw_packedMaterial; flat out uvec3 _flw_packedMaterial;
flat out uint _flw_instanceID;
void main() { void main() {
#if __VERSION__ < 460 #if __VERSION__ < 460
uint drawIndex = gl_DrawIDARB + _flw_baseDraw; uint drawIndex = gl_DrawIDARB + _flw_baseDraw;
@ -49,5 +55,8 @@ void main() {
#endif #endif
FlwInstance instance = _flw_unpackInstance(instanceIndex); FlwInstance instance = _flw_unpackInstance(instanceIndex);
_flw_main(instance, instanceIndex); _flw_main(instance);
// Add 1 because a 0 instance id means null.
_flw_instanceID = _flw_globalInstanceIdOffset + instanceIndex + 1;
} }

View file

@ -0,0 +1,25 @@
layout(local_size_x = 8, local_size_y = 8) in;
layout(binding = 0) uniform usampler2D visBuffer;
layout(std430) restrict buffer VisibleFlagBuffer {
uint _flw_visibleFlag[];
};
void main() {
uint instanceID = texelFetch(visBuffer, ivec2(gl_GlobalInvocationID.xy), 0).r;
// Null instance id.
if (instanceID == 0) {
return;
}
// Adjust for null to find the actual index.
instanceID = instanceID - 1;
uint index = instanceID >> 5;
uint mask = 1u << (instanceID & 31u);
atomicOr(_flw_visibleFlag[index], mask);
}

View file

@ -3,10 +3,12 @@
uniform uvec4 _flw_packedMaterial; uniform uvec4 _flw_packedMaterial;
flat in uint _flw_instanceID;
void main() { void main() {
_flw_uberMaterialFragmentIndex = _flw_packedMaterial.y; _flw_uberMaterialFragmentIndex = _flw_packedMaterial.y;
_flw_unpackUint2x16(_flw_packedMaterial.z, _flw_uberFogIndex, _flw_uberCutoutIndex); _flw_unpackUint2x16(_flw_packedMaterial.z, _flw_uberFogIndex, _flw_uberCutoutIndex);
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material); _flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);
_flw_main(); _flw_main(_flw_instanceID);
} }

View file

@ -10,6 +10,8 @@ uniform mat4 _flw_modelMatrixUniform;
uniform mat3 _flw_normalMatrixUniform; uniform mat3 _flw_normalMatrixUniform;
#endif #endif
flat out uint _flw_instanceID;
void main() { void main() {
_flw_uberMaterialVertexIndex = _flw_packedMaterial.x; _flw_uberMaterialVertexIndex = _flw_packedMaterial.x;
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material); _flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);
@ -21,5 +23,7 @@ void main() {
_flw_normalMatrix = _flw_normalMatrixUniform; _flw_normalMatrix = _flw_normalMatrixUniform;
#endif #endif
_flw_main(instance, uint(gl_InstanceID)); _flw_main(instance);
_flw_instanceID = gl_InstanceID;
} }