mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-03-03 22:24:40 +01:00
Fabulously transparent
- Write out depth in the composite pass - When fabulous is enabled, write to the item entity target - Flip the total transmittance back to alpha when compositing so it can be consumed by the blit shader
This commit is contained in:
parent
19c97df115
commit
452d912e7b
4 changed files with 72 additions and 53 deletions
|
@ -160,7 +160,7 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
|||
group.submitTransparent(PipelineCompiler.OitMode.GENERATE_COEFFICIENTS);
|
||||
}
|
||||
|
||||
oitFramebuffer.renderDepth();
|
||||
oitFramebuffer.renderDepthFromTransmittance();
|
||||
|
||||
// Need to bind this again because we just drew a full screen quad for OIT.
|
||||
vertexArray.bindForDraw();
|
||||
|
@ -198,6 +198,8 @@ public class IndirectDrawManager extends DrawManager<IndirectInstancer<?>> {
|
|||
lightBuffers.delete();
|
||||
|
||||
matrixBuffer.delete();
|
||||
|
||||
oitFramebuffer.delete();
|
||||
}
|
||||
|
||||
public void renderCrumbling(List<Engine.CrumblingBlock> crumblingBlocks) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.engine_room.flywheel.backend.engine.indirect;
|
|||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL46;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
|
@ -33,19 +34,40 @@ public class OitFramebuffer {
|
|||
* Set up the framebuffer.
|
||||
*/
|
||||
public void prepare() {
|
||||
var mainRenderTarget = Minecraft.getInstance()
|
||||
.getMainRenderTarget();
|
||||
RenderTarget renderTarget;
|
||||
|
||||
maybeResizeFBO(mainRenderTarget.width, mainRenderTarget.height);
|
||||
if (Minecraft.useShaderTransparency()) {
|
||||
renderTarget = Minecraft.getInstance().levelRenderer.getItemEntityTarget();
|
||||
|
||||
GL46.glNamedFramebufferTexture(fbo, GL46.GL_DEPTH_ATTACHMENT, mainRenderTarget.getDepthTextureId(), 0);
|
||||
renderTarget.copyDepthFrom(Minecraft.getInstance()
|
||||
.getMainRenderTarget());
|
||||
} else {
|
||||
renderTarget = Minecraft.getInstance()
|
||||
.getMainRenderTarget();
|
||||
}
|
||||
|
||||
maybeResizeFBO(renderTarget.width, renderTarget.height);
|
||||
|
||||
GL46.glNamedFramebufferTexture(fbo, GL46.GL_DEPTH_ATTACHMENT, renderTarget.getDepthTextureId(), 0);
|
||||
|
||||
Samplers.COEFFICIENTS.makeActive();
|
||||
RenderSystem.bindTexture(0);
|
||||
GL46.glBindTextureUnit(Samplers.COEFFICIENTS.number, coefficients);
|
||||
|
||||
Samplers.DEPTH_RANGE.makeActive();
|
||||
RenderSystem.bindTexture(depthBounds);
|
||||
|
||||
Samplers.NOISE.makeActive();
|
||||
NoiseTextures.BLUE_NOISE.bind();
|
||||
|
||||
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render out the min and max depth per fragment.
|
||||
*/
|
||||
public void depthRange() {
|
||||
// No depth writes, but we'll still use the depth test
|
||||
// No depth writes, but we'll still use the depth test.
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.enableBlend();
|
||||
|
@ -57,8 +79,6 @@ public class OitFramebuffer {
|
|||
var far = Minecraft.getInstance().gameRenderer.getDepthFar();
|
||||
|
||||
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{-far, -far, 0, 0});
|
||||
|
||||
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,38 +92,24 @@ public class OitFramebuffer {
|
|||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
|
||||
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
|
||||
|
||||
Samplers.DEPTH_RANGE.makeActive();
|
||||
GlStateManager._bindTexture(depthBounds);
|
||||
|
||||
Samplers.NOISE.makeActive();
|
||||
NoiseTextures.BLUE_NOISE.bind();
|
||||
|
||||
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});
|
||||
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 1, new float[]{0, 0, 0, 0});
|
||||
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 2, new float[]{0, 0, 0, 0});
|
||||
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 3, new float[]{0, 0, 0, 0});
|
||||
|
||||
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
|
||||
public void renderDepthFromTransmittance() {
|
||||
// Only write to depth, not color.
|
||||
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);
|
||||
RenderSystem.depthFunc(GL32.GL_ALWAYS);
|
||||
|
||||
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{});
|
||||
|
||||
|
@ -124,50 +130,53 @@ public class OitFramebuffer {
|
|||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
|
||||
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
|
||||
|
||||
Samplers.DEPTH_RANGE.makeActive();
|
||||
GlStateManager._bindTexture(depthBounds);
|
||||
|
||||
Samplers.COEFFICIENTS.makeActive();
|
||||
GlStateManager._bindTexture(0);
|
||||
GL46.glBindTextureUnit(Samplers.COEFFICIENTS.number, coefficients);
|
||||
|
||||
Samplers.NOISE.makeActive();
|
||||
NoiseTextures.BLUE_NOISE.bind();
|
||||
|
||||
GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT5});
|
||||
|
||||
GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{0, 0, 0, 0});
|
||||
|
||||
GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if (Minecraft.useShaderTransparency()) {
|
||||
Minecraft.getInstance().levelRenderer.getItemEntityTarget()
|
||||
.bindWrite(false);
|
||||
} else {
|
||||
Minecraft.getInstance()
|
||||
.getMainRenderTarget()
|
||||
.bindWrite(false);
|
||||
}
|
||||
|
||||
// The composite shader writes out the closest depth to gl_FragDepth.
|
||||
// depthMask = true: OIT stuff renders on top of other transparent stuff.
|
||||
// depthMask = false: other transparent stuff renders on top of OIT stuff.
|
||||
// If Neo gets wavelet OIT we can use their hooks to be correct with everything.
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.DestFactor.SRC_ALPHA);
|
||||
|
||||
// We rely on the blend func to achieve:
|
||||
// final color = (1 - transmittance_total) * sum(color_f * alpha_f * transmittance_f) / sum(alpha_f * transmittance_f)
|
||||
// + color_dst * transmittance_total
|
||||
//
|
||||
// Though note that the alpha value we emit in the fragment shader is actually (1. - transmittance_total).
|
||||
// The extra inversion step is so we can have a sane alpha value written out for the fabulous blit shader to consume.
|
||||
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
RenderSystem.blendEquation(GL46.GL_FUNC_ADD);
|
||||
|
||||
var mainRenderTarget = Minecraft.getInstance()
|
||||
.getMainRenderTarget();
|
||||
|
||||
mainRenderTarget.bindWrite(false);
|
||||
RenderSystem.depthFunc(GL32.GL_ALWAYS);
|
||||
|
||||
GlTextureUnit.T0.makeActive();
|
||||
RenderSystem.bindTexture(0);
|
||||
GL46.glBindTextureUnit(0, coefficients);
|
||||
|
||||
GlTextureUnit.T1.makeActive();
|
||||
RenderSystem.bindTexture(accumulate);
|
||||
|
||||
programs.getOitCompositeProgram()
|
||||
.bind();
|
||||
|
||||
drawFullscreenQuad();
|
||||
|
||||
Minecraft.getInstance()
|
||||
.getMainRenderTarget()
|
||||
.bindWrite(false);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
|
|
|
@ -13,6 +13,7 @@ import dev.engine_room.flywheel.backend.mixin.LevelRendererAccessor;
|
|||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
@ -198,7 +199,7 @@ public final class FrameUniforms extends UniformWriter {
|
|||
int pyramidHeight = DepthPyramid.mip0Size(mainRenderTarget.height);
|
||||
int pyramidDepth = DepthPyramid.getImageMipLevels(pyramidWidth, pyramidHeight);
|
||||
|
||||
ptr = writeFloat(ptr, 0.05F); // zNear
|
||||
ptr = writeFloat(ptr, GameRenderer.PROJECTION_Z_NEAR); // zNear
|
||||
ptr = writeFloat(ptr, mc.gameRenderer.getDepthFar()); // zFar
|
||||
ptr = writeFloat(ptr, PROJECTION.m00()); // P00
|
||||
ptr = writeFloat(ptr, PROJECTION.m11()); // P11
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include "flywheel:internal/wavelet.glsl"
|
||||
#include "flywheel:internal/depth.glsl"
|
||||
#include "flywheel:internal/uniforms/frame.glsl"
|
||||
|
||||
layout (location = 0) out vec4 frag;
|
||||
|
||||
layout (binding = 0) uniform sampler2DArray _flw_coefficients;
|
||||
layout (binding = 1) uniform sampler2D _flw_accumulate;
|
||||
layout (binding = 0) uniform sampler2D _flw_accumulate;
|
||||
layout (binding = 7) uniform sampler2D _flw_depthRange;
|
||||
layout (binding = 8) uniform sampler2DArray _flw_coefficients;
|
||||
|
||||
void main() {
|
||||
vec4 texel = texelFetch(_flw_accumulate, ivec2(gl_FragCoord.xy), 0);
|
||||
|
@ -14,5 +17,9 @@ void main() {
|
|||
|
||||
float total_transmittance = total_transmittance(_flw_coefficients);
|
||||
|
||||
frag = vec4(texel.rgb / texel.a, total_transmittance);
|
||||
frag = vec4(texel.rgb / texel.a, 1. - total_transmittance);
|
||||
|
||||
float minDepth = -texelFetch(_flw_depthRange, ivec2(gl_FragCoord.xy), 0).r;
|
||||
|
||||
gl_FragDepth = delinearize_depth(minDepth, _flw_cullData.znear, _flw_cullData.zfar);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue