Skip to content

Commit 3f2086e

Browse files
committed
Wave goodbye to order
- Implement wavelet OIT - Needed to do the same normalization step as in MBOIT but that's not described in the blog post I followed - Use an expensive pseudo blue noise function to slightly correct banding artifacts
1 parent 4eba43b commit 3f2086e

File tree

10 files changed

+383
-1388
lines changed

10 files changed

+383
-1388
lines changed

common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public class Samplers {
1111
public static final GlTextureUnit LIGHT_LUT = GlTextureUnit.T5;
1212
public static final GlTextureUnit LIGHT_SECTIONS = GlTextureUnit.T6;
1313

14-
public static final GlTextureUnit ZEROTH_MOMENT = GlTextureUnit.T7;
15-
public static final GlTextureUnit MOMENTS0 = GlTextureUnit.T8;
16-
public static final GlTextureUnit MOMENTS1 = GlTextureUnit.T9;
14+
public static final GlTextureUnit DEPTH_RANGE = GlTextureUnit.T7;
15+
public static final GlTextureUnit COEFFICIENTS = GlTextureUnit.T8;
1716
}

common/src/backend/java/dev/engine_room/flywheel/backend/compile/PipelineCompiler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,9 @@ public record PipelineProgramKey(InstanceType<?> instanceType, ContextShader con
230230

231231
public enum OitMode {
232232
OFF("", ""),
233-
GENERATE("_FLW_GENERATE_MOMENTS", "_generate"),
234-
RESOLVE("_FLW_RESOLVE_MOMENTS", "_resolve"),
233+
DEPTH_RANGE("_FLW_DEPTH_RANGE", "_depth_range"),
234+
GENERATE_COEFFICIENTS("_FLW_COLLECT_COEFFS", "_generate_coefficients"),
235+
EVALUATE("_FLW_EVALUATE", "_resolve"),
235236
;
236237

237238
public final String define;

common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
4949

5050
private final DepthPyramid depthPyramid;
5151

52-
private final MboitFramebuffer wboitFrameBuffer;
52+
private final OitFramebuffer wboitFrameBuffer;
5353

5454
public IndirectDrawManager(IndirectPrograms programs) {
5555
this.programs = programs;
@@ -66,7 +66,7 @@ public IndirectDrawManager(IndirectPrograms programs) {
6666

6767
depthPyramid = new DepthPyramid(programs);
6868

69-
wboitFrameBuffer = new MboitFramebuffer(programs);
69+
wboitFrameBuffer = new OitFramebuffer(programs);
7070
}
7171

7272
@Override
@@ -146,16 +146,26 @@ public void render(LightStorage lightStorage, EnvironmentStorage environmentStor
146146
group.submitSolid();
147147
}
148148

149-
wboitFrameBuffer.generateMoments();
149+
wboitFrameBuffer.depthRange();
150150

151151
for (var group : cullingGroups.values()) {
152-
group.submitTransparent(PipelineCompiler.OitMode.GENERATE);
152+
group.submitTransparent(PipelineCompiler.OitMode.DEPTH_RANGE);
153153
}
154154

155-
wboitFrameBuffer.resolveMoments();
155+
wboitFrameBuffer.renderTransmittance();
156156

157157
for (var group : cullingGroups.values()) {
158-
group.submitTransparent(PipelineCompiler.OitMode.RESOLVE);
158+
group.submitTransparent(PipelineCompiler.OitMode.GENERATE_COEFFICIENTS);
159+
}
160+
161+
// wboitFrameBuffer.adjustBackgroundForTotalTransmittance();
162+
163+
// vertexArray.bindForDraw();
164+
165+
wboitFrameBuffer.shade();
166+
167+
for (var group : cullingGroups.values()) {
168+
group.submitTransparent(PipelineCompiler.OitMode.EVALUATE);
159169
}
160170

161171
wboitFrameBuffer.composite();

common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MboitFramebuffer.java renamed to common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/OitFramebuffer.java

Lines changed: 57 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,27 @@
1010
import dev.engine_room.flywheel.backend.compile.IndirectPrograms;
1111
import dev.engine_room.flywheel.backend.gl.GlTextureUnit;
1212
import net.minecraft.client.Minecraft;
13-
import net.minecraft.util.Mth;
1413

15-
public class MboitFramebuffer {
14+
public class OitFramebuffer {
1615

1716
public final int fbo;
1817
private final IndirectPrograms programs;
1918
private final int vao;
2019

21-
public int zerothMoment;
22-
public int moments0;
23-
public int moments1;
20+
public int depthBounds;
21+
public int coefficients;
2422
public int accumulate;
2523

2624
private int lastWidth = -1;
2725
private int lastHeight = -1;
2826

29-
public MboitFramebuffer(IndirectPrograms programs) {
27+
public OitFramebuffer(IndirectPrograms programs) {
3028
this.programs = programs;
3129
fbo = GL46.glCreateFramebuffers();
3230
vao = GL46.glCreateVertexArrays();
3331
}
3432

35-
public void generateMoments() {
33+
public void depthRange() {
3634
var mainRenderTarget = Minecraft.getInstance()
3735
.getMainRenderTarget();
3836

@@ -42,63 +40,83 @@ public void generateMoments() {
4240
RenderSystem.depthMask(false);
4341
RenderSystem.enableBlend();
4442
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
45-
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
43+
RenderSystem.blendEquation(GL46.GL_MAX);
4644

4745
GL46.glNamedFramebufferTexture(fbo, GL46.GL_DEPTH_ATTACHMENT, mainRenderTarget.getDepthTextureId(), 0);
4846

49-
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT0, GL46.GL_COLOR_ATTACHMENT1, GL46.GL_COLOR_ATTACHMENT2});
47+
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT0});
48+
49+
var far = Minecraft.getInstance().gameRenderer.getDepthFar();
50+
51+
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{-far, -far, 0, 0});
52+
53+
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
54+
}
55+
56+
public void renderTransmittance() {
57+
// No depth writes, but we'll still use the depth test
58+
RenderSystem.depthMask(false);
59+
RenderSystem.enableBlend();
60+
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
61+
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
62+
63+
Samplers.DEPTH_RANGE.makeActive();
64+
GlStateManager._bindTexture(depthBounds);
65+
66+
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT1, GL46.GL_COLOR_ATTACHMENT2, GL46.GL_COLOR_ATTACHMENT3, GL46.GL_COLOR_ATTACHMENT4});
5067

5168
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{0, 0, 0, 0});
5269
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 1, new float[]{0, 0, 0, 0});
5370
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 2, new float[]{0, 0, 0, 0});
71+
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 3, new float[]{0, 0, 0, 0});
5472

5573
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
5674
}
5775

58-
public void resolveMoments() {
76+
public void shade() {
5977
// No depth writes, but we'll still use the depth test
6078
RenderSystem.depthMask(false);
6179
RenderSystem.enableBlend();
6280
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
6381
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
6482

65-
Samplers.ZEROTH_MOMENT.makeActive();
66-
GlStateManager._bindTexture(zerothMoment);
83+
Samplers.DEPTH_RANGE.makeActive();
84+
GlStateManager._bindTexture(depthBounds);
6785

68-
Samplers.MOMENTS0.makeActive();
69-
GlStateManager._bindTexture(moments0);
86+
Samplers.COEFFICIENTS.makeActive();
87+
GlStateManager._bindTexture(0);
7088

71-
Samplers.MOMENTS1.makeActive();
72-
GlStateManager._bindTexture(moments1);
89+
GL46.glBindTextureUnit(Samplers.COEFFICIENTS.number, coefficients);
7390

74-
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT3});
91+
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT5});
7592

7693
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{0, 0, 0, 0});
7794

7895
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
7996
}
8097

8198
public void composite() {
99+
// No depth writes, but we'll still use the depth test
100+
RenderSystem.depthMask(false);
101+
RenderSystem.enableBlend();
102+
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.DestFactor.SRC_ALPHA);
103+
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
104+
82105
var mainRenderTarget = Minecraft.getInstance()
83106
.getMainRenderTarget();
84107

85108
mainRenderTarget.bindWrite(false);
86109

87-
var oitCompositeProgram = programs.getOitCompositeProgram();
88-
89-
GlStateManager._depthMask(false);
90-
GlStateManager._depthFunc(GL46.GL_ALWAYS);
91-
GlStateManager._enableBlend();
92-
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.DestFactor.SRC_ALPHA);
93-
94-
oitCompositeProgram.bind();
95-
96110
GlTextureUnit.T0.makeActive();
97-
GlStateManager._bindTexture(zerothMoment);
111+
GlStateManager._bindTexture(0);
112+
GL46.glBindTextureUnit(0, coefficients);
98113

99114
GlTextureUnit.T1.makeActive();
100115
GlStateManager._bindTexture(accumulate);
101116

117+
programs.getOitCompositeProgram()
118+
.bind();
119+
102120
// Empty VAO, the actual full screen triangle is generated in the vertex shader
103121
GlStateManager._glBindVertexArray(vao);
104122

@@ -112,9 +130,8 @@ public void delete() {
112130
}
113131

114132
private void deleteTextures() {
115-
GL46.glDeleteTextures(zerothMoment);
116-
GL46.glDeleteTextures(moments0);
117-
GL46.glDeleteTextures(moments1);
133+
GL46.glDeleteTextures(depthBounds);
134+
GL46.glDeleteTextures(coefficients);
118135
GL46.glDeleteTextures(accumulate);
119136
}
120137

@@ -128,14 +145,12 @@ private void createTextures(int width, int height) {
128145

129146
deleteTextures();
130147

131-
zerothMoment = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
132-
moments0 = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
133-
moments1 = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
148+
depthBounds = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
149+
coefficients = GL46.glCreateTextures(GL46.GL_TEXTURE_2D_ARRAY);
134150
accumulate = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
135151

136-
GL46.glTextureStorage2D(zerothMoment, 1, GL32.GL_R16F, width, height);
137-
GL46.glTextureStorage2D(moments0, 1, GL32.GL_RGBA16F, width, height);
138-
GL46.glTextureStorage2D(moments1, 1, GL32.GL_RGBA16F, width, height);
152+
GL46.glTextureStorage2D(depthBounds, 1, GL32.GL_RG32F, width, height);
153+
GL46.glTextureStorage3D(coefficients, 1, GL32.GL_RGBA16F, width, height, 4);
139154

140155
GL46.glTextureStorage2D(accumulate, 1, GL32.GL_RGBA16F, width, height);
141156

@@ -147,39 +162,11 @@ private void createTextures(int width, int height) {
147162
// GL46.glTextureParameteri(tex, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_EDGE);
148163
// }
149164

150-
GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT0, zerothMoment, 0);
151-
GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT1, moments0, 0);
152-
GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT2, moments1, 0);
153-
GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT3, accumulate, 0);
154-
}
155-
156-
float circleToParameter(float angle) {
157-
float x = Mth.cos(angle);
158-
float y = Mth.sin(angle);
159-
float result = Mth.abs(y) - Mth.abs(x);
160-
result = (x < 0.0f) ? (2.0f - result) : result;
161-
result = (y < 0.0f) ? (6.0f - result) : result;
162-
result += (angle >= 2.0f * Mth.PI) ? 8.0f : 0.0f;
163-
return result;
164-
}
165-
166-
void computeWrappingZoneParameters(float[] out) {
167-
computeWrappingZoneParameters(out, 0.1f * Mth.PI);
168-
}
169-
170-
/*! Given an angle in radians providing the size of the wrapping zone, this
171-
function computes all constants required by the shader.*/
172-
void computeWrappingZoneParameters(float[] p_out_wrapping_zone_parameters, float new_wrapping_zone_angle) {
173-
p_out_wrapping_zone_parameters[0] = new_wrapping_zone_angle;
174-
p_out_wrapping_zone_parameters[1] = Mth.PI - 0.5f * new_wrapping_zone_angle;
175-
if (new_wrapping_zone_angle <= 0.0f) {
176-
p_out_wrapping_zone_parameters[2] = 0.0f;
177-
p_out_wrapping_zone_parameters[3] = 0.0f;
178-
} else {
179-
float zone_end_parameter = 7;
180-
float zone_begin_parameter = circleToParameter(2.0f * Mth.PI - new_wrapping_zone_angle);
181-
p_out_wrapping_zone_parameters[2] = 1.0f / (zone_end_parameter - zone_begin_parameter);
182-
p_out_wrapping_zone_parameters[3] = 1.0f - zone_end_parameter * p_out_wrapping_zone_parameters[2];
183-
}
165+
GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT0, depthBounds, 0);
166+
GL46.glNamedFramebufferTextureLayer(fbo, GL46.GL_COLOR_ATTACHMENT1, coefficients, 0, 0);
167+
GL46.glNamedFramebufferTextureLayer(fbo, GL46.GL_COLOR_ATTACHMENT2, coefficients, 0, 1);
168+
GL46.glNamedFramebufferTextureLayer(fbo, GL46.GL_COLOR_ATTACHMENT3, coefficients, 0, 2);
169+
GL46.glNamedFramebufferTextureLayer(fbo, GL46.GL_COLOR_ATTACHMENT4, coefficients, 0, 3);
170+
GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT5, accumulate, 0);
184171
}
185172
}

0 commit comments

Comments
 (0)