Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ public static boolean pathTrace(Scene scene, Ray ray, WorkerState state,
break;
}
ray.depth += 1;

// Russian Roulette
if (!firstReflection && ray.depth >= scene.minRayDepth) {
double max = FastMath.max(ray.color.x, FastMath.max(ray.color.y, ray.color.z));
double p = QuickMath.clamp(max, 0.05, 1.0);
if (random.nextDouble() > p) {
ray.color.set(0, 0, 0, 0);
break;
} else {
ray.color.scale(1 / p);
}
}

Vector4 cumulativeColor = new Vector4(0, 0, 0, 0);
Ray next = new Ray();
float pMetal = currentMat.metalness;
Expand Down
26 changes: 26 additions & 0 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ public class Scene implements JsonSerializable {
* Recursive ray depth limit (not including Russian Roulette).
*/
protected int rayDepth = PersistentSettings.getRayDepthDefault();
/**
* Minimum number of ray bounces before Russian Roulette starts.
*/
protected int minRayDepth = PersistentSettings.getMinRayDepthDefault();
protected String worldPath = "";
protected int worldDimension = 0;
protected RenderMode mode = RenderMode.PREVIEW;
Expand Down Expand Up @@ -1685,13 +1689,32 @@ public synchronized void setRayDepth(int value) {
}
}

/**
* Set the minimum recursive ray depth before Russian Roulette starts
*/
public synchronized void setMinRayDepth(int value) {
value = Math.max(1, value);
if (minRayDepth != value) {
minRayDepth = value;
PersistentSettings.setMinRayDepth(minRayDepth);
refresh();
}
}

/**
* @return Recursive ray depth limit
*/
public int getRayDepth() {
return rayDepth;
}

/**
* @return Minimum ray depth before Russion Roulette is applied
*/
public int getMinRayDepth() {
return minRayDepth;
}

/**
* Clear the scene refresh flag
*/
Expand Down Expand Up @@ -1939,6 +1962,7 @@ public synchronized void copyTransients(Scene other) {
sppTarget = other.sppTarget;
branchCount = other.branchCount;
rayDepth = other.rayDepth;
minRayDepth = other.minRayDepth;
mode = other.mode;
pictureExportFormat = other.pictureExportFormat;
cameraPresets = other.cameraPresets;
Expand Down Expand Up @@ -2624,6 +2648,7 @@ public void setUseCustomWaterColor(boolean value) {
json.add("sppTarget", sppTarget);
json.add("branchCount", branchCount);
json.add("rayDepth", rayDepth);
json.add("minRayDepth", minRayDepth);
json.add("pathTrace", mode != RenderMode.PREVIEW);
json.add("dumpFrequency", dumpFrequency);
json.add("saveSnapshots", saveSnapshots);
Expand Down Expand Up @@ -2880,6 +2905,7 @@ public synchronized void importFromJson(JsonObject json) {
sppTarget = json.get("sppTarget").intValue(sppTarget);
branchCount = json.get("branchCount").intValue(branchCount);
rayDepth = json.get("rayDepth").intValue(rayDepth);
minRayDepth = json.get("minRayDepth").intValue(minRayDepth);
if (!json.get("pathTrace").isUnknown()) {
boolean pathTrace = json.get("pathTrace").boolValue(false);
if (pathTrace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class AdvancedTab extends ScrollPane implements RenderControlsTab, Initia
@FXML private IntegerAdjuster renderThreads;
@FXML private IntegerAdjuster cpuLoad;
@FXML private IntegerAdjuster rayDepth;
@FXML private IntegerAdjuster minRayDepth;
@FXML private IntegerAdjuster branchCount;
@FXML private Button mergeRenderDump;
@FXML private CheckBox shutdown;
Expand Down Expand Up @@ -104,10 +105,15 @@ public void initialize(URL location, ResourceBundle resources) {
controller.getRenderManager().setCPULoad(value);
});
rayDepth.setName("Ray depth");
rayDepth.setTooltip("Sets the minimum recursive ray depth.");
rayDepth.setTooltip("Sets the maximum recursive ray depth.");
rayDepth.setRange(1, 25);
rayDepth.clampMin();
rayDepth.onValueChange(value -> scene.setRayDepth(value));
minRayDepth.setName("Min ray depth");
minRayDepth.setTooltip("Sets the minimum recursive ray depth before Russian Roulette is applied.");
minRayDepth.setRange(1, 25);
minRayDepth.clampMin();
minRayDepth.onValueChange(value -> scene.setMinRayDepth(value));

branchCount.setName("Branch count");
branchCount.setTooltip("Sets the number of rays cast after the first intersection, effectively reusing the first ray that many times." +
Expand Down Expand Up @@ -339,6 +345,7 @@ public void update(Scene scene) {
renderThreads.set(PersistentSettings.getNumThreads());
cpuLoad.set(PersistentSettings.getCPULoad());
rayDepth.set(scene.getRayDepth());
minRayDepth.set(scene.getMinRayDepth());
branchCount.set(scene.getBranchCount());
octreeImplementation.getSelectionModel().select(scene.getOctreeImplementation());
bvhMethod.getSelectionModel().select(scene.getBvhImplementation());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<IntegerAdjuster fx:id="cpuLoad" />
<Separator prefWidth="200.0" />
<IntegerAdjuster fx:id="rayDepth" />
<IntegerAdjuster fx:id="minRayDepth" />
<IntegerAdjuster fx:id="branchCount" />
<Separator layoutX="20.0" layoutY="90.0" prefWidth="200.0" />
<Button fx:id="mergeRenderDump" mnemonicParsing="false" text="Merge render dumps" />
Expand Down
10 changes: 10 additions & 0 deletions lib/src/se/llbit/chunky/PersistentSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public final class PersistentSettings {
public static final double DEFAULT_FOG_BLUE = 1;

public static final int DEFAULT_RAY_DEPTH = 5;
public static final int DEFAULT_MIN_RAY_DEPTH = 3;
public static final int DEFAULT_BRANCH_COUNT = 10;
public static final int DEFAULT_SPP_TARGET = 1000;

Expand Down Expand Up @@ -272,13 +273,22 @@ public static void setRayDepth(int rayDepth) {
save();
}

public static void setMinRayDepth(int rayDepth) {
settings.setInt("minRayDepth", rayDepth);
save();
}

/**
* @return the default configured ray depth
*/
public static int getRayDepthDefault() {
return settings.getInt("rayDepth", DEFAULT_RAY_DEPTH);
}

public static int getMinRayDepthDefault() {
return settings.getInt("minRayDepth", DEFAULT_MIN_RAY_DEPTH);
}

public static int get3DCanvasHeight() {
return settings.getInt("3dcanvas.height", DEFAULT_3D_CANVAS_HEIGHT);
}
Expand Down