Skip to content

Commit

Permalink
Implement multiple cloud layers
Browse files Browse the repository at this point in the history
  • Loading branch information
Peregrine05 committed Oct 17, 2023
1 parent 217df7f commit b7b1121
Show file tree
Hide file tree
Showing 20 changed files with 985 additions and 582 deletions.
542 changes: 542 additions & 0 deletions chunky/src/java/se/llbit/chunky/renderer/scene/CloudLayer.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class CuboidFogVolume extends FogVolume {
private AABB aabb;

@Override
public boolean intersect(Ray ray, Scene scene, Random random) {
public boolean intersect(Scene scene, Ray ray, Random random) {
double distance;
double fogPenetrated = -FastMath.log(1 - random.nextDouble());
double fogDistance = fogPenetrated / density;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public ExponentialFogVolume(Vector3 color, double density) {
}

@Override
public boolean intersect(Ray ray, Scene scene, Random random) {
public boolean intersect(Scene scene, Ray ray, Random random) {
// Amount of fog the ray should pass through before being scattered
// Sampled from an exponential distribution
double fogPenetrated = -FastMath.log(1 - random.nextDouble());
Expand Down
27 changes: 14 additions & 13 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Fog.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,17 @@ private double sampleLayeredScatterOffset(Random random, double y1, double y2, d
return (offsetY - y1) / clampDy(dy);
}

public boolean particleFogIntersection(Scene scene, Ray ray, Random random) {
if (random == null) {
return false;
}
boolean hit = false;
for (FogVolume v : volumes) {
hit |= v.intersect(scene, ray, random);
}
return hit;
}

@Override public JsonObject toJson() {
JsonObject fogObj = new JsonObject();
fogObj.add("mode", mode.name());
Expand All @@ -249,11 +260,7 @@ private double sampleLayeredScatterOffset(Random random, double y1, double y2, d
jsonVolumes.add(volume.toJson());
}
fogObj.add("volumes", jsonVolumes);
JsonObject colorObj = new JsonObject();
colorObj.add("red", fogColor.x);
colorObj.add("green", fogColor.y);
colorObj.add("blue", fogColor.z);
fogObj.add("color", colorObj);
fogObj.add("color", ColorUtil.rgbToJson(fogColor));
fogObj.add("fastFog", fastFog);
return fogObj;
}
Expand All @@ -276,10 +283,7 @@ public void importFromJson(JsonObject json, Scene scene) {
fogVolume.importFromJson(jsonVolumeObject);
addVolume(fogVolume);
}
JsonObject colorObj = json.get("color").object();
fogColor.x = colorObj.get("red").doubleValue(fogColor.x);
fogColor.y = colorObj.get("green").doubleValue(fogColor.y);
fogColor.z = colorObj.get("blue").doubleValue(fogColor.z);
fogColor.set(ColorUtil.jsonToRGB(json.get("color").object()));
fastFog = json.get("fastFog").boolValue(fastFog);
}

Expand All @@ -289,10 +293,7 @@ public void importFromLegacy(JsonObject json) {
skyFogDensity = json.get("skyFogDensity").doubleValue(skyFogDensity);
layers.clear();
volumes.clear();
JsonObject colorObj = json.get("fogColor").object();
fogColor.x = colorObj.get("red").doubleValue(fogColor.x);
fogColor.y = colorObj.get("green").doubleValue(fogColor.y);
fogColor.z = colorObj.get("blue").doubleValue(fogColor.z);
fogColor.set(ColorUtil.jsonToRGB(json.get("fogColor").asObject()));
fastFog = json.get("fastFog").boolValue(fastFog);
}

Expand Down
35 changes: 7 additions & 28 deletions chunky/src/java/se/llbit/chunky/renderer/scene/FogVolume.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package se.llbit.chunky.renderer.scene;

import org.apache.commons.math3.util.FastMath;
import se.llbit.chunky.world.Material;
import se.llbit.chunky.world.VolumeMaterial;
import se.llbit.chunky.world.material.ParticleFogMaterial;
import se.llbit.json.JsonObject;
import se.llbit.math.ColorUtil;
import se.llbit.math.Ray;
import se.llbit.math.Vector3;
import se.llbit.util.JsonSerializable;
Expand All @@ -14,27 +15,12 @@ public abstract class FogVolume implements JsonSerializable {
protected FogVolumeType type;
protected Vector3 color;
protected double density;
protected Material material = new ParticleFogMaterial();
protected VolumeMaterial material = new ParticleFogMaterial();

public abstract boolean intersect(Ray ray, Scene scene, Random random);
public abstract boolean intersect(Scene scene, Ray ray, Random random);

public void setRandomNormal(Ray ray, Random random) {
Vector3 a1 = new Vector3();
a1.cross(ray.d, new Vector3(0, 1, 0));
a1.normalize();
Vector3 a2 = new Vector3();
a2.cross(ray.d, a1);
// get random point on unit disk
double x1 = random.nextDouble();
double x2 = random.nextDouble();
double r = FastMath.sqrt(x1);
double theta = 2 * Math.PI * x2;
double t1 = r * FastMath.cos(theta);
double t2 = r * FastMath.sin(theta);
a1.scale(t1);
a1.scaleAdd(t2, a2);
a1.scaleAdd(-Math.sqrt(1 - a1.lengthSquared()), ray.d);
ray.setNormal(a1);
material.setRandomSphericalNormal(ray, random);
}

public void setRayMaterialAndColor(Ray ray) {
Expand Down Expand Up @@ -88,11 +74,7 @@ public FogVolumeType getType() {
public JsonObject toJson() {
JsonObject properties = volumeSpecificPropertiesToJson();
properties.add("type", type.name());
JsonObject colorObj = new JsonObject();
colorObj.add("red", color.x);
colorObj.add("green", color.y);
colorObj.add("blue", color.z);
properties.add("color", colorObj);
properties.add("color", ColorUtil.rgbToJson(color));
properties.add("density", density);
properties.add("materialProperties", materialPropertiesToJson());
return properties;
Expand All @@ -108,10 +90,7 @@ protected JsonObject materialPropertiesToJson() {
protected abstract void importVolumeSpecificProperties(JsonObject jsonObject);

public void importFromJson(JsonObject json) {
JsonObject colorObj = json.get("color").object();
color.x = colorObj.get("red").doubleValue(color.x);
color.y = colorObj.get("green").doubleValue(color.y);
color.z = colorObj.get("blue").doubleValue(color.z);
color.set(ColorUtil.jsonToRGB(json.get("color").asObject()));
density = json.get("density").doubleValue(Scene.DEFAULT_FOG_DENSITY);
JsonObject materialProperties = json.get("materialProperties").object();
importMaterialProperties(materialProperties);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ public IntersectionConfig(boolean cloudIntersect, boolean fogIntersect, boolean
}

public static IntersectionConfig defaultIntersect(Scene scene, boolean isRenderPreview) {
return new IntersectionConfig(scene.sky().cloudsEnabled(), !isRenderPreview || scene.getPreviewParticleFog(), scene.isWaterPlaneEnabled(), true);
return new IntersectionConfig(true, !isRenderPreview || scene.getPreviewParticleFog(), scene.isWaterPlaneEnabled(), true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public LayerFogVolume(Vector3 color, double density) {
}

@Override
public boolean intersect(Ray ray, Scene scene, Random random) {
public boolean intersect(Scene scene, Ray ray, Random random) {
// Amount of fog the ray should pass through before being scattered
// Sampled from an exponential distribution
double fogPenetrated = -Math.log(1 - random.nextDouble());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,22 +119,15 @@ public static boolean nextIntersection(Scene scene, Ray ray, Random random, Inte
}

public static boolean nextIntersection(Scene scene, Ray ray) {
return nextIntersection(scene, ray, null, new IntersectionConfig((scene.sky.cloudsEnabled() && !scene.sky.getVolumetricClouds()), false, scene.waterPlaneEnabled, true));
return nextIntersection(scene, ray, null, new IntersectionConfig(true, 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;
return scene.fog.particleFogIntersection(scene, ray, random);
}

private static boolean waterPlaneIntersection(Scene scene, Ray ray) {
Expand Down
13 changes: 3 additions & 10 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ public boolean traceTarget(Ray ray) {
ray.o.y -= origin.y;
ray.o.z -= origin.z;
while (PreviewRayTracer.nextIntersection(this, ray, null,
new IntersectionConfig((sky.cloudsEnabled() && !sky.getVolumetricClouds()),
new IntersectionConfig(true,
false, waterPlaneEnabled, true))) {
if (ray.getCurrentMaterial() != Air.INSTANCE) {
return true;
Expand Down Expand Up @@ -2658,11 +2658,7 @@ public void setUseCustomWaterColor(boolean value) {
json.add("waterVisibility", waterVisibility);
json.add("useCustomWaterColor", useCustomWaterColor);
if (useCustomWaterColor) {
JsonObject colorObj = new JsonObject();
colorObj.add("red", waterColor.x);
colorObj.add("green", waterColor.y);
colorObj.add("blue", waterColor.z);
json.add("waterColor", colorObj);
json.add("waterColor", ColorUtil.rgbToJson(waterColor));
}
waterShading.save(json);
json.add("fog", fog.toJson());
Expand Down Expand Up @@ -2940,10 +2936,7 @@ public synchronized void importFromJson(JsonObject json) {
waterVisibility = json.get("waterVisibility").doubleValue(waterVisibility);
useCustomWaterColor = json.get("useCustomWaterColor").boolValue(useCustomWaterColor);
if (useCustomWaterColor) {
JsonObject colorObj = json.get("waterColor").object();
waterColor.x = colorObj.get("red").doubleValue(waterColor.x);
waterColor.y = colorObj.get("green").doubleValue(waterColor.y);
waterColor.z = colorObj.get("blue").doubleValue(waterColor.z);
waterColor.set(ColorUtil.jsonToRGB(json.get("waterColor").asObject()));
}
String waterShader = json.get("waterShader").stringValue("SIMPLEX");
if(waterShader.equals("LEGACY"))
Expand Down
Loading

0 comments on commit b7b1121

Please sign in to comment.