add RandomGenerator parameter to Hittable#hit
This commit is contained in:
parent
9b72909d27
commit
871c837c34
@ -128,7 +128,7 @@ public final class SimpleRenderer implements Renderer {
|
|||||||
var attenuation = white;
|
var attenuation = white;
|
||||||
|
|
||||||
while (depth-- > 0) {
|
while (depth-- > 0) {
|
||||||
var optional = scene.hit(ray);
|
var optional = scene.hit(ray, random);
|
||||||
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);
|
||||||
|
@ -9,15 +9,16 @@ import eu.jonahbauer.raytracing.scene.transform.Translate;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public interface Hittable {
|
public interface Hittable {
|
||||||
@NotNull Range FORWARD = new Range(0.001, Double.POSITIVE_INFINITY);
|
@NotNull Range FORWARD = new Range(0.001, Double.POSITIVE_INFINITY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #hit(Ray, Range)
|
* @see #hit(Ray, Range, RandomGenerator)
|
||||||
*/
|
*/
|
||||||
default @NotNull Optional<HitResult> hit(@NotNull Ray ray) {
|
default @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull RandomGenerator random) {
|
||||||
return hit(ray, FORWARD);
|
return hit(ray, FORWARD, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +32,7 @@ public interface Hittable {
|
|||||||
* @return the result of the hit test, containing (among others) the value {@code t} such that {@code ray.at(t)} is
|
* @return the result of the hit test, containing (among others) the value {@code t} such that {@code ray.at(t)} is
|
||||||
* a point on {@code this} hittable
|
* a point on {@code this} hittable
|
||||||
*/
|
*/
|
||||||
@NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range);
|
@NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @NotNull RandomGenerator random);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@return the axis-aligned bounding box of this hittable}
|
* {@return the axis-aligned bounding box of this hittable}
|
||||||
|
@ -12,6 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public final class Scene extends HittableCollection {
|
public final class Scene extends HittableCollection {
|
||||||
private final @NotNull HittableCollection objects;
|
private final @NotNull HittableCollection objects;
|
||||||
@ -42,8 +43,8 @@ public final class Scene extends HittableCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(@NotNull Ray ray, @NotNull State state) {
|
public void hit(@NotNull Ray ray, @NotNull State state, @NotNull RandomGenerator random) {
|
||||||
objects.hit(ray, state);
|
objects.hit(ray, state, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -7,9 +7,11 @@ import eu.jonahbauer.raytracing.render.material.Material;
|
|||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import eu.jonahbauer.raytracing.scene.Hittable;
|
import eu.jonahbauer.raytracing.scene.Hittable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public abstract class Hittable2D implements Hittable {
|
public abstract class Hittable2D implements Hittable {
|
||||||
protected final @NotNull Vec3 origin;
|
protected final @NotNull Vec3 origin;
|
||||||
@ -36,7 +38,7 @@ public abstract class Hittable2D implements Hittable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @Nullable RandomGenerator random) {
|
||||||
var denominator = ray.direction().dot(normal);
|
var denominator = ray.direction().dot(normal);
|
||||||
if (Math.abs(denominator) < 1e-8) return Optional.empty(); // parallel
|
if (Math.abs(denominator) < 1e-8) return Optional.empty(); // parallel
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ public final class Box implements Hittable, Target {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @Nullable RandomGenerator random) {
|
||||||
// based on AABB#hit with additional detection of the side hit
|
// based on AABB#hit with additional detection of the side hit
|
||||||
var origin = ray.origin();
|
var origin = ray.origin();
|
||||||
var direction = ray.direction();
|
var direction = ray.direction();
|
||||||
@ -103,13 +103,13 @@ public final class Box implements Hittable, Target {
|
|||||||
t = tmin;
|
t = tmin;
|
||||||
side = entry;
|
side = entry;
|
||||||
frontFace = true;
|
frontFace = true;
|
||||||
material = materials[side.ordinal()];
|
material = materials[entry.ordinal()];
|
||||||
normal = side.normal;
|
normal = side.normal;
|
||||||
} else if (range.surrounds(tmax) && materials[exit.ordinal()] != null) {
|
} else if (range.surrounds(tmax) && materials[exit.ordinal()] != null) {
|
||||||
t = tmax;
|
t = tmax;
|
||||||
side = exit;
|
side = exit;
|
||||||
frontFace = false;
|
frontFace = false;
|
||||||
material = materials[side.ordinal()];
|
material = materials[exit.ordinal()];
|
||||||
normal = side.normal.neg();
|
normal = side.normal.neg();
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
@ -130,7 +130,7 @@ public final class Box implements Hittable, Target {
|
|||||||
@Override
|
@Override
|
||||||
public double getProbabilityDensity(@NotNull Vec3 origin, @NotNull Vec3 direction) {
|
public double getProbabilityDensity(@NotNull Vec3 origin, @NotNull Vec3 direction) {
|
||||||
if (contains(origin)) return 1 / (4 * Math.PI);
|
if (contains(origin)) return 1 / (4 * Math.PI);
|
||||||
if (hit(new Ray(origin, direction)).isEmpty()) return 0;
|
if (hit(new Ray(origin, direction), null).isEmpty()) return 0;
|
||||||
|
|
||||||
var solidAngle = 0d;
|
var solidAngle = 0d;
|
||||||
for (var s : Side.values()) {
|
for (var s : Side.values()) {
|
||||||
|
@ -10,15 +10,16 @@ import eu.jonahbauer.raytracing.scene.Hittable;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public record ConstantMedium(@NotNull Hittable boundary, double density, @NotNull IsotropicMaterial material) implements Hittable {
|
public record ConstantMedium(@NotNull Hittable boundary, double density, @NotNull IsotropicMaterial material) implements Hittable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @NotNull RandomGenerator random) {
|
||||||
var hit1 = boundary.hit(ray, Range.UNIVERSE);
|
var hit1 = boundary.hit(ray, Range.UNIVERSE, random);
|
||||||
if (hit1.isEmpty()) return Optional.empty();
|
if (hit1.isEmpty()) return Optional.empty();
|
||||||
|
|
||||||
var hit2 = boundary.hit(ray, new Range(hit1.get().t() + 0.0001, Double.POSITIVE_INFINITY));
|
var hit2 = boundary.hit(ray, new Range(hit1.get().t() + 0.0001, Double.POSITIVE_INFINITY), random);
|
||||||
if (hit2.isEmpty()) return Optional.empty();
|
if (hit2.isEmpty()) return Optional.empty();
|
||||||
|
|
||||||
var tmin = Math.max(range.min(), hit1.get().t());
|
var tmin = Math.max(range.min(), hit1.get().t());
|
||||||
@ -28,7 +29,7 @@ public record ConstantMedium(@NotNull Hittable boundary, double density, @NotNul
|
|||||||
|
|
||||||
var length = ray.direction().length();
|
var length = ray.direction().length();
|
||||||
var distance = length * (tmax - tmin);
|
var distance = length * (tmax - tmin);
|
||||||
var hitDistance = - Math.log(Math.random()) / density;
|
var hitDistance = - Math.log(random.nextDouble()) / density;
|
||||||
if (hitDistance > distance) return Optional.empty();
|
if (hitDistance > distance) return Optional.empty();
|
||||||
|
|
||||||
var t = tmin + hitDistance / length;
|
var t = tmin + hitDistance / length;
|
||||||
|
@ -9,6 +9,7 @@ import eu.jonahbauer.raytracing.scene.HitResult;
|
|||||||
import eu.jonahbauer.raytracing.scene.Hittable;
|
import eu.jonahbauer.raytracing.scene.Hittable;
|
||||||
import eu.jonahbauer.raytracing.scene.Target;
|
import eu.jonahbauer.raytracing.scene.Target;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -40,7 +41,7 @@ public final class Sphere implements Hittable, Target {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @Nullable RandomGenerator random) {
|
||||||
var t = hit0(ray, range);
|
var t = hit0(ray, range);
|
||||||
if (Double.isNaN(t)) return Optional.empty();
|
if (Double.isNaN(t)) return Optional.empty();
|
||||||
|
|
||||||
|
@ -2,10 +2,8 @@ package eu.jonahbauer.raytracing.scene.transform;
|
|||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Range;
|
import eu.jonahbauer.raytracing.math.Range;
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.math.Vec3;
|
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import eu.jonahbauer.raytracing.scene.Hittable;
|
import eu.jonahbauer.raytracing.scene.Hittable;
|
||||||
import eu.jonahbauer.raytracing.scene.Target;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -24,7 +22,7 @@ public abstract class Transform implements Hittable {
|
|||||||
protected abstract @NotNull HitResult transform(@NotNull HitResult result);
|
protected abstract @NotNull HitResult transform(@NotNull HitResult result);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
public final @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @NotNull RandomGenerator random) {
|
||||||
return object.hit(transform(ray), range).map(this::transform);
|
return object.hit(transform(ray), range, random).map(this::transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public final class HittableBinaryTree extends HittableCollection {
|
public final class HittableBinaryTree extends HittableCollection {
|
||||||
private final @Nullable Hittable left;
|
private final @Nullable Hittable left;
|
||||||
@ -46,17 +47,17 @@ public final class HittableBinaryTree extends HittableCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(@NotNull Ray ray, @NotNull State state) {
|
public void hit(@NotNull Ray ray, @NotNull State state, @NotNull RandomGenerator random) {
|
||||||
if (!bbox.hit(ray, state.getRange())) return;
|
if (!bbox.hit(ray, state.getRange())) return;
|
||||||
if (left instanceof HittableCollection coll) {
|
if (left instanceof HittableCollection coll) {
|
||||||
coll.hit(ray, state);
|
coll.hit(ray, state, random);
|
||||||
} else if (left != null) {
|
} else if (left != null) {
|
||||||
hit(state, ray, left);
|
hit(state, ray, left, random);
|
||||||
}
|
}
|
||||||
if (right instanceof HittableCollection coll) {
|
if (right instanceof HittableCollection coll) {
|
||||||
coll.hit(ray, state);
|
coll.hit(ray, state, random);
|
||||||
} else if (right != null) {
|
} else if (right != null) {
|
||||||
hit(state, ray, right);
|
hit(state, ray, right, random);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,20 +8,21 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public abstract class HittableCollection implements Hittable {
|
public abstract class HittableCollection implements Hittable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
public final @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range, @NotNull RandomGenerator random) {
|
||||||
var state = new State(range);
|
var state = new State(range);
|
||||||
hit(ray, state);
|
hit(ray, state, random);
|
||||||
return state.getResult();
|
return state.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void hit(@NotNull Ray ray, @NotNull State state);
|
public abstract void hit(@NotNull Ray ray, @NotNull State state, @NotNull RandomGenerator random);
|
||||||
|
|
||||||
protected static boolean hit(@NotNull State state, @NotNull Ray ray, @NotNull Hittable object) {
|
protected static boolean hit(@NotNull State state, @NotNull Ray ray, @NotNull Hittable object, @NotNull RandomGenerator random) {
|
||||||
var r = object.hit(ray, state.range);
|
var r = object.hit(ray, state.range, random);
|
||||||
if (r.isPresent()) {
|
if (r.isPresent()) {
|
||||||
if (state.range.surrounds(r.get().t())){
|
if (state.range.surrounds(r.get().t())){
|
||||||
state.result = r.get();
|
state.result = r.get();
|
||||||
|
@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public final class HittableList extends HittableCollection {
|
public final class HittableList extends HittableCollection {
|
||||||
private final @NotNull List<Hittable> objects;
|
private final @NotNull List<Hittable> objects;
|
||||||
@ -22,8 +23,8 @@ public final class HittableList extends HittableCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(@NotNull Ray ray, @NotNull State state) {
|
public void hit(@NotNull Ray ray, @NotNull State state, @NotNull RandomGenerator random) {
|
||||||
objects.forEach(object -> hit(state, ray, object));
|
objects.forEach(object -> hit(state, ray, object, random));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user