Began work on post processing

This commit is contained in:
mcrcortex
2024-01-30 20:55:46 +10:00
parent 80bd0d7c67
commit a3f043a577
16 changed files with 224 additions and 123 deletions

View File

@@ -28,8 +28,9 @@ public class DistanceTracker {
this.minYSection = MinecraftClient.getInstance().world.getBottomSectionCoord()/2;
this.maxYSection = MinecraftClient.getInstance().world.getTopSectionCoord()/2;
if (true) {
this.rings[0] = new TransitionRing2D(5, MinecraftClient.getInstance().options.getViewDistance().getValue() / 2, (x, z) -> {
int radius = (MinecraftClient.getInstance().options.getViewDistance().getValue() / 2) - 4;
if (radius > 0 && false) {
this.rings[0] = new TransitionRing2D(5, radius, (x, z) -> {
for (int y = this.minYSection; y <= this.maxYSection; y++) {
this.tracker.remLvl0(x, y, z);
}

View File

@@ -1,14 +1,15 @@
package me.cortex.zenith.client.core;
import com.mojang.blaze3d.platform.GlStateManager;
import me.cortex.zenith.client.config.ZenithConfig;
import me.cortex.zenith.client.core.rendering.*;
import me.cortex.zenith.client.core.rendering.building.RenderGenerationService;
import me.cortex.zenith.client.core.rendering.post.PostProcessing;
import me.cortex.zenith.client.core.util.DebugUtil;
import me.cortex.zenith.common.world.WorldEngine;
import me.cortex.zenith.client.importers.WorldImporter;
import me.cortex.zenith.common.world.storage.FragmentedStorageBackendAdaptor;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.util.math.MatrixStack;
@@ -63,7 +64,7 @@ public class VoxelCore {
this.distanceTracker = new DistanceTracker(this.renderTracker, 5, ZenithConfig.CONFIG.qualityScale);
System.out.println("Distance tracker initialized");
this.postProcessing = null;//new PostProcessing();
this.postProcessing = new PostProcessing();
this.world.getMapper().setCallbacks(this.renderer::addBlockState, a->{});
@@ -107,9 +108,8 @@ public class VoxelCore {
//this.renderer.getModelManager().updateEntry(0, Blocks.COMPARATOR.getDefaultState());
//this.renderer.getModelManager().updateEntry(0, Blocks.OAK_LEAVES.getDefaultState());
//int boundFB = GlStateManager.getBoundFramebuffer();
//this.postProcessing.setSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight);
//this.postProcessing.bindClearFramebuffer();
int boundFB = GlStateManager.getBoundFramebuffer();
this.postProcessing.setup(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight, boundFB);
//TODO: FIXME: since we just bound the post processing FB the depth information isnt
// copied over, we must do this manually and also copy it with respect to the
@@ -121,13 +121,15 @@ public class VoxelCore {
// occlusion culler
this.renderer.renderFarAwayOpaque(matrices, cameraX, cameraY, cameraZ);
//glBindFramebuffer(GL_FRAMEBUFFER, boundFB);
//this.postProcessing.renderPost(boundFB);
//Compute the SSAO of the rendered terrain
this.postProcessing.computeSSAO();
//We can render the translucent directly after as it is the furthest translucent objects
this.renderer.renderFarAwayTranslucent();
this.postProcessing.renderPost(boundFB);
}
public void addDebugInfo(List<String> debug) {

View File

@@ -1,81 +0,0 @@
package me.cortex.zenith.client.core.rendering;
import me.cortex.zenith.client.core.gl.GlFramebuffer;
import me.cortex.zenith.client.core.gl.GlTexture;
import me.cortex.zenith.client.core.gl.shader.Shader;
import me.cortex.zenith.client.core.gl.shader.ShaderType;
import org.lwjgl.opengl.GL11C;
import static org.lwjgl.opengl.ARBFramebufferObject.*;
import static org.lwjgl.opengl.ARBShaderImageLoadStore.glBindImageTexture;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15C.GL_READ_WRITE;
import static org.lwjgl.opengl.GL44C.glBindImageTextures;
import static org.lwjgl.opengl.GL45C.glTextureBarrier;
public class PostProcessing {
private final GlFramebuffer framebuffer;
private int width;
private int height;
private GlTexture colour;
private GlTexture depthStencil;
private final Shader ssao = Shader.make()
.add(ShaderType.COMPUTE, "voxelmon:lod/ssao/ssao.comp")
.compile();
//private final Shader blit = Shader.make()
// .add(ShaderType.VERTEX, "voxelmon:lod/blit_nodepth/quad.vert")
// .add(ShaderType.FRAGMENT, "voxelmon:lod/blit_nodepth/quad.frag")
// .compile();
public PostProcessing() {
this.framebuffer = new GlFramebuffer();
}
public void setSize(int width, int height) {
if (this.width != width || this.height != height) {
this.width = width;
this.height = height;
if (this.colour != null) {
this.colour.free();
this.depthStencil.free();
}
this.colour = new GlTexture().store(GL_RGBA8, 1, width, height);
this.depthStencil = new GlTexture().store(GL_DEPTH24_STENCIL8, 1, width, height);
this.framebuffer.bind(GL_COLOR_ATTACHMENT0, this.colour);
this.framebuffer.bind(GL_DEPTH_STENCIL_ATTACHMENT, this.depthStencil);
this.framebuffer.verify();
}
}
//Bind and clears the post processing frame buffer
public void bindClearFramebuffer() {
glBindFramebuffer(GL_FRAMEBUFFER, this.framebuffer.id);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
//Executes the post processing and emits to whatever framebuffer is currently bound via a blit
public void renderPost(int outputFb) {
this.ssao.bind();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, this.depthStencil.id);
glBindImageTexture(0, this.colour.id, 0, false,0, GL_READ_WRITE, GL_RGBA8);
//glDispatchCompute(this.width/32, this.height/32, 1);
glTextureBarrier();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this.colour.id);
glDrawArrays(GL11C.GL_TRIANGLES, 0, 3);
}
public void shutdown() {
this.framebuffer.free();
if (this.colour != null) this.colour.free();
if (this.depthStencil != null) this.depthStencil.free();
this.ssao.free();
//this.blit.free();
}
}

View File

@@ -0,0 +1,33 @@
package me.cortex.zenith.client.core.rendering.post;
import me.cortex.zenith.client.core.gl.shader.Shader;
import me.cortex.zenith.client.core.gl.shader.ShaderType;
import net.minecraft.util.Identifier;
import static org.lwjgl.opengl.GL11C.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11C.glDrawArrays;
import static org.lwjgl.opengl.GL30C.glBindVertexArray;
import static org.lwjgl.opengl.GL45C.glCreateVertexArrays;
public class FullscreenBlit {
private static final int EMPTY_VAO = glCreateVertexArrays();
private final Shader shader;
public FullscreenBlit(String fragId) {
this.shader = Shader.make()
.add(ShaderType.VERTEX, "zenith:post/fullscreen.vert")
.add(ShaderType.FRAGMENT, fragId)
.compile();
}
public void blit() {
glBindVertexArray(EMPTY_VAO);
this.shader.bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
public void delete() {
this.shader.free();
}
}

View File

@@ -0,0 +1,147 @@
package me.cortex.zenith.client.core.rendering.post;
import me.cortex.zenith.client.core.gl.GlFramebuffer;
import me.cortex.zenith.client.core.gl.GlTexture;
import me.cortex.zenith.client.core.gl.shader.Shader;
import me.cortex.zenith.client.core.gl.shader.ShaderType;
import org.lwjgl.opengl.GL11C;
import static org.lwjgl.opengl.ARBFramebufferObject.*;
import static org.lwjgl.opengl.ARBShaderImageLoadStore.glBindImageTexture;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15C.GL_READ_WRITE;
import static org.lwjgl.opengl.GL20C.glStencilFuncSeparate;
import static org.lwjgl.opengl.GL44C.glBindImageTextures;
import static org.lwjgl.opengl.GL45C.glBlitNamedFramebuffer;
import static org.lwjgl.opengl.GL45C.glTextureBarrier;
public class PostProcessing {
private final GlFramebuffer framebuffer;
private int width;
private int height;
private GlTexture colour;
private GlTexture depthStencil;
private final Shader ssao = Shader.make()
.add(ShaderType.COMPUTE, "zenith:lod/ssao/ssao.comp")
.compile();
private final FullscreenBlit emptyBlit = new FullscreenBlit("zenith:post/noop.frag");
private final FullscreenBlit blitTexture = new FullscreenBlit("zenith:post/blit_texture_cutout.frag");
public PostProcessing() {
this.framebuffer = new GlFramebuffer();
}
public void setSize(int width, int height) {
if (this.width != width || this.height != height) {
this.width = width;
this.height = height;
if (this.colour != null) {
this.colour.free();
this.depthStencil.free();
}
this.colour = new GlTexture().store(GL_RGBA8, 1, width, height);
this.depthStencil = new GlTexture().store(GL_DEPTH24_STENCIL8, 1, width, height);
this.framebuffer.bind(GL_COLOR_ATTACHMENT0, this.colour);
this.framebuffer.bind(GL_DEPTH_STENCIL_ATTACHMENT, this.depthStencil);
this.framebuffer.verify();
}
}
public void shutdown() {
this.framebuffer.free();
if (this.colour != null) this.colour.free();
if (this.depthStencil != null) this.depthStencil.free();
this.ssao.free();
this.emptyBlit.delete();
this.blitTexture.delete();
}
public void setup(int width, int height, int sourceFB) {
this.setSize(width, height);
glBindFramebuffer(GL_FRAMEBUFFER, this.framebuffer.id);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBlitNamedFramebuffer(sourceFB, this.framebuffer.id, 0,0, width, height, 0,0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
//TODO: need to blit a fullscreen quad to generate a stencil mask of where the vanilla terrain is/isnt
// then when rastering zenith terrain, only render to non masked areas
//Hell once the stencil mask is computed, could clear the depth buffer and use a different near/far plane
//Create a stencil mask of terrain generated by minecraft
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
glDepthMask(false);
glColorMask(false,false,false,false);
this.emptyBlit.blit();
glColorMask(true,true,true,true);
glDepthMask(true);
glDisable(GL_DEPTH_TEST);
//Clear the depth buffer we copied cause else it will interfear with results (not really i think idk)
glClear(GL_DEPTH_BUFFER_BIT);
//Make zenith terrain render only where there isnt mc terrain
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 1, 0xFF);
//glDisable(GL_STENCIL_TEST);
//TODO: need to figure out how to do translucency cause doing it normally will cause water to have double translucency (i think)
}
//Computes ssao on the current framebuffer data and updates it
// this means that translucency wont be effected etc
public void computeSSAO() {
//this.ssao.bind();
//glActiveTexture(GL_TEXTURE1);
//glBindTexture(GL_TEXTURE_2D, this.depthStencil.id);
//glBindImageTexture(0, this.colour.id, 0, false,0, GL_READ_WRITE, GL_RGBA8);
////glDispatchCompute(this.width/32, this.height/32, 1);
//glTextureBarrier();
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, this.colour.id);
//glDrawArrays(GL11C.GL_TRIANGLES, 0, 3);
}
//Executes the post processing and emits to whatever framebuffer is currently bound via a blit
public void renderPost(int outputFB) {
glDisable(GL_STENCIL_TEST);
glBindFramebuffer(GL_FRAMEBUFFER, outputFB);
//This will need to be replaced with a blit shader to raster with respect to the stencil
//glBlitNamedFramebuffer(this.framebuffer.id, outputFB, 0,0, this.width, this.height, 0,0, this.width, this.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
int oldActiveTexture = glGetInteger(GL_ACTIVE_TEXTURE);
glActiveTexture(GL_TEXTURE0);
int oldBoundTexture = glGetInteger(GL_TEXTURE_BINDING_2D);
glBindTexture(GL_TEXTURE_2D, this.colour.id);
glEnable(GL_DEPTH_TEST);
glDepthMask(false);
this.blitTexture.blit();
glDisable(GL_DEPTH_TEST);
glDepthMask(true);
glBindTexture(GL_TEXTURE_2D, oldBoundTexture);
glActiveTexture(oldActiveTexture);
}
}

View File

@@ -55,11 +55,11 @@ public class VoxelIngestService {
section.getBiomeContainer(),
(x, y, z, state) -> {
if (lighting == null || ((lighting.first() != null && lighting.first().isUninitialized())&&(lighting.second()!=null&&lighting.second().isUninitialized()))) {
return (byte) 0xFF;
return (byte) 0x0f;
} else {
//Lighting is a piece of shit cause its done per face
int block = lighting.first()!=null?Math.min(15,lighting.first().get(x, y, z)):0xF;
int sky = lighting.second()!=null?Math.min(15,lighting.second().get(x, y, z)):0xF;
int block = lighting.first()!=null?Math.min(15,lighting.first().get(x, y, z)):0;
int sky = lighting.second()!=null?Math.min(15,lighting.second().get(x, y, z)):0;
if (block<state.getLuminance()) {
block = state.getLuminance();
}

View File

@@ -13,7 +13,7 @@ layout(location = 0) out vec4 outColour;
void main() {
vec2 uv = mod(uv, vec2(1))*(1f/(vec2(3,2)*256f));
vec4 colour = texture(blockModelAtlas, uv + baseUV);
if (discardAlpha == 1 && colour.a == 0.0f) {
if (discardAlpha == 1 && colour.a <= 0.001f) {
discard;
}
outColour = colour * colourTinting;

View File

@@ -0,0 +1,12 @@
#version 330 core
uniform sampler2D text;
out vec4 colour;
in vec2 UV;
void main() {
colour = texture(text, UV.xy);
if (colour.a == 0.0) {
discard;
}
}

View File

@@ -0,0 +1,7 @@
#version 330 core
out vec2 UV;
void main() {
gl_Position = vec4(vec2(gl_VertexID&1, (gl_VertexID>>1)&1) * 4 - 1, 0.99999999999f, 1);
UV = gl_Position.xy*0.5+0.5;
}

View File

@@ -0,0 +1,6 @@
#version 330 core
out vec4 colour;
in vec2 UV;
void main() {
colour = vec4(1,0,1,1);
}

View File

@@ -1,8 +0,0 @@
#version 460 core
layout(location = 0) in flat vec4 colour;
layout(location = 0) out vec4 outColour;
void main() {
//TODO: randomly discard the fragment with respect to the alpha value
outColour = colour;
}

View File

@@ -1,18 +0,0 @@
#version 460 core
layout(location = 0) out flat vec4 colour;
layout(binding = 0, std140) uniform SceneUniform {
mat4 MVP;
ivec3 baseSectionPos;
int _pad1;
};
void main() {
int cornerIdx = gl_VertexID&3;
gl_Position = MVP * vec4(vec3(cornerIdx&1,((cornerIdx>>1)&1),0),1);
colour = vec4(float((uint(gl_VertexID)>>2)&7)/7,float((uint(gl_VertexID)>>5)&7)/7,float((uint(gl_VertexID)>>8)&7)/7,1);
}