|
|
@ -7,7 +7,6 @@ import eu.jonahbauer.raytracing.render.renderer.pdf.MixtureProbabilityDensityFun
|
|
|
|
import eu.jonahbauer.raytracing.render.spectrum.SampledSpectrum;
|
|
|
|
import eu.jonahbauer.raytracing.render.spectrum.SampledSpectrum;
|
|
|
|
import eu.jonahbauer.raytracing.render.camera.Camera;
|
|
|
|
import eu.jonahbauer.raytracing.render.camera.Camera;
|
|
|
|
import eu.jonahbauer.raytracing.render.canvas.Canvas;
|
|
|
|
import eu.jonahbauer.raytracing.render.canvas.Canvas;
|
|
|
|
import eu.jonahbauer.raytracing.render.spectrum.SampledWavelengths;
|
|
|
|
|
|
|
|
import eu.jonahbauer.raytracing.scene.Scene;
|
|
|
|
import eu.jonahbauer.raytracing.scene.Scene;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
|
|
|
|
|
|
@ -21,10 +20,7 @@ import static eu.jonahbauer.raytracing.Main.DEBUG;
|
|
|
|
public final class SimpleRenderer implements Renderer {
|
|
|
|
public final class SimpleRenderer implements Renderer {
|
|
|
|
private final int sqrtSamplesPerPixel;
|
|
|
|
private final int sqrtSamplesPerPixel;
|
|
|
|
private final int maxDepth;
|
|
|
|
private final int maxDepth;
|
|
|
|
|
|
|
|
private final double gamma;
|
|
|
|
private final int spectralSamples;
|
|
|
|
|
|
|
|
private final SampledSpectrum black;
|
|
|
|
|
|
|
|
private final SampledSpectrum white;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final boolean parallel;
|
|
|
|
private final boolean parallel;
|
|
|
|
private final boolean iterative;
|
|
|
|
private final boolean iterative;
|
|
|
@ -40,10 +36,7 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
private SimpleRenderer(@NotNull Builder builder) {
|
|
|
|
private SimpleRenderer(@NotNull Builder builder) {
|
|
|
|
this.sqrtSamplesPerPixel = (int) Math.sqrt(builder.samplesPerPixel);
|
|
|
|
this.sqrtSamplesPerPixel = (int) Math.sqrt(builder.samplesPerPixel);
|
|
|
|
this.maxDepth = builder.maxDepth;
|
|
|
|
this.maxDepth = builder.maxDepth;
|
|
|
|
|
|
|
|
this.gamma = builder.gamma;
|
|
|
|
this.spectralSamples = builder.spectralSamples;
|
|
|
|
|
|
|
|
this.black = new SampledSpectrum(spectralSamples, 0);
|
|
|
|
|
|
|
|
this.white = new SampledSpectrum(spectralSamples, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.parallel = builder.parallel;
|
|
|
|
this.parallel = builder.parallel;
|
|
|
|
this.iterative = builder.iterative;
|
|
|
|
this.iterative = builder.iterative;
|
|
|
@ -103,8 +96,7 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
int i = 0;
|
|
|
|
int i = 0;
|
|
|
|
for (int sj = 0; sj < sqrtSamplesPerPixel; sj++) {
|
|
|
|
for (int sj = 0; sj < sqrtSamplesPerPixel; sj++) {
|
|
|
|
for (int si = 0; si < sqrtSamplesPerPixel; si++) {
|
|
|
|
for (int si = 0; si < sqrtSamplesPerPixel; si++) {
|
|
|
|
var lambda = SampledWavelengths.uniform(random.nextDouble(), spectralSamples);
|
|
|
|
var ray = camera.cast(x, y, si, sj, sqrtSamplesPerPixel, random);
|
|
|
|
var ray = camera.cast(x, y, si, sj, sqrtSamplesPerPixel, random).with(lambda);
|
|
|
|
|
|
|
|
if (DEBUG) {
|
|
|
|
if (DEBUG) {
|
|
|
|
System.out.println("Casting ray " + ray + " through pixel (" + x + "," + y + ") at subpixel (" + si + "," + sj + ")...");
|
|
|
|
System.out.println("Casting ray " + ray + " through pixel (" + x + "," + y + ") at subpixel (" + si + "," + sj + ")...");
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -124,11 +116,11 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private @NotNull SampledSpectrum getColor0(@NotNull Scene scene, @NotNull Ray ray, int depth, @NotNull RandomGenerator random) {
|
|
|
|
private @NotNull SampledSpectrum getColor0(@NotNull Scene scene, @NotNull Ray ray, int depth, @NotNull RandomGenerator random) {
|
|
|
|
var color = black;
|
|
|
|
var color = SampledSpectrum.BLACK;
|
|
|
|
var attenuation = white;
|
|
|
|
var attenuation = SampledSpectrum.WHITE;
|
|
|
|
|
|
|
|
|
|
|
|
while (depth-- > 0) {
|
|
|
|
while (depth-- > 0) {
|
|
|
|
var optional = scene.hit(ray, random);
|
|
|
|
var optional = scene.hit(ray);
|
|
|
|
if (optional.isEmpty()) {
|
|
|
|
if (optional.isEmpty()) {
|
|
|
|
var background = scene.getBackgroundColor(ray);
|
|
|
|
var background = scene.getBackgroundColor(ray);
|
|
|
|
color = SampledSpectrum.fma(attenuation, background, color);
|
|
|
|
color = SampledSpectrum.fma(attenuation, background, color);
|
|
|
@ -144,7 +136,7 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var material = hit.material();
|
|
|
|
var material = hit.material();
|
|
|
|
var emitted = material.emitted(hit).sample(ray.lambda());
|
|
|
|
var emitted = material.emitted(hit).sample(ray.lambda());
|
|
|
|
if (DEBUG && !black.equals(emitted)) {
|
|
|
|
if (DEBUG && !SampledSpectrum.BLACK.equals(emitted)) {
|
|
|
|
System.out.println(" Emitted: " + emitted);
|
|
|
|
System.out.println(" Emitted: " + emitted);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -221,7 +213,7 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
public static class Builder {
|
|
|
|
public static class Builder {
|
|
|
|
private int samplesPerPixel = 100;
|
|
|
|
private int samplesPerPixel = 100;
|
|
|
|
private int maxDepth = 10;
|
|
|
|
private int maxDepth = 10;
|
|
|
|
private int spectralSamples = 4;
|
|
|
|
private double gamma = 2.0;
|
|
|
|
private boolean parallel = true;
|
|
|
|
private boolean parallel = true;
|
|
|
|
private boolean iterative = false;
|
|
|
|
private boolean iterative = false;
|
|
|
|
|
|
|
|
|
|
|
@ -237,9 +229,9 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
return this;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public @NotNull Builder withSpectralSamples(int samples) {
|
|
|
|
public @NotNull Builder withGamma(double gamma) {
|
|
|
|
if (samples <= 0) throw new IllegalArgumentException("samples must be positive");
|
|
|
|
if (gamma <= 0 || !Double.isFinite(gamma)) throw new IllegalArgumentException("gamma must be positive");
|
|
|
|
this.spectralSamples = samples;
|
|
|
|
this.gamma = gamma;
|
|
|
|
return this;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|