Skip to content

Commit

Permalink
Simplify emitter logic and make it more correct (#1621)
Browse files Browse the repository at this point in the history
* kill ray.emittance (good riddance)

* remove special case for torches so they don't look ridiculous

* rearrange algebra to improve readability
  • Loading branch information
JustinTimeCuber authored Nov 1, 2023
1 parent c91e3e8 commit 24eda0e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 52 deletions.
12 changes: 6 additions & 6 deletions chunky/src/java/se/llbit/chunky/chunk/BlockPalette.java
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@ public static Map<String, Consumer<Block>> getDefaultMaterialProperties() {
}
});
materialProperties.put("minecraft:torch", block -> {
block.emittance = 50.0f;
block.emittance = 1.0f;
});
materialProperties.put("minecraft:wall_torch", block -> {
block.emittance = 50.0f;
block.emittance = 1.0f;
});
materialProperties.put("minecraft:fire", block -> {
block.emittance = 1.0f;
Expand Down Expand Up @@ -449,16 +449,16 @@ public static Map<String, Consumer<Block>> getDefaultMaterialProperties() {
block.emittance = 0.6f;
});
materialProperties.put("minecraft:soul_fire_torch", block -> { // MC 20w06a-20w16a
block.emittance = 35.0f;
block.emittance = 0.6f;
});
materialProperties.put("minecraft:soul_torch", block -> { // MC >= 20w17a
block.emittance = 35.0f;
block.emittance = 0.6f;
});
materialProperties.put("minecraft:soul_fire_wall_torch", block -> { // MC 20w06a-20w16a
block.emittance = 35.0f;
block.emittance = 0.6f;
});
materialProperties.put("minecraft:soul_wall_torch", block -> { // MC >= 20w17a
block.emittance = 35.0f;
block.emittance = 0.6f;
});
materialProperties.put("minecraft:soul_fire", block -> {
block.emittance = 0.6f;
Expand Down
61 changes: 22 additions & 39 deletions chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class PathTracer implements RayTracer {
} else {
ray.setCurrentMaterial(Air.INSTANCE);
}
pathTrace(scene, ray, state, 1, true);
pathTrace(scene, ray, state, true);
}

/**
Expand All @@ -54,7 +54,7 @@ public class PathTracer implements RayTracer {
* @param firstReflection {@code true} if the ray has not yet hit the first
* diffuse or specular reflection
*/
public static boolean pathTrace(Scene scene, Ray ray, WorkerState state, int addEmitted,
public static boolean pathTrace(Scene scene, Ray ray, WorkerState state,
boolean firstReflection) {

boolean hit = false;
Expand Down Expand Up @@ -141,7 +141,7 @@ public static boolean pathTrace(Scene scene, Ray ray, WorkerState state, int add
if (doMetal || (pSpecular > Ray.EPSILON && random.nextFloat() < pSpecular)) {
hit |= doSpecularReflection(ray, next, cumulativeColor, doMetal, random, state, scene);
} else if(random.nextFloat() < pDiffuse) {
hit |= doDiffuseReflection(ray, next, currentMat, cumulativeColor, addEmitted, random, state, scene);
hit |= doDiffuseReflection(ray, next, currentMat, cumulativeColor, random, state, scene);
} else if (n1 != n2) {
hit |= doRefraction(ray, next, currentMat, prevMat, cumulativeColor, n1, n2, pDiffuse, random, state, scene);
} else {
Expand Down Expand Up @@ -204,10 +204,7 @@ public static boolean pathTrace(Scene scene, Ray ray, WorkerState state, int add
private static boolean doSpecularReflection(Ray ray, Ray next, Vector4 cumulativeColor, boolean doMetal, Random random, WorkerState state, Scene scene) {
boolean hit = false;
next.specularReflection(ray, random);
if (pathTrace(scene, next, state, 1, false)) {
ray.emittance.x = ray.color.x * next.emittance.x;
ray.emittance.y = ray.color.y * next.emittance.y;
ray.emittance.z = ray.color.z * next.emittance.z;
if (pathTrace(scene, next, state, false)) {

if (doMetal) {
// use the albedo color as specular color
Expand All @@ -224,20 +221,17 @@ private static boolean doSpecularReflection(Ray ray, Ray next, Vector4 cumulativ
return hit;
}

private static boolean doDiffuseReflection(Ray ray, Ray next, Material currentMat, Vector4 cumulativeColor, int addEmitted, Random random, WorkerState state, Scene scene) {
private static boolean doDiffuseReflection(Ray ray, Ray next, Material currentMat, Vector4 cumulativeColor, Random random, WorkerState state, Scene scene) {
boolean hit = false;
float emittance = 0;
Vector3 emittance = new Vector3();
Vector4 indirectEmitterColor = new Vector4(0, 0, 0, 0);

if (scene.emittersEnabled && (!scene.isPreventNormalEmitterWithSampling() || scene.getEmitterSamplingStrategy() == EmitterSamplingStrategy.NONE || ray.depth == 0) && currentMat.emittance > Ray.EPSILON) {

emittance = addEmitted;
ray.emittance.x = ray.color.x * ray.color.x *
currentMat.emittance * scene.emitterIntensity;
ray.emittance.y = ray.color.y * ray.color.y *
currentMat.emittance * scene.emitterIntensity;
ray.emittance.z = ray.color.z * ray.color.z *
currentMat.emittance * scene.emitterIntensity;
// Quadratic emittance mapping, so a pixel that's 50% darker will emit only 25% as much light
// This is arbitrary but gives pretty good results in most cases.
emittance = new Vector3(ray.color.x * ray.color.x, ray.color.y * ray.color.y, ray.color.z * ray.color.z);
emittance.scale(currentMat.emittance * scene.emitterIntensity);

hit = true;
} else if (scene.emittersEnabled && scene.emitterSamplingStrategy != EmitterSamplingStrategy.NONE && scene.getEmitterGrid() != null) {
Expand Down Expand Up @@ -294,14 +288,11 @@ private static boolean doDiffuseReflection(Ray ray, Ray next, Material currentMa
}

next.diffuseReflection(ray, random);
hit = pathTrace(scene, next, state, 0, false) || hit;
hit = pathTrace(scene, next, state, false) || hit;
if (hit) {
cumulativeColor.x += ray.color.x * (emittance + directLightR * scene.sun.emittance.x + (
next.color.x + next.emittance.x) + (indirectEmitterColor.x));
cumulativeColor.y += ray.color.y * (emittance + directLightG * scene.sun.emittance.y + (
next.color.y + next.emittance.y) + (indirectEmitterColor.y));
cumulativeColor.z += ray.color.z * (emittance + directLightB * scene.sun.emittance.z + (
next.color.z + next.emittance.z) + (indirectEmitterColor.z));
cumulativeColor.x += emittance.x + ray.color.x * (directLightR * scene.sun.emittance.x + next.color.x + indirectEmitterColor.x);
cumulativeColor.y += emittance.y + ray.color.y * (directLightG * scene.sun.emittance.y + next.color.y + indirectEmitterColor.y);
cumulativeColor.z += emittance.z + ray.color.z * (directLightB * scene.sun.emittance.z + next.color.z + indirectEmitterColor.z);
} else if (indirectEmitterColor.x > Ray.EPSILON || indirectEmitterColor.y > Ray.EPSILON || indirectEmitterColor.z > Ray.EPSILON) {
hit = true;
cumulativeColor.x += ray.color.x * indirectEmitterColor.x;
Expand All @@ -312,11 +303,11 @@ private static boolean doDiffuseReflection(Ray ray, Ray next, Material currentMa
} else {
next.diffuseReflection(ray, random);

hit = pathTrace(scene, next, state, 0, false) || hit;
hit = pathTrace(scene, next, state, false) || hit;
if (hit) {
cumulativeColor.x += ray.color.x * (emittance + (next.color.x + next.emittance.x) + (indirectEmitterColor.x));
cumulativeColor.y += ray.color.y * (emittance + (next.color.y + next.emittance.y) + (indirectEmitterColor.y));
cumulativeColor.z += ray.color.z * (emittance + (next.color.z + next.emittance.z) + (indirectEmitterColor.z));
cumulativeColor.x += emittance.x + ray.color.x * (next.color.x + indirectEmitterColor.x);
cumulativeColor.y += emittance.y + ray.color.y * (next.color.y + indirectEmitterColor.y);
cumulativeColor.z += emittance.z + ray.color.z * (next.color.z + indirectEmitterColor.z);
} else if (indirectEmitterColor.x > Ray.EPSILON || indirectEmitterColor.y > Ray.EPSILON || indirectEmitterColor.z > Ray.EPSILON) {
hit = true;
cumulativeColor.x += ray.color.x * indirectEmitterColor.x;
Expand All @@ -338,10 +329,7 @@ private static boolean doRefraction(Ray ray, Ray next, Material currentMat, Mate
if (doRefraction && radicand < Ray.EPSILON) {
// Total internal reflection.
next.specularReflection(ray, random);
if (pathTrace(scene, next, state, 1, false)) {
ray.emittance.x = ray.color.x * next.emittance.x;
ray.emittance.y = ray.color.y * next.emittance.y;
ray.emittance.z = ray.color.z * next.emittance.z;
if (pathTrace(scene, next, state, false)) {

cumulativeColor.x += next.color.x;
cumulativeColor.y += next.color.y;
Expand All @@ -362,10 +350,7 @@ private static boolean doRefraction(Ray ray, Ray next, Material currentMat, Mate

if (random.nextFloat() < Rtheta) {
next.specularReflection(ray, random);
if (pathTrace(scene, next, state, 1, false)) {
ray.emittance.x = ray.color.x * next.emittance.x;
ray.emittance.y = ray.color.y * next.emittance.y;
ray.emittance.z = ray.color.z * next.emittance.z;
if (pathTrace(scene, next, state, false)) {

cumulativeColor.x += next.color.x;
cumulativeColor.y += next.color.y;
Expand Down Expand Up @@ -401,7 +386,7 @@ private static boolean doRefraction(Ray ray, Ray next, Material currentMat, Mate
next.o.scaleAdd(Ray.OFFSET, next.d);
}

if (pathTrace(scene, next, state, 1, false)) {
if (pathTrace(scene, next, state, false)) {
// Calculate the color and emittance of the refracted ray
translucentRayColor(scene, ray, next, cumulativeColor, pDiffuse);
hit = true;
Expand All @@ -416,7 +401,7 @@ private static boolean doTransmission(Ray ray, Ray next, Vector4 cumulativeColor
next.set(ray);
next.o.scaleAdd(Ray.OFFSET, next.d);

if (pathTrace(scene, next, state, 1, false)) {
if (pathTrace(scene, next, state, false)) {
// Calculate the color and emittance of the refracted ray
translucentRayColor(scene, ray, next, cumulativeColor, pDiffuse);
hit = true;
Expand Down Expand Up @@ -481,8 +466,6 @@ private static void translucentRayColor(Scene scene, Ray ray, Ray next, Vector4
Vector4 outputColor = new Vector4(0, 0, 0, 0);
outputColor.multiplyEntrywise(new Vector4(rgbTrans, 1), next.color);
cumulativeColor.add(outputColor);
// Use emittance from next ray
ray.emittance.multiplyEntrywise(rgbTrans, next.emittance);
}

private static double reassignTransmissivity(double from, double to, double other, double trans, double cap) {
Expand Down
7 changes: 0 additions & 7 deletions chunky/src/java/se/llbit/math/Ray.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ public class Ray {
*/
public Vector4 color = new Vector4();

/**
* Emittance of previously intersected surface.
*/
public Vector3 emittance = new Vector3();

/**
* Previous material.
*/
Expand Down Expand Up @@ -149,7 +144,6 @@ public void setDefault() {
currentMaterial = Air.INSTANCE;
depth = 0;
color.set(0, 0, 0, 0);
emittance.set(0, 0, 0);
specular = true;
}

Expand All @@ -166,7 +160,6 @@ public void set(Ray other) {
n.set(other.n);
geomN.set(other.geomN);
color.set(0, 0, 0, 0);
emittance.set(0, 0, 0);
specular = other.specular;
}

Expand Down

0 comments on commit 24eda0e

Please sign in to comment.