Skip to content

Commit

Permalink
fix depth calculation and separate 3D texture size from model size
Browse files Browse the repository at this point in the history
also correctly compute normal in case the
ray immediately hits the model box.
  • Loading branch information
httpdigest committed Jan 7, 2024
1 parent 69c3a86 commit fa3334b
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 20 deletions.
21 changes: 14 additions & 7 deletions res/org/lwjgl/demo/opengl/shader/raymarching.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,31 @@ layout (depth_less) out float gl_FragDepth;
#endif

uniform sampler3D tex;
uniform vec3 size;
uniform mat4 mvp;

in vec3 o;
in vec3 d;

vec3 rayMarch(vec3 o, vec3 d, vec3 ts) {
vec3 rayMarch(vec3 o, vec3 d, vec3 n, vec3 size) {
vec3 ts = vec3(textureSize(tex, 0));
float ti = 0.0;
vec3 p = floor(o), di = vec3(1.0) / d, s = sign(d), t = abs((p + max(s, vec3(0.0)) - o) * di);
int N = int(ts.x + ts.y + ts.z); // <- maximum can only be manhattan distance
int N = int(size.x + size.y + size.z); // <- maximum can only be manhattan distance
vec3 c;
int i;
for (i = 0; i < N; i++) {
if (texture(tex, (p+vec3(0.5))/ts).r > 0.0) {
vec4 cp = mvp * vec4((o+d*t)/ts-vec3(0.5), 1.0);
vec4 cp = mvp * vec4((o+d*ti)/size-vec3(0.5), 1.0);
gl_FragDepth = cp.z / cp.w;
return abs(c);
return n;
}
c = step(t.xyz, t.yzx)*step(t.xyz, t.zxy);
t += di * s * c;
p += s * c;
vec3 ds = s*c;
ti = min(t.x, min(t.y, t.z));
n = -ds;
t += di * ds;
p += ds;
if (any(lessThan(p, vec3(0.0))) || any(greaterThanEqual(p, ts))) {
break;
}
Expand All @@ -40,6 +46,7 @@ vec3 rayMarch(vec3 o, vec3 d, vec3 ts) {
void main(void) {
vec3 ts = vec3(textureSize(tex, 0));
vec3 di = 1.0/d, t = min((vec3(-0.5)-o)*di, (vec3(0.5)-o)*di);
vec3 s = sign(d), n = -s*step(t.yzx, t.xyz)*step(t.zxy, t.xyz);
vec3 p = o + d * max(max(max(t.x, t.y), t.z), 0.0);
fragColor = vec4(rayMarch((p+vec3(0.5))*ts, d*ts, ts), 1.0);
fragColor = vec4(rayMarch((p+vec3(0.5))*size, d*size, n, size), 1.0);
}
36 changes: 23 additions & 13 deletions src/org/lwjgl/demo/opengl/shader/RayMarchingVolumeTexture.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector3i;
import org.lwjgl.BufferUtils;
import org.lwjgl.demo.util.MagicaVoxelLoader;
import org.lwjgl.glfw.*;
Expand All @@ -40,6 +39,7 @@ public class RayMarchingVolumeTexture {
private static class Volume {
int x, y, z;
int w, h, d;
int tw, th, td;
int tex;
byte[] field;
}
Expand All @@ -49,7 +49,7 @@ private static class Volume {
private int height = 768;

private int program;
private int mvpUniform, invModelUniform, camPositionUniform;
private int mvpUniform, invModelUniform, camPositionUniform, sizeUniform;

private GLFWErrorCallback errCallback;
private Callback debugProc;
Expand Down Expand Up @@ -155,7 +155,6 @@ else if (action == GLFW_RELEASE)
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
GL.createCapabilities();
debugProc = GLUtil.setupDebugMessageCallback();
glClearColor(0.1f, 0.15f, 0.23f, 1.0f);
Expand All @@ -166,6 +165,7 @@ else if (action == GLFW_RELEASE)
volumes.add(create3dVolume("org/lwjgl/demo/models/mikelovesrobots_mmmm/scene_house5.vox", 0, 0, 0));
volumes.add(create3dVolume("org/lwjgl/demo/models/mikelovesrobots_mmmm/scene_house6.vox", 140, 0, 0));
createBoxVao();
glfwShowWindow(window);
}
private void createBoxVao() {
int vao = glGenVertexArrays();
Expand All @@ -188,22 +188,32 @@ private void createBoxVao() {
private static int idx(int x, int y, int z, int width, int height) {
return x + width * (y + z * height);
}
private static int nextPowerOfTwo(int v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
return (v | v >> 16) + 1;
}
private Volume create3dVolume(String resource, int x, int y, int z) throws IOException {
int texture = glGenTextures();
glBindTexture(GL_TEXTURE_3D, texture);
Vector3i dims = new Vector3i();
Volume v = new Volume();
v.x = x;
v.y = y;
v.z = z;
try (InputStream is = Objects.requireNonNull(getSystemResourceAsStream(resource))) {
BufferedInputStream bis = new BufferedInputStream(is);
new MagicaVoxelLoader().read(bis, new MagicaVoxelLoader.Callback() {
public void voxel(int x, int y, int z, byte c) {
v.field[idx(x, z, dims.z - 1 - y, dims.x, dims.y)] = c;
v.field[idx(x, z, v.td - 1 - y, v.tw, v.th)] = c;
}
public void size(int x, int y, int z) {
dims.x = x;
dims.y = z;
dims.z = y;
v.field = new byte[x * y * z];
v.tw = nextPowerOfTwo(x);
v.th = nextPowerOfTwo(z);
v.td = nextPowerOfTwo(y);
v.field = new byte[v.tw * v.th * v.td];
v.w = x;
v.h = z;
v.d = y;
Expand All @@ -216,16 +226,14 @@ public void paletteMaterial(int i, MagicaVoxelLoader.Material mat) {
bb.put(v.field);
bb.flip();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, v.w, v.h, v.d, 0, GL_RED, GL_UNSIGNED_BYTE, bb);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, v.tw, v.th, v.td, 0, GL_RED, GL_UNSIGNED_BYTE, bb);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenerateMipmap(GL_TEXTURE_3D);
v.tex = texture;
v.x = x;
v.y = y;
v.z = z;
return v;
}
private void createProgram() throws IOException {
Expand All @@ -248,6 +256,7 @@ private void createProgram() throws IOException {
mvpUniform = glGetUniformLocation(program, "mvp");
invModelUniform = glGetUniformLocation(program, "invModel");
camPositionUniform = glGetUniformLocation(program, "camPosition");
sizeUniform = glGetUniformLocation(program, "size");
int texUniform = glGetUniformLocation(program, "tex");
glUniform1i(texUniform, 0);
glUseProgram(0);
Expand All @@ -259,6 +268,7 @@ private void renderVolume(Volume v) {
glUniformMatrix4fv(mvpUniform, false, mvpMatrix.get(matrixBuffer));
modelMatrix.invert(invModelMatrix);
glUniformMatrix4fv(invModelUniform, false, invModelMatrix.get(matrixBuffer));
glUniform3f(sizeUniform, v.w, v.h, v.d);
glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, 0L);
}
private void loop() {
Expand Down

0 comments on commit fa3334b

Please sign in to comment.