mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-03-03 22:24:40 +01:00
A win for window sizes
- Fix transparent objects disappearing when the window is resized - Clean up OitFramebuffer some more, add a quick description of each render pass - Move oit noise factor to frame uniforms
This commit is contained in:
parent
fe55693cbb
commit
19c97df115
7 changed files with 98 additions and 59 deletions
|
@ -3,23 +3,23 @@ package dev.engine_room.flywheel.backend;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.jetbrains.annotations.UnknownNullability;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import dev.engine_room.flywheel.api.Flywheel;
|
||||
import dev.engine_room.flywheel.backend.gl.GlTextureUnit;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
|
||||
public class NoiseTextures {
|
||||
|
||||
public static final ResourceLocation NOISE_TEXTURE = Flywheel.rl("textures/flywheel/noise/blue/0.png");
|
||||
public static final int NOISE_LAYERS = 16;
|
||||
public static final ResourceLocation NOISE_TEXTURE = Flywheel.rl("textures/flywheel/noise/blue.png");
|
||||
|
||||
@UnknownNullability
|
||||
public static DynamicTexture BLUE_NOISE;
|
||||
|
||||
|
||||
public static void reload(ResourceManager manager) {
|
||||
if (BLUE_NOISE != null) {
|
||||
BLUE_NOISE.close();
|
||||
|
@ -36,6 +36,15 @@ public class NoiseTextures {
|
|||
var image = NativeImage.read(NativeImage.Format.LUMINANCE, is);
|
||||
|
||||
BLUE_NOISE = new DynamicTexture(image);
|
||||
|
||||
GlTextureUnit.T0.makeActive();
|
||||
BLUE_NOISE.bind();
|
||||
|
||||
NoiseTextures.BLUE_NOISE.setFilter(true, false);
|
||||
RenderSystem.texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_S, GL32.GL_REPEAT);
|
||||
RenderSystem.texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_T, GL32.GL_REPEAT);
|
||||
|
||||
RenderSystem.bindTexture(0);
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
|||
|
||||
private final DepthPyramid depthPyramid;
|
||||
|
||||
private final OitFramebuffer wboitFrameBuffer;
|
||||
private final OitFramebuffer oitFramebuffer;
|
||||
|
||||
public IndirectDrawManager(IndirectPrograms programs) {
|
||||
this.programs = programs;
|
||||
|
@ -66,7 +66,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
|||
|
||||
depthPyramid = new DepthPyramid(programs);
|
||||
|
||||
wboitFrameBuffer = new OitFramebuffer(programs);
|
||||
oitFramebuffer = new OitFramebuffer(programs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,29 +146,32 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
|||
group.submitSolid();
|
||||
}
|
||||
|
||||
wboitFrameBuffer.depthRange();
|
||||
oitFramebuffer.prepare();
|
||||
|
||||
oitFramebuffer.depthRange();
|
||||
|
||||
for (var group : cullingGroups.values()) {
|
||||
group.submitTransparent(PipelineCompiler.OitMode.DEPTH_RANGE);
|
||||
}
|
||||
|
||||
wboitFrameBuffer.renderTransmittance();
|
||||
oitFramebuffer.renderTransmittance();
|
||||
|
||||
for (var group : cullingGroups.values()) {
|
||||
group.submitTransparent(PipelineCompiler.OitMode.GENERATE_COEFFICIENTS);
|
||||
}
|
||||
|
||||
wboitFrameBuffer.renderDepth();
|
||||
oitFramebuffer.renderDepth();
|
||||
|
||||
// Need to bind this again because we just drew a full screen quad for OIT.
|
||||
vertexArray.bindForDraw();
|
||||
|
||||
wboitFrameBuffer.shade();
|
||||
oitFramebuffer.shade();
|
||||
|
||||
for (var group : cullingGroups.values()) {
|
||||
group.submitTransparent(PipelineCompiler.OitMode.EVALUATE);
|
||||
}
|
||||
|
||||
wboitFrameBuffer.composite();
|
||||
oitFramebuffer.composite();
|
||||
|
||||
MaterialRenderState.reset();
|
||||
TextureBinder.resetLightAndOverlay();
|
||||
|
|
|
@ -13,7 +13,6 @@ import dev.engine_room.flywheel.backend.gl.GlTextureUnit;
|
|||
import net.minecraft.client.Minecraft;
|
||||
|
||||
public class OitFramebuffer {
|
||||
|
||||
private final IndirectPrograms programs;
|
||||
private final int vao;
|
||||
|
||||
|
@ -27,16 +26,25 @@ public class OitFramebuffer {
|
|||
|
||||
public OitFramebuffer(IndirectPrograms programs) {
|
||||
this.programs = programs;
|
||||
fbo = GL46.glCreateFramebuffers();
|
||||
vao = GL46.glCreateVertexArrays();
|
||||
}
|
||||
|
||||
public void depthRange() {
|
||||
/**
|
||||
* Set up the framebuffer.
|
||||
*/
|
||||
public void prepare() {
|
||||
var mainRenderTarget = Minecraft.getInstance()
|
||||
.getMainRenderTarget();
|
||||
|
||||
createTextures(mainRenderTarget.width, mainRenderTarget.height);
|
||||
maybeResizeFBO(mainRenderTarget.width, mainRenderTarget.height);
|
||||
|
||||
GL46.glNamedFramebufferTexture(fbo, GL46.GL_DEPTH_ATTACHMENT, mainRenderTarget.getDepthTextureId(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render out the min and max depth per fragment.
|
||||
*/
|
||||
public void depthRange() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
|
@ -44,8 +52,6 @@ public class OitFramebuffer {
|
|||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
|
||||
RenderSystem.blendEquation(GL46.GL_MAX);
|
||||
|
||||
GL46.glNamedFramebufferTexture(fbo, GL46.GL_DEPTH_ATTACHMENT, mainRenderTarget.getDepthTextureId(), 0);
|
||||
|
||||
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT0});
|
||||
|
||||
var far = Minecraft.getInstance().gameRenderer.getDepthFar();
|
||||
|
@ -55,6 +61,9 @@ public class OitFramebuffer {
|
|||
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the coefficients to the transmittance function.
|
||||
*/
|
||||
public void renderTransmittance() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
RenderSystem.depthMask(false);
|
||||
|
@ -69,11 +78,6 @@ public class OitFramebuffer {
|
|||
Samplers.NOISE.makeActive();
|
||||
NoiseTextures.BLUE_NOISE.bind();
|
||||
|
||||
NoiseTextures.BLUE_NOISE.setFilter(true, false);
|
||||
GL46.glTextureParameteri(NoiseTextures.BLUE_NOISE.getId(), GL32.GL_TEXTURE_WRAP_S, GL32.GL_REPEAT);
|
||||
GL46.glTextureParameteri(NoiseTextures.BLUE_NOISE.getId(), GL32.GL_TEXTURE_WRAP_T, GL32.GL_REPEAT);
|
||||
|
||||
|
||||
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT1, GL46.GL_COLOR_ATTACHMENT2, GL46.GL_COLOR_ATTACHMENT3, GL46.GL_COLOR_ATTACHMENT4});
|
||||
|
||||
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{0, 0, 0, 0});
|
||||
|
@ -84,6 +88,34 @@ public class OitFramebuffer {
|
|||
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* If any fragment has its transmittance fall off to zero, search the transmittance
|
||||
* function to determine at what depth that occurs and write out to the depth buffer.
|
||||
*/
|
||||
public void renderDepth() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.disableBlend();
|
||||
|
||||
Samplers.COEFFICIENTS.makeActive();
|
||||
RenderSystem.bindTexture(0);
|
||||
GL46.glBindTextureUnit(0, coefficients);
|
||||
|
||||
Samplers.DEPTH_RANGE.makeActive();
|
||||
RenderSystem.bindTexture(depthBounds);
|
||||
|
||||
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{});
|
||||
|
||||
programs.getOitDepthProgram()
|
||||
.bind();
|
||||
|
||||
drawFullscreenQuad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample the transmittance function and accumulate.
|
||||
*/
|
||||
public void shade() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
RenderSystem.depthMask(false);
|
||||
|
@ -109,30 +141,9 @@ public class OitFramebuffer {
|
|||
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
public void renderDepth() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.colorMask(false, false, false, false);
|
||||
RenderSystem.disableBlend();
|
||||
|
||||
Samplers.COEFFICIENTS.makeActive();
|
||||
GlStateManager._bindTexture(0);
|
||||
GL46.glBindTextureUnit(0, coefficients);
|
||||
|
||||
Samplers.DEPTH_RANGE.makeActive();
|
||||
GlStateManager._bindTexture(depthBounds);
|
||||
|
||||
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{});
|
||||
|
||||
programs.getOitDepthProgram()
|
||||
.bind();
|
||||
|
||||
// Empty VAO, the actual full screen triangle is generated in the vertex shader
|
||||
GlStateManager._glBindVertexArray(vao);
|
||||
|
||||
GL46.glDrawArrays(GL46.GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Composite the accumulated luminance onto the main framebuffer.
|
||||
*/
|
||||
public void composite() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
RenderSystem.depthMask(false);
|
||||
|
@ -147,27 +158,30 @@ public class OitFramebuffer {
|
|||
mainRenderTarget.bindWrite(false);
|
||||
|
||||
GlTextureUnit.T0.makeActive();
|
||||
GlStateManager._bindTexture(0);
|
||||
RenderSystem.bindTexture(0);
|
||||
GL46.glBindTextureUnit(0, coefficients);
|
||||
|
||||
GlTextureUnit.T1.makeActive();
|
||||
GlStateManager._bindTexture(accumulate);
|
||||
RenderSystem.bindTexture(accumulate);
|
||||
|
||||
programs.getOitCompositeProgram()
|
||||
.bind();
|
||||
|
||||
// Empty VAO, the actual full screen triangle is generated in the vertex shader
|
||||
GlStateManager._glBindVertexArray(vao);
|
||||
|
||||
GL46.glDrawArrays(GL46.GL_TRIANGLES, 0, 3);
|
||||
drawFullscreenQuad();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
deleteTextures();
|
||||
GL46.glDeleteFramebuffers(fbo);
|
||||
GL46.glDeleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
private void drawFullscreenQuad() {
|
||||
// Empty VAO, the actual full screen triangle is generated in the vertex shader
|
||||
GlStateManager._glBindVertexArray(vao);
|
||||
|
||||
GL46.glDrawArrays(GL46.GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
private void deleteTextures() {
|
||||
if (depthBounds != -1) {
|
||||
GL46.glDeleteTextures(depthBounds);
|
||||
|
@ -178,9 +192,19 @@ public class OitFramebuffer {
|
|||
if (accumulate != -1) {
|
||||
GL46.glDeleteTextures(accumulate);
|
||||
}
|
||||
if (fbo != -1) {
|
||||
GL46.glDeleteFramebuffers(fbo);
|
||||
}
|
||||
|
||||
// We sometimes get the same texture ID back when creating new textures,
|
||||
// so bind zero to clear the GlStateManager
|
||||
Samplers.COEFFICIENTS.makeActive();
|
||||
RenderSystem.bindTexture(0);
|
||||
Samplers.DEPTH_RANGE.makeActive();
|
||||
RenderSystem.bindTexture(0);
|
||||
}
|
||||
|
||||
private void createTextures(int width, int height) {
|
||||
private void maybeResizeFBO(int width, int height) {
|
||||
if (lastWidth == width && lastHeight == height) {
|
||||
return;
|
||||
}
|
||||
|
@ -190,13 +214,14 @@ public class OitFramebuffer {
|
|||
|
||||
deleteTextures();
|
||||
|
||||
fbo = GL46.glCreateFramebuffers();
|
||||
|
||||
depthBounds = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
|
||||
coefficients = GL46.glCreateTextures(GL46.GL_TEXTURE_2D_ARRAY);
|
||||
accumulate = GL46.glCreateTextures(GL46.GL_TEXTURE_2D);
|
||||
|
||||
GL46.glTextureStorage2D(depthBounds, 1, GL32.GL_RG32F, width, height);
|
||||
GL46.glTextureStorage3D(coefficients, 1, GL32.GL_RGBA16F, width, height, 4);
|
||||
|
||||
GL46.glTextureStorage2D(accumulate, 1, GL32.GL_RGBA16F, width, height);
|
||||
|
||||
// for (int tex : new int[]{zerothMoment, moments, composite}) {
|
||||
|
|
|
@ -116,6 +116,9 @@ public final class FrameUniforms extends UniformWriter {
|
|||
|
||||
ptr = writeInt(ptr, debugMode);
|
||||
|
||||
// OIT noise factor
|
||||
ptr = writeFloat(ptr, 0.07f);
|
||||
|
||||
firstWrite = false;
|
||||
BUFFER.markDirty();
|
||||
}
|
||||
|
|
|
@ -27,9 +27,6 @@ layout (binding = 8) uniform sampler2DArray _flw_coefficients;
|
|||
|
||||
layout (binding = 9) uniform sampler2D _flw_blueNoise;
|
||||
|
||||
|
||||
uniform float _flw_blueNoiseFactor = 0.08;
|
||||
|
||||
float tented_blue_noise(float normalizedDepth) {
|
||||
|
||||
float tentIn = abs(normalizedDepth * 2. - 1);
|
||||
|
@ -53,7 +50,7 @@ float depth() {
|
|||
float delta = depthRange.x + depthRange.y;
|
||||
float depth = (linearDepth + depthRange.x) / delta;
|
||||
|
||||
return depth - tented_blue_noise(depth) * _flw_blueNoiseFactor;
|
||||
return depth - tented_blue_noise(depth) * _flw_oitNoise;
|
||||
}
|
||||
|
||||
#ifdef _FLW_DEPTH_RANGE
|
||||
|
|
|
@ -62,6 +62,8 @@ layout(std140) uniform _FlwFrameUniforms {
|
|||
uint flw_cameraInBlock;
|
||||
|
||||
uint _flw_debugMode;
|
||||
|
||||
float _flw_oitNoise;
|
||||
};
|
||||
|
||||
#define flw_renderOrigin (_flw_renderOrigin.xyz)
|
||||
|
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Loading…
Add table
Reference in a new issue