Began work on post processing
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
6
src/main/resources/assets/zenith/shaders/post/noop.frag
Normal file
6
src/main/resources/assets/zenith/shaders/post/noop.frag
Normal file
@@ -0,0 +1,6 @@
|
||||
#version 330 core
|
||||
out vec4 colour;
|
||||
in vec2 UV;
|
||||
void main() {
|
||||
colour = vec4(1,0,1,1);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
//Contains the definision of a ray and step functions
|
||||
struct Ray {
|
||||
ivec3 pos;
|
||||
vec3 innerPos;
|
||||
|
||||
vec3 dir;
|
||||
vec3 invDir;
|
||||
};
|
||||
|
||||
Ray ray;
|
||||
void setup(vec3 origin, vec3 direction) {
|
||||
ray.pos = ivec3(origin);
|
||||
ray.innerPos = origin - ray.pos;
|
||||
direction *= inversesqrt(direction);
|
||||
ray.dir = direction;
|
||||
ray.invDir = 1/direction;
|
||||
}
|
||||
|
||||
void step(ivec3 aabb) {
|
||||
//TODO:check for innerPos>=1 and step into that voxel
|
||||
vec3 t2f = (aabb - ray.innerPos) * ray.invDir;
|
||||
float mint2f = min(t2f.x, min(t2f.y, t2f.z));
|
||||
bvec3 msk = lessThanEqual(t2f.xyz, vec3(mint2f));
|
||||
vec3 newIP = mint2f * ray.dir + ray.innerPos;
|
||||
ivec3 offset = min(aabb-1, ivec3(newIP));
|
||||
ray.pos += offset + ivec3(msk);
|
||||
ray.innerPos = mix(vec3(0), newIP - offset, not(msk));
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
struct Voxel {
|
||||
|
||||
};
|
||||
|
||||
//TODO: add tlas and blas voxel fetching (rings and all)
|
||||
void getVoxel() {
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
//Glue code between ray stepper and voxel storage
|
||||
// its the primary ray tracer
|
||||
Reference in New Issue
Block a user