work on chunk outline renderer
This commit is contained in:
@@ -12,6 +12,9 @@ public class GlTexture extends TrackedObject {
|
||||
public final int id;
|
||||
private final int type;
|
||||
private int format;
|
||||
private int width;
|
||||
private int height;
|
||||
private int layers;
|
||||
public GlTexture() {
|
||||
this(GL_TEXTURE_2D);
|
||||
}
|
||||
@@ -34,6 +37,9 @@ public class GlTexture extends TrackedObject {
|
||||
this.format = format;
|
||||
if (this.type == GL_TEXTURE_2D) {
|
||||
glTextureStorage2D(this.id, levels, format, width, height);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.layers = layers;
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown texture type");
|
||||
}
|
||||
@@ -55,4 +61,16 @@ public class GlTexture extends TrackedObject {
|
||||
public GlTexture name(String name) {
|
||||
return GlDebug.name(name, this);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public int getLayers() {
|
||||
return this.layers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ public class ModelTextureBakery {
|
||||
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, this.capture.framebuffer.id);
|
||||
//TODO: make use glClearNamedFramebuffer* to reduce/remove state change
|
||||
glClearColor(0,0,0,0);
|
||||
glClearDepth(1);
|
||||
glClearStencil(0);
|
||||
|
||||
@@ -3,19 +3,30 @@ package me.cortex.voxy.client.core.rendering;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||
import me.cortex.voxy.client.core.gl.GlBuffer;
|
||||
import me.cortex.voxy.client.core.gl.GlFramebuffer;
|
||||
import me.cortex.voxy.client.core.gl.GlTexture;
|
||||
import me.cortex.voxy.client.core.gl.shader.Shader;
|
||||
import me.cortex.voxy.client.core.gl.shader.ShaderType;
|
||||
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3i;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import static me.cortex.voxy.client.core.rendering.PrintfDebugUtil.PRINTF_processor;
|
||||
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
|
||||
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
|
||||
import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
|
||||
import static org.lwjgl.opengl.GL15.glBindBuffer;
|
||||
import static org.lwjgl.opengl.GL30.glBindBufferBase;
|
||||
import static org.lwjgl.opengl.GL30.glBindVertexArray;
|
||||
import static org.lwjgl.opengl.GL30C.*;
|
||||
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;
|
||||
import static org.lwjgl.opengl.GL31.glDrawElementsInstanced;
|
||||
import static org.lwjgl.opengl.GL40C.GL_DRAW_INDIRECT_BUFFER;
|
||||
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;
|
||||
import static org.lwjgl.opengl.GL45.glClearNamedFramebufferfv;
|
||||
|
||||
//This is a render subsystem, its very simple in what it does
|
||||
// it renders an AABB around loaded chunks, thats it
|
||||
@@ -25,12 +36,24 @@ public class ChunkBoundRenderer {
|
||||
private final GlBuffer uniformBuffer = new GlBuffer(128);
|
||||
private final Long2IntOpenHashMap chunk2idx = new Long2IntOpenHashMap(MAX_CHUNK_COUNT);
|
||||
private final long[] idx2chunk = new long[MAX_CHUNK_COUNT];
|
||||
private final Shader rasterShader = Shader.makeAuto()
|
||||
.add(ShaderType.VERTEX, "voxy:chunkoutline/outline.vsh")
|
||||
.add(ShaderType.FRAGMENT, "voxy:chunkoutline/outline.fsh")
|
||||
.compile()
|
||||
.ssbo(0, this.uniformBuffer)
|
||||
.ssbo(1, this.chunkPosBuffer);
|
||||
|
||||
private GlTexture depthBuffer = new GlTexture().store(GL_DEPTH_COMPONENT24, 1, 128, 128);
|
||||
private final GlFramebuffer frameBuffer = new GlFramebuffer().bind(GL_DEPTH_ATTACHMENT, this.depthBuffer).verify();
|
||||
|
||||
public ChunkBoundRenderer() {
|
||||
this.chunk2idx.defaultReturnValue(-1);
|
||||
}
|
||||
|
||||
public void addChunk(long pos) {
|
||||
if (this.chunk2idx.size() >= MAX_CHUNK_COUNT) {
|
||||
throw new IllegalStateException("At capacity");
|
||||
}
|
||||
if (this.chunk2idx.containsKey(pos)) {
|
||||
throw new IllegalArgumentException("Chunk already in map");
|
||||
}
|
||||
@@ -75,22 +98,62 @@ public class ChunkBoundRenderer {
|
||||
|
||||
//Bind and render, changing as little gl state as possible so that the caller may configure how it wants to render
|
||||
public void render(Viewport<?> viewport) {
|
||||
if (this.depthBuffer.getWidth() != viewport.width || this.depthBuffer.getHeight() != viewport.height) {
|
||||
this.depthBuffer.free();
|
||||
this.depthBuffer = new GlTexture().store(GL_DEPTH_COMPONENT24, 1, viewport.width, viewport.height);
|
||||
this.frameBuffer.bind(GL_DEPTH_ATTACHMENT, this.depthBuffer).verify();
|
||||
}
|
||||
|
||||
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 128);
|
||||
viewport.MVP.getToAddress(ptr); ptr += 4*4*4;
|
||||
viewport.section.getToAddress(ptr); ptr += 4*4;
|
||||
viewport.innerTranslation.getToAddress(ptr); ptr += 4*4;
|
||||
long matPtr = ptr; ptr += 4*4*4;
|
||||
{//This is recomputed to be in chunk section space not worldsection
|
||||
int sx = MathHelper.floor(viewport.cameraX) >> 4;
|
||||
int sy = MathHelper.floor(viewport.cameraY) >> 4;
|
||||
int sz = MathHelper.floor(viewport.cameraZ) >> 4;
|
||||
new Vector3i(sx, sy, sz).getToAddress(ptr); ptr += 4*4;
|
||||
|
||||
viewport.MVP.translate(
|
||||
-(float) (viewport.cameraX - (sx << 4)),
|
||||
-(float) (viewport.cameraY - (sy << 4)),
|
||||
-(float) (viewport.cameraZ - (sz << 4)),
|
||||
new Matrix4f()).getToAddress(matPtr);
|
||||
}
|
||||
UploadStream.INSTANCE.commit();
|
||||
|
||||
|
||||
//TODO: NOTE: need to reverse the winding order since we want the back faces of the AABB, not the front
|
||||
//this.cullShader.bind();
|
||||
{
|
||||
glFrontFace(GL_CW);//Reverse winding order
|
||||
|
||||
//"reverse depth buffer" it goes from 0->1 where 1 is far away
|
||||
glClearNamedFramebufferfv(this.frameBuffer.id, GL_DEPTH, 0, new float[]{0});
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GREATER);
|
||||
}
|
||||
|
||||
glBindVertexArray(RenderService.STATIC_VAO);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.chunkPosBuffer.id);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, this.frameBuffer.id);
|
||||
this.rasterShader.bind();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE.id());
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 6*2*3, GL_UNSIGNED_BYTE, SharedIndexBuffer.CUBE_INDEX_OFFSET, this.chunk2idx.size());
|
||||
|
||||
{
|
||||
glFrontFace(GL_CCW);//Restore winding order
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
//TODO: check this is correct
|
||||
glEnable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
public void free() {
|
||||
this.depthBuffer.free();
|
||||
this.frameBuffer.free();
|
||||
|
||||
this.rasterShader.free();
|
||||
this.uniformBuffer.free();
|
||||
this.chunkPosBuffer.free();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.cortex.voxy.client.mixin.sodium;
|
||||
|
||||
import me.cortex.voxy.client.VoxyClientInstance;
|
||||
import me.cortex.voxy.client.config.VoxyConfig;
|
||||
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
|
||||
import me.cortex.voxy.commonImpl.VoxyCommon;
|
||||
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
@@ -18,13 +19,23 @@ public class MixinRenderSectionManager {
|
||||
|
||||
@Inject(method = "onChunkAdded", at = @At("HEAD"))
|
||||
private void voxy$trackChunkAdd(int x, int z, CallbackInfo ci) {
|
||||
if (this.level.worldRenderer != null) {
|
||||
var system = ((IGetVoxyRenderSystem)(this.level.worldRenderer)).getVoxyRenderSystem();
|
||||
if (system != null) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onChunkRemoved", at = @At("HEAD"))
|
||||
private void voxy$trackChunkRemove(int x, int z, CallbackInfo ci) {
|
||||
if (this.level.worldRenderer != null) {
|
||||
var system = ((IGetVoxyRenderSystem)(this.level.worldRenderer)).getVoxyRenderSystem();
|
||||
if (system != null) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onChunkRemoved", at = @At("HEAD"))
|
||||
private void injectIngest(int x, int z, CallbackInfo ci) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
layout(early_fragment_tests) in;
|
||||
|
||||
void main() {}
|
||||
@@ -0,0 +1,21 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec2 uv;
|
||||
layout(binding = 0, std140) uniform SceneUniform {
|
||||
mat4 MVP;
|
||||
ivec4 section;
|
||||
};
|
||||
|
||||
layout(binding = 1, std430) restrict readonly buffer ChunkPosBuffer {
|
||||
ivec2[] chunkPos;
|
||||
};
|
||||
|
||||
void main() {
|
||||
ivec3 cubeCornerI = ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1);
|
||||
cubeCornerI.xz += chunkPos[gl_InstanceID];
|
||||
//Expand the y height to be big (will be +- 8192)
|
||||
//TODO: make it W.R.T world height and offsets
|
||||
cubeCornerI.y = cubeCornerI.y*1024-512;
|
||||
cubeCornerI -= section.xyz;
|
||||
gl_Position = MVP * vec4(vec3(cubeCornerI*16), 1);
|
||||
}
|
||||
Reference in New Issue
Block a user