|
|
@ -86,20 +86,28 @@ public final class SimpleRenderer implements Renderer {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private @NotNull Color getColor0(@NotNull Scene scene, @NotNull Ray ray, int depth) {
|
|
|
|
private @NotNull Color getColor0(@NotNull Scene scene, @NotNull Ray ray, int depth) {
|
|
|
|
if (depth <= 0) return Color.BLACK;
|
|
|
|
var color = Color.BLACK;
|
|
|
|
|
|
|
|
var attenuation = Color.WHITE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (depth-- > 0) {
|
|
|
|
var optional = scene.hit(ray, new Range(0.001, Double.POSITIVE_INFINITY));
|
|
|
|
var optional = scene.hit(ray, new Range(0.001, Double.POSITIVE_INFINITY));
|
|
|
|
if (optional.isPresent()) {
|
|
|
|
if (optional.isEmpty()) {
|
|
|
|
|
|
|
|
color = Color.add(color, Color.multiply(attenuation, scene.getBackgroundColor(ray)));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var hit = optional.get();
|
|
|
|
var hit = optional.get();
|
|
|
|
var material = hit.material();
|
|
|
|
var material = hit.material();
|
|
|
|
var emitted = material.emitted(hit);
|
|
|
|
var emitted = material.emitted(hit);
|
|
|
|
return material.scatter(ray, hit)
|
|
|
|
var scatter = material.scatter(ray, hit);
|
|
|
|
.map(scatter -> Color.multiply(scatter.attenuation(), getColor0(scene, scatter.ray(), depth - 1)))
|
|
|
|
color = Color.add(color, Color.multiply(attenuation, emitted));
|
|
|
|
.map(color -> Color.add(color, emitted))
|
|
|
|
|
|
|
|
.orElse(emitted);
|
|
|
|
if (scatter.isEmpty()) break;
|
|
|
|
} else {
|
|
|
|
attenuation = Color.multiply(attenuation, scatter.get().attenuation());
|
|
|
|
return scene.getBackgroundColor(ray);
|
|
|
|
ray = scatter.get().ray();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|