diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/IntersectionConfig.java b/chunky/src/java/se/llbit/chunky/renderer/scene/IntersectionConfig.java new file mode 100644 index 0000000000..cf9bb3487e --- /dev/null +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/IntersectionConfig.java @@ -0,0 +1,19 @@ +package se.llbit.chunky.renderer.scene; + +public class IntersectionConfig { + public final boolean cloudIntersect; + public final boolean fogIntersect; + public final boolean waterPlaneIntersect; + public final boolean sceneIntersect; + + public IntersectionConfig(boolean cloudIntersect, boolean fogIntersect, boolean waterPlaneIntersect, boolean sceneIntersect) { + this.cloudIntersect = cloudIntersect; + this.fogIntersect = fogIntersect; + this.waterPlaneIntersect = waterPlaneIntersect; + this.sceneIntersect = sceneIntersect; + } + + public static IntersectionConfig defaultIntersect(Scene scene, boolean isRenderPreview) { + return new IntersectionConfig(scene.sky().cloudsEnabled(), !isRenderPreview || scene.getPreviewParticleFog(), scene.isWaterPlaneEnabled(), true); + } +} diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java b/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java index a7163fb132..39e7ea7f0b 100644 --- a/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java @@ -66,7 +66,7 @@ public static boolean pathTrace(Scene scene, Ray ray, WorkerState state, while (true) { - if (!PreviewRayTracer.nextIntersection(scene, ray, true, random)) { + if (!PreviewRayTracer.nextIntersection(scene, ray, random, IntersectionConfig.defaultIntersect(scene, false))) { if (ray.getPrevMaterial().isWater()) { ray.color.set(0, 0, 0, 1); hit = true; @@ -579,7 +579,7 @@ private static void sampleEmitterFace(Scene scene, Ray ray, Grid.EmitterPosition emitterRay.o.scaleAdd(Ray.OFFSET, emitterRay.d); emitterRay.distance += Ray.OFFSET; - PreviewRayTracer.nextIntersection(scene, emitterRay, true, random); + PreviewRayTracer.nextIntersection(scene, emitterRay, random, IntersectionConfig.defaultIntersect(scene, false)); if (Math.abs(emitterRay.distance - distance) < Ray.OFFSET) { double e = Math.abs(emitterRay.d.dot(emitterRay.getNormal())); e /= Math.max(distance * distance, 1); @@ -635,7 +635,7 @@ public static void getDirectLightAttenuation(Scene scene, Ray ray, WorkerState s attenuation.w = 1; while (attenuation.w > 0) { ray.o.scaleAdd(Ray.OFFSET, ray.d); - if (!PreviewRayTracer.nextIntersection(scene, ray, true, state.random)) { + if (!PreviewRayTracer.nextIntersection(scene, ray, state.random, IntersectionConfig.defaultIntersect(scene, false))) { break; } double mult = 1 - ray.color.w; diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java b/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java index cb5059ee81..32be683d0e 100644 --- a/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java @@ -43,7 +43,7 @@ public class PreviewRayTracer implements RayTracer { ray.setCurrentMaterial(Air.INSTANCE); } while (true) { - if (!nextIntersection(scene, ray, scene.getPreviewParticleFog(), state.random)) { + if (!nextIntersection(scene, ray, state.random, IntersectionConfig.defaultIntersect(scene, true))) { if (mapIntersection(scene, ray)) { break; } @@ -70,7 +70,7 @@ public static double skyOcclusion(Scene scene, WorkerState state) { Ray ray = state.ray; double occlusion = 1.0; while (true) { - if (!nextIntersection(scene, ray)) { + if (!nextIntersection(scene, ray, state.random, IntersectionConfig.defaultIntersect(scene, false))) { break; } else { occlusion *= (1 - ray.color.w); @@ -85,28 +85,27 @@ public static double skyOcclusion(Scene scene, WorkerState state) { /** * Find next ray intersection. - * @param particleFog Whether to process particle fog * @param random Used for particle fog, can be null if particleFog is false * @return Next intersection */ - public static boolean nextIntersection(Scene scene, Ray ray, boolean particleFog, Random random) { + public static boolean nextIntersection(Scene scene, Ray ray, Random random, IntersectionConfig config) { ray.setPrevMaterial(ray.getCurrentMaterial(), ray.getCurrentData()); ray.t = Double.POSITIVE_INFINITY; boolean hit = false; - if (scene.sky().cloudsEnabled()) { - hit = scene.sky().cloudIntersection(scene, ray, random); + if (config.cloudIntersect) { + hit |= cloudIntersection(scene, ray, random); } - if (scene.isWaterPlaneEnabled()) { - hit = waterPlaneIntersection(scene, ray) || hit; + if (config.waterPlaneIntersect) { + hit |= waterPlaneIntersection(scene, ray); } - if (particleFog) { - for(FogVolume v : scene.fog.getFogVolumes()) { - hit |= v.intersect(ray, scene, random); - } + if (config.fogIntersect) { + hit |= fogIntersection(scene, ray, random); } - if (scene.intersect(ray)) { + if (config.sceneIntersect) { // Octree tracer handles updating distance. - return true; + if (sceneIntersection(scene, ray)) { + return true; + } } if (hit) { ray.distance += ray.t; @@ -120,7 +119,22 @@ public static boolean nextIntersection(Scene scene, Ray ray, boolean particleFog } public static boolean nextIntersection(Scene scene, Ray ray) { - return nextIntersection(scene, ray, false, null); + return nextIntersection(scene, ray, null, new IntersectionConfig((scene.sky.cloudsEnabled() && !scene.sky.getVolumetricClouds()), false, scene.waterPlaneEnabled, true)); + } + + private static boolean cloudIntersection(Scene scene, Ray ray, Random random) { + return scene.sky.cloudIntersection(scene, ray, random); + } + + private static boolean fogIntersection(Scene scene, Ray ray, Random random) { + if (random == null) { + return false; + } + boolean hit = false; + for(FogVolume v : scene.fog.getFogVolumes()) { + hit |= v.intersect(ray, scene, random); + } + return hit; } private static boolean waterPlaneIntersection(Scene scene, Ray ray) { @@ -152,6 +166,10 @@ private static boolean waterPlaneIntersection(Scene scene, Ray ray) { return false; } + private static boolean sceneIntersection(Scene scene, Ray ray) { + return scene.intersect(ray); + } + // Chunk pattern config private static final double chunkPatternLineWidth = 0.5; // in blocks private static final double chunkPatternLinePosition = 8 - chunkPatternLineWidth / 2; diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java b/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java index e80d838dd0..cdc8cfc111 100644 --- a/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java @@ -1685,7 +1685,9 @@ public boolean traceTarget(Ray ray) { ray.o.x -= origin.x; ray.o.y -= origin.y; ray.o.z -= origin.z; - while (PreviewRayTracer.nextIntersection(this, ray)) { + while (PreviewRayTracer.nextIntersection(this, ray, null, + new IntersectionConfig((sky.cloudsEnabled() && !sky.getVolumetricClouds()), + false, waterPlaneEnabled, true))) { if (ray.getCurrentMaterial() != Air.INSTANCE) { return true; }