add texture support
This commit is contained in:
parent
2c28b10a6e
commit
7c0bc68ab2
@ -1,7 +1,8 @@
|
|||||||
package eu.jonahbauer.raytracing;
|
package eu.jonahbauer.raytracing;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Vec3;
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.CheckerTexture;
|
||||||
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import eu.jonahbauer.raytracing.render.camera.SimpleCamera;
|
import eu.jonahbauer.raytracing.render.camera.SimpleCamera;
|
||||||
import eu.jonahbauer.raytracing.render.material.*;
|
import eu.jonahbauer.raytracing.render.material.*;
|
||||||
import eu.jonahbauer.raytracing.scene.Hittable;
|
import eu.jonahbauer.raytracing.scene.Hittable;
|
||||||
@ -61,7 +62,10 @@ public class Examples {
|
|||||||
|
|
||||||
var rng = new Random(1);
|
var rng = new Random(1);
|
||||||
var objects = new ArrayList<Hittable>();
|
var objects = new ArrayList<Hittable>();
|
||||||
objects.add(new Sphere(new Vec3(0, -1000, 0), 1000, new LambertianMaterial(new Color(0.5, 0.5, 0.5))));
|
objects.add(new Sphere(
|
||||||
|
new Vec3(0, -1000, 0), 1000,
|
||||||
|
new LambertianMaterial(new CheckerTexture(0.32, new Color(.2, .3, .1), new Color(.9, .9, .9)))
|
||||||
|
));
|
||||||
|
|
||||||
for (int a = -11; a < 11; a++) {
|
for (int a = -11; a < 11; a++) {
|
||||||
for (int b = -11; b < 11; b++) {
|
for (int b = -11; b < 11; b++) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.jonahbauer.raytracing.render.canvas;
|
package eu.jonahbauer.raytracing.render.canvas;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.jonahbauer.raytracing.render.canvas;
|
package eu.jonahbauer.raytracing.render.canvas;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.jonahbauer.raytracing.render.canvas;
|
package eu.jonahbauer.raytracing.render.canvas;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -2,7 +2,8 @@ package eu.jonahbauer.raytracing.render.material;
|
|||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.math.Vec3;
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
|
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -10,13 +11,13 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.random.RandomGenerator;
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public record DielectricMaterial(double refractionIndex, @NotNull Color albedo) implements Material {
|
public record DielectricMaterial(double refractionIndex, @NotNull Texture texture) implements Material {
|
||||||
public DielectricMaterial(double refractionIndex) {
|
public DielectricMaterial(double refractionIndex) {
|
||||||
this(refractionIndex, Color.WHITE);
|
this(refractionIndex, Color.WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DielectricMaterial {
|
public DielectricMaterial {
|
||||||
Objects.requireNonNull(albedo, "albedo");
|
Objects.requireNonNull(texture, "texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -30,7 +31,8 @@ public record DielectricMaterial(double refractionIndex, @NotNull Color albedo)
|
|||||||
var newDirection = (reflect ? Optional.<Vec3>empty() : Vec3.refract(ray.direction(), hit.normal(), ri))
|
var newDirection = (reflect ? Optional.<Vec3>empty() : Vec3.refract(ray.direction(), hit.normal(), ri))
|
||||||
.orElseGet(() -> Vec3.reflect(ray.direction(), hit.normal()));
|
.orElseGet(() -> Vec3.reflect(ray.direction(), hit.normal()));
|
||||||
|
|
||||||
return Optional.of(new ScatterResult(new Ray(hit.position(), newDirection), albedo));
|
var attenuation = texture.get(hit);
|
||||||
|
return Optional.of(new ScatterResult(new Ray(hit.position(), newDirection), attenuation));
|
||||||
}
|
}
|
||||||
|
|
||||||
private double reflectance(double cos) {
|
private double reflectance(double cos) {
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package eu.jonahbauer.raytracing.render.material;
|
package eu.jonahbauer.raytracing.render.material;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
|
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.random.RandomGenerator;
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public record DiffuseLight(@NotNull Color emit) implements Material {
|
public record DiffuseLight(@NotNull Texture texture) implements Material {
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
@ -16,6 +17,6 @@ public record DiffuseLight(@NotNull Color emit) implements Material {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Color emitted(@NotNull HitResult hit) {
|
public @NotNull Color emitted(@NotNull HitResult hit) {
|
||||||
return emit;
|
return texture.get(hit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ package eu.jonahbauer.raytracing.render.material;
|
|||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.math.Vec3;
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.random.RandomGenerator;
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public record IsotropicMaterial(@NotNull Color albedo) implements Material{
|
public record IsotropicMaterial(@NotNull Color albedo) implements Material {
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||||
return Optional.of(new ScatterResult(new Ray(hit.position(), Vec3.random(random, true)), albedo()));
|
return Optional.of(new ScatterResult(new Ray(hit.position(), Vec3.random(random, true)), albedo()));
|
||||||
|
@ -2,7 +2,7 @@ package eu.jonahbauer.raytracing.render.material;
|
|||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.math.Vec3;
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -10,9 +10,9 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.random.RandomGenerator;
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public record LambertianMaterial(@NotNull Color albedo) implements Material {
|
public record LambertianMaterial(@NotNull Texture texture) implements Material {
|
||||||
public LambertianMaterial {
|
public LambertianMaterial {
|
||||||
Objects.requireNonNull(albedo, "albedo");
|
Objects.requireNonNull(texture, "texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -20,7 +20,8 @@ public record LambertianMaterial(@NotNull Color albedo) implements Material {
|
|||||||
var newDirection = hit.normal().plus(Vec3.random(random, true));
|
var newDirection = hit.normal().plus(Vec3.random(random, true));
|
||||||
if (newDirection.isNearZero()) newDirection = hit.normal();
|
if (newDirection.isNearZero()) newDirection = hit.normal();
|
||||||
|
|
||||||
|
var attenuation = texture.get(hit);
|
||||||
var scattered = new Ray(hit.position(), newDirection);
|
var scattered = new Ray(hit.position(), newDirection);
|
||||||
return Optional.of(new ScatterResult(scattered, albedo));
|
return Optional.of(new ScatterResult(scattered, attenuation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package eu.jonahbauer.raytracing.render.material;
|
package eu.jonahbauer.raytracing.render.material;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package eu.jonahbauer.raytracing.render.material;
|
|||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.math.Vec3;
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -10,14 +10,14 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.random.RandomGenerator;
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
public record MetallicMaterial(@NotNull Color albedo, double fuzz) implements Material {
|
public record MetallicMaterial(@NotNull Texture texture, double fuzz) implements Material {
|
||||||
|
|
||||||
public MetallicMaterial(@NotNull Color albedo) {
|
public MetallicMaterial(@NotNull Texture texture) {
|
||||||
this(albedo, 0);
|
this(texture, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetallicMaterial {
|
public MetallicMaterial {
|
||||||
Objects.requireNonNull(albedo, "albedo");
|
Objects.requireNonNull(texture, "texture");
|
||||||
if (fuzz < 0 || !Double.isFinite(fuzz)) throw new IllegalArgumentException("fuzz must be non-negative");
|
if (fuzz < 0 || !Double.isFinite(fuzz)) throw new IllegalArgumentException("fuzz must be non-negative");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +27,7 @@ public record MetallicMaterial(@NotNull Color albedo, double fuzz) implements Ma
|
|||||||
if (fuzz > 0) {
|
if (fuzz > 0) {
|
||||||
newDirection = newDirection.unit().plus(Vec3.random(random, true).times(fuzz));
|
newDirection = newDirection.unit().plus(Vec3.random(random, true).times(fuzz));
|
||||||
}
|
}
|
||||||
return Optional.of(new ScatterResult(new Ray(hit.position(), newDirection), albedo));
|
var attenuation = texture.get(hit);
|
||||||
|
return Optional.of(new ScatterResult(new Ray(hit.position(), newDirection), attenuation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package eu.jonahbauer.raytracing.render.renderer;
|
|||||||
|
|
||||||
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.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
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.scene.Scene;
|
import eu.jonahbauer.raytracing.scene.Scene;
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package eu.jonahbauer.raytracing.render.texture;
|
||||||
|
|
||||||
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public record CheckerTexture(double scale, @NotNull Texture even, @NotNull Texture odd) implements Texture {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Color get(double u, double v, @NotNull Vec3 p) {
|
||||||
|
var x = (int) Math.floor(p.x() / scale);
|
||||||
|
var y = (int) Math.floor(p.y() / scale);
|
||||||
|
var z = (int) Math.floor(p.z() / scale);
|
||||||
|
var even = (x + y + z) % 2 == 0;
|
||||||
|
return even ? even().get(u, v, p) : odd().get(u, v, p);
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
package eu.jonahbauer.raytracing.render;
|
package eu.jonahbauer.raytracing.render.texture;
|
||||||
|
|
||||||
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public record Color(double r, double g, double b) {
|
public record Color(double r, double g, double b) implements Texture {
|
||||||
public static final @NotNull Color BLACK = new Color(0.0, 0.0, 0.0);
|
public static final @NotNull Color BLACK = new Color(0.0, 0.0, 0.0);
|
||||||
public static final @NotNull Color WHITE = new Color(1.0, 1.0, 1.0);
|
public static final @NotNull Color WHITE = new Color(1.0, 1.0, 1.0);
|
||||||
public static final @NotNull Color RED = new Color(1.0, 0.0, 0.0);
|
public static final @NotNull Color RED = new Color(1.0, 0.0, 0.0);
|
||||||
@ -68,7 +69,9 @@ public record Color(double r, double g, double b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color {}
|
public Color(int rgb) {
|
||||||
|
this((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
public Color(int red, int green, int blue) {
|
public Color(int red, int green, int blue) {
|
||||||
this(red / 255f, green / 255f, blue / 255f);
|
this(red / 255f, green / 255f, blue / 255f);
|
||||||
@ -86,7 +89,12 @@ public record Color(double r, double g, double b) {
|
|||||||
return toInt(b);
|
return toInt(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Color get(double u, double v, @NotNull Vec3 p) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private static int toInt(double value) {
|
private static int toInt(double value) {
|
||||||
return Math.max(0, Math.min(255, (int) (255.99 * value)));
|
return Math.clamp((int) (255.99 * value), 0, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.jonahbauer.raytracing.render.texture;
|
||||||
|
|
||||||
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface Texture {
|
||||||
|
default @NotNull Color get(@NotNull HitResult hit) {
|
||||||
|
return get(hit.u(), hit.v(), hit.position());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull Color get(double u, double v, @NotNull Vec3 p);
|
||||||
|
}
|
@ -7,17 +7,18 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public record HitResult(
|
public record HitResult(
|
||||||
double t,
|
double t, @NotNull Vec3 position, @NotNull Vec3 normal,
|
||||||
@NotNull Vec3 position,
|
@NotNull Material material, double u, double v, boolean frontFace
|
||||||
@NotNull Vec3 normal,
|
|
||||||
@NotNull Material material,
|
|
||||||
boolean frontFace
|
|
||||||
) implements Comparable<HitResult> {
|
) implements Comparable<HitResult> {
|
||||||
public HitResult {
|
public HitResult {
|
||||||
Objects.requireNonNull(position, "position");
|
Objects.requireNonNull(position, "position");
|
||||||
normal = normal.unit();
|
normal = normal.unit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NotNull HitResult withPositionAndNormal(@NotNull Vec3 position, @NotNull Vec3 normal) {
|
||||||
|
return new HitResult(t, position, normal, material, u, v, frontFace);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NotNull HitResult o) {
|
public int compareTo(@NotNull HitResult o) {
|
||||||
return Double.compare(t, o.t);
|
return Double.compare(t, o.t);
|
||||||
|
@ -2,7 +2,7 @@ package eu.jonahbauer.raytracing.scene;
|
|||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.AABB;
|
import eu.jonahbauer.raytracing.math.AABB;
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import eu.jonahbauer.raytracing.scene.util.HittableBinaryTree;
|
import eu.jonahbauer.raytracing.scene.util.HittableBinaryTree;
|
||||||
import eu.jonahbauer.raytracing.scene.util.HittableCollection;
|
import eu.jonahbauer.raytracing.scene.util.HittableCollection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package eu.jonahbauer.raytracing.scene;
|
package eu.jonahbauer.raytracing.scene;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.math.Ray;
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
@ -51,7 +51,10 @@ public abstract class Hittable2D implements Hittable {
|
|||||||
if (!isInterior(alpha, beta)) return Optional.empty();
|
if (!isInterior(alpha, beta)) return Optional.empty();
|
||||||
|
|
||||||
var frontFace = denominator < 0;
|
var frontFace = denominator < 0;
|
||||||
return Optional.of(new HitResult(t, position, frontFace ? normal : normal.neg(), material, frontFace));
|
return Optional.of(new HitResult(
|
||||||
|
t, position, frontFace ? normal : normal.neg(),
|
||||||
|
material, alpha, beta, frontFace
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract boolean isInterior(double alpha, double beta);
|
protected abstract boolean isInterior(double alpha, double beta);
|
||||||
|
@ -32,7 +32,7 @@ public record ConstantMedium(@NotNull Hittable boundary, double density, @NotNul
|
|||||||
if (hitDistance > distance) return Optional.empty();
|
if (hitDistance > distance) return Optional.empty();
|
||||||
|
|
||||||
var t = tmin + hitDistance / length;
|
var t = tmin + hitDistance / length;
|
||||||
return Optional.of(new HitResult(t, ray.at(t), Vec3.UNIT_X, material, true)); // arbitrary normal and frontFace
|
return Optional.of(new HitResult(t, ray.at(t), Vec3.UNIT_X, material, 0, 0, true)); // arbitrary normal and frontFace
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,9 +49,19 @@ public final class Sphere implements Hittable {
|
|||||||
if (!range.surrounds(t)) return Optional.empty();
|
if (!range.surrounds(t)) return Optional.empty();
|
||||||
|
|
||||||
var position = ray.at(t);
|
var position = ray.at(t);
|
||||||
var normal = position.minus(center);
|
var normal = position.minus(center).div(radius);
|
||||||
var frontFace = normal.times(ray.direction()) < 0;
|
var frontFace = normal.times(ray.direction()) < 0;
|
||||||
return Optional.of(new HitResult(t, position, frontFace ? normal : normal.times(-1), material, frontFace));
|
|
||||||
|
var theta = Math.acos(- normal.y());
|
||||||
|
var phi = Math.atan2(- normal.z(), normal.x()) + Math.PI;
|
||||||
|
|
||||||
|
var u = phi / (2 * Math.PI);
|
||||||
|
var v = theta / Math.PI;
|
||||||
|
|
||||||
|
return Optional.of(new HitResult(
|
||||||
|
t, position, frontFace ? normal : normal.neg(),
|
||||||
|
material, u, v, frontFace
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,7 +79,7 @@ public final class RotateY extends Transform {
|
|||||||
-sin * normal.x() + cos * normal.z()
|
-sin * normal.x() + cos * normal.z()
|
||||||
);
|
);
|
||||||
|
|
||||||
return new HitResult(result.t(), newPosition, newNormal, result.material(), result.frontFace());
|
return result.withPositionAndNormal(newPosition, newNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,13 +29,7 @@ public final class Translate extends Transform {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull HitResult transform(@NotNull HitResult result) {
|
protected @NotNull HitResult transform(@NotNull HitResult result) {
|
||||||
return new HitResult(
|
return result.withPositionAndNormal(result.position().plus(offset), result.normal());
|
||||||
result.t(),
|
|
||||||
result.position().plus(offset),
|
|
||||||
result.normal(),
|
|
||||||
result.material(),
|
|
||||||
result.frontFace()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.jonahbauer.raytracing.render.canvas;
|
package eu.jonahbauer.raytracing.render.canvas;
|
||||||
|
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import eu.jonahbauer.raytracing.render.ImageFormat;
|
import eu.jonahbauer.raytracing.render.ImageFormat;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
@ -3,7 +3,7 @@ package eu.jonahbauer.raytracing.scene.hittable3d;
|
|||||||
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.math.Vec3;
|
||||||
import eu.jonahbauer.raytracing.render.Color;
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
import eu.jonahbauer.raytracing.render.material.LambertianMaterial;
|
import eu.jonahbauer.raytracing.render.material.LambertianMaterial;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user