Add proper frustum check
This commit is contained in:
@@ -1,18 +1,41 @@
|
|||||||
package me.cortex.voxy.client.core.rendering;
|
package me.cortex.voxy.client.core.rendering;
|
||||||
|
|
||||||
|
import org.joml.FrustumIntersection;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
public abstract class Viewport <A extends Viewport<A>> {
|
public abstract class Viewport <A extends Viewport<A>> {
|
||||||
|
private static final Field planesField;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
planesField = FrustumIntersection.class.getDeclaredField("planes");
|
||||||
|
planesField.setAccessible(true);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int width;
|
public int width;
|
||||||
public int height;
|
public int height;
|
||||||
public int frameId;
|
public int frameId;
|
||||||
public Matrix4f projection;
|
public Matrix4f projection;
|
||||||
public Matrix4f modelView;
|
public Matrix4f modelView;
|
||||||
|
public final FrustumIntersection frustum = new FrustumIntersection();
|
||||||
|
public final Vector4f[] frustumPlanes;
|
||||||
public double cameraX;
|
public double cameraX;
|
||||||
public double cameraY;
|
public double cameraY;
|
||||||
public double cameraZ;
|
public double cameraZ;
|
||||||
|
|
||||||
protected Viewport() {
|
protected Viewport() {
|
||||||
|
Vector4f[] planes = null;
|
||||||
|
try {
|
||||||
|
planes = (Vector4f[]) planesField.get(this.frustum);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
this.frustumPlanes = planes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void delete() {
|
public final void delete() {
|
||||||
@@ -43,4 +66,9 @@ public abstract class Viewport <A extends Viewport<A>> {
|
|||||||
this.height = height;
|
this.height = height;
|
||||||
return (A) this;
|
return (A) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public A updateFrustum() {
|
||||||
|
this.frustum.set(new Matrix4f(this.projection).mul(this.modelView), false);
|
||||||
|
return (A) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,8 @@ public class VoxyRenderSystem {
|
|||||||
.setProjection(projection)
|
.setProjection(projection)
|
||||||
.setModelView(matrices.peek().getPositionMatrix())
|
.setModelView(matrices.peek().getPositionMatrix())
|
||||||
.setCamera(cameraX, cameraY, cameraZ)
|
.setCamera(cameraX, cameraY, cameraZ)
|
||||||
.setScreenSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight);
|
.setScreenSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight)
|
||||||
|
.updateFrustum();
|
||||||
viewport.frameId++;
|
viewport.frameId++;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,14 @@ import me.cortex.voxy.client.core.rendering.Viewport;
|
|||||||
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
|
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
|
||||||
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import org.joml.FrustumIntersection;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
import org.joml.Vector4f;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import static me.cortex.voxy.client.core.rendering.PrintfDebugUtil.PRINTF_processor;
|
import static me.cortex.voxy.client.core.rendering.PrintfDebugUtil.PRINTF_processor;
|
||||||
import static org.lwjgl.opengl.GL11.*;
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
import static org.lwjgl.opengl.GL12.GL_UNPACK_IMAGE_HEIGHT;
|
import static org.lwjgl.opengl.GL12.GL_UNPACK_IMAGE_HEIGHT;
|
||||||
@@ -116,6 +120,14 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
.ssboIf("STATISTICS_BUFFER_BINDING", this.statisticsBuffer);
|
.ssboIf("STATISTICS_BUFFER_BINDING", this.statisticsBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void setFrustum(Viewport<?> viewport, long ptr) {
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
var plane = viewport.frustumPlanes[i];
|
||||||
|
plane.getToAddress(ptr); ptr += 4*4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void uploadUniform(Viewport<?> viewport) {
|
private void uploadUniform(Viewport<?> viewport) {
|
||||||
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 1024);
|
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 1024);
|
||||||
int sx = MathHelper.floor(viewport.cameraX)>>5;
|
int sx = MathHelper.floor(viewport.cameraX)>>5;
|
||||||
@@ -135,6 +147,8 @@ public class HierarchicalOcclusionTraverser {
|
|||||||
|
|
||||||
MemoryUtil.memPutFloat(ptr, viewport.height); ptr += 4;
|
MemoryUtil.memPutFloat(ptr, viewport.height); ptr += 4;
|
||||||
|
|
||||||
|
setFrustum(viewport, ptr); ptr += 4*4*6;
|
||||||
|
|
||||||
MemoryUtil.memPutInt(ptr, (int) (this.renderList.size()/4-1)); ptr += 4;
|
MemoryUtil.memPutInt(ptr, (int) (this.renderList.size()/4-1)); ptr += 4;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
14
src/main/resources/assets/voxy/shaders/lod/frustum.glsl
Normal file
14
src/main/resources/assets/voxy/shaders/lod/frustum.glsl
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
struct Frustum {
|
||||||
|
vec4 planes[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
bool testPlane(vec4 plane, vec3 base, float size) {
|
||||||
|
return dot(plane.xyz, base+mix(vec3(size), vec3(0), lessThan(plane.xyz, vec3(0)))) >= -plane.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: optimize this, this can be done by computing the base point value, then multiplying and adding a seperate value by the size
|
||||||
|
bool outsideFrustum(in Frustum frustum, vec3 pos, float size) {
|
||||||
|
return !(testPlane(frustum.planes[0], pos, size) && testPlane(frustum.planes[1], pos, size) &&
|
||||||
|
testPlane(frustum.planes[2], pos, size) && testPlane(frustum.planes[3], pos, size) &&
|
||||||
|
testPlane(frustum.planes[4], pos, size));//Dont need to test far plane
|
||||||
|
}
|
||||||
@@ -58,13 +58,16 @@ void setupScreenspace(in UnpackedNode node) {
|
|||||||
+ (transform.worldPos.xyz-camChunkPos))-camSubChunk);
|
+ (transform.worldPos.xyz-camChunkPos))-camSubChunk);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//TODO: AABB SIZES not just a max cube
|
|
||||||
|
|
||||||
//vec3 minPos = minSize + basePos;
|
|
||||||
//vec3 maxPos = maxSize + basePos;
|
|
||||||
|
|
||||||
vec3 basePos = vec3(((node.pos<<node.lodLevel)-camSecPos)<<5)-camSubSecPos;
|
vec3 basePos = vec3(((node.pos<<node.lodLevel)-camSecPos)<<5)-camSubSecPos;
|
||||||
|
|
||||||
|
insideFrustum = !outsideFrustum(frustum, basePos, float(32<<node.lodLevel));
|
||||||
|
|
||||||
|
//Fast exit
|
||||||
|
if (!insideFrustum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vec4 P000 = VP * vec4(basePos, 1);
|
vec4 P000 = VP * vec4(basePos, 1);
|
||||||
mat3x4 Axis = mat3x4(VP) * float(32<<node.lodLevel);
|
mat3x4 Axis = mat3x4(VP) * float(32<<node.lodLevel);
|
||||||
|
|
||||||
@@ -76,13 +79,6 @@ void setupScreenspace(in UnpackedNode node) {
|
|||||||
vec4 P011 = Axis[1] + P001;
|
vec4 P011 = Axis[1] + P001;
|
||||||
vec4 P111 = Axis[1] + P101;
|
vec4 P111 = Axis[1] + P101;
|
||||||
|
|
||||||
insideFrustum = checkPointInView(P000) || checkPointInView(P100) || checkPointInView(P001) || checkPointInView(P101) ||
|
|
||||||
checkPointInView(P010) || checkPointInView(P110) || checkPointInView(P011) || checkPointInView(P111);
|
|
||||||
|
|
||||||
//Fast exit
|
|
||||||
if (!insideFrustum) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Perspective divide + convert to screenspace (i.e. range 0->1 if within viewport)
|
//Perspective divide + convert to screenspace (i.e. range 0->1 if within viewport)
|
||||||
vec3 p000 = (P000.xyz/P000.w) * 0.5f + 0.5f;
|
vec3 p000 = (P000.xyz/P000.w) * 0.5f + 0.5f;
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
#define LOCAL_SIZE (1<<LOCAL_SIZE_BITS)
|
#define LOCAL_SIZE (1<<LOCAL_SIZE_BITS)
|
||||||
layout(local_size_x=LOCAL_SIZE) in;//, local_size_y=1
|
layout(local_size_x=LOCAL_SIZE) in;//, local_size_y=1
|
||||||
|
|
||||||
|
#import <voxy:lod/frustum.glsl>
|
||||||
|
|
||||||
layout(binding = SCENE_UNIFORM_BINDING, std140) uniform SceneUniform {
|
layout(binding = SCENE_UNIFORM_BINDING, std140) uniform SceneUniform {
|
||||||
mat4 VP;
|
mat4 VP;
|
||||||
ivec3 camSecPos;
|
ivec3 camSecPos;
|
||||||
float screenW;
|
float screenW;
|
||||||
vec3 camSubSecPos;
|
vec3 camSubSecPos;
|
||||||
float screenH;
|
float screenH;
|
||||||
|
Frustum frustum;
|
||||||
uint renderQueueMaxSize;
|
uint renderQueueMaxSize;
|
||||||
float minSSS;
|
float minSSS;
|
||||||
uint frameId;
|
uint frameId;
|
||||||
|
|||||||
Reference in New Issue
Block a user