From e2c9609e0ecd1527eb630c9818327691113cec4a Mon Sep 17 00:00:00 2001 From: jbb01 <32650546+jbb01@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:10:38 +0200 Subject: [PATCH] add Vec3#fma to improve performance --- .../eu/jonahbauer/raytracing/math/Ray.java | 6 +---- .../eu/jonahbauer/raytracing/math/Vec3.java | 22 ++++++++++++++----- .../render/camera/SimpleCamera.java | 2 +- .../render/material/MetallicMaterial.java | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/main/java/eu/jonahbauer/raytracing/math/Ray.java b/src/main/java/eu/jonahbauer/raytracing/math/Ray.java index ca3d79c..c622be1 100644 --- a/src/main/java/eu/jonahbauer/raytracing/math/Ray.java +++ b/src/main/java/eu/jonahbauer/raytracing/math/Ray.java @@ -11,11 +11,7 @@ public record Ray(@NotNull Vec3 origin, @NotNull Vec3 direction) { } public @NotNull Vec3 at(double t) { - return new Vec3( - Math.fma(t, direction.x(), origin.x()), - Math.fma(t, direction.y(), origin.y()), - Math.fma(t, direction.z(), origin.z()) - ); + return Vec3.fma(t, direction, origin); } public int vmask() { diff --git a/src/main/java/eu/jonahbauer/raytracing/math/Vec3.java b/src/main/java/eu/jonahbauer/raytracing/math/Vec3.java index 6398560..3bdb046 100644 --- a/src/main/java/eu/jonahbauer/raytracing/math/Vec3.java +++ b/src/main/java/eu/jonahbauer/raytracing/math/Vec3.java @@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull; import java.util.Optional; import java.util.random.RandomGenerator; +import static eu.jonahbauer.raytracing.Main.DEBUG; + public record Vec3(double x, double y, double z) { public static final Vec3 ZERO = new Vec3(0, 0, 0); public static final Vec3 MAX = new Vec3(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); @@ -14,7 +16,11 @@ public record Vec3(double x, double y, double z) { public static final Vec3 UNIT_Z = new Vec3(0, 0, 1); public Vec3 { - assert Double.isFinite(x) && Double.isFinite(y) && Double.isFinite(z) : "x, y and z must be finite"; + if (DEBUG) { + if (!Double.isFinite(x) || !Double.isFinite(y) || !Double.isFinite(z)) { + throw new IllegalArgumentException("x, y and z must be finite"); + } + } } /** @@ -48,11 +54,7 @@ public record Vec3(double x, double y, double z) { public static @NotNull Vec3 reflect(@NotNull Vec3 vec, @NotNull Vec3 normal) { var factor = - 2 * normal.times(vec); - return new Vec3( - Math.fma(factor, normal.x(), vec.x()), - Math.fma(factor, normal.y(), vec.y()), - Math.fma(factor, normal.z(), vec.z()) - ); + return Vec3.fma(factor, normal, vec); } public static @NotNull Optional refract(@NotNull Vec3 vec, @NotNull Vec3 normal, double ri) { @@ -101,6 +103,14 @@ public record Vec3(double x, double y, double z) { ); } + public static @NotNull Vec3 fma(double a, @NotNull Vec3 b, @NotNull Vec3 c) { + return new Vec3( + Math.fma(a, b.x(), c.x()), + Math.fma(a, b.y(), c.y()), + Math.fma(a, b.z(), c.z()) + ); + } + public @NotNull Vec3 plus(double x, double y, double z) { return new Vec3(this.x + x, this.y + y, this.z + z); } diff --git a/src/main/java/eu/jonahbauer/raytracing/render/camera/SimpleCamera.java b/src/main/java/eu/jonahbauer/raytracing/render/camera/SimpleCamera.java index a26686e..84f40cd 100644 --- a/src/main/java/eu/jonahbauer/raytracing/render/camera/SimpleCamera.java +++ b/src/main/java/eu/jonahbauer/raytracing/render/camera/SimpleCamera.java @@ -60,7 +60,7 @@ public final class SimpleCamera implements Camera { this.pixel00 = origin.plus(direction.times(builder.focusDistance)) .minus(u.times(0.5 * viewportWidth)).minus(v.times(0.5 * viewportHeight)) - .plus(pixelU.div(2)).plus(pixelV.div(2)); + .plus(pixelU.times(.5)).plus(pixelV.times(.5)); } /** diff --git a/src/main/java/eu/jonahbauer/raytracing/render/material/MetallicMaterial.java b/src/main/java/eu/jonahbauer/raytracing/render/material/MetallicMaterial.java index c1a66f4..cdffa63 100644 --- a/src/main/java/eu/jonahbauer/raytracing/render/material/MetallicMaterial.java +++ b/src/main/java/eu/jonahbauer/raytracing/render/material/MetallicMaterial.java @@ -25,7 +25,7 @@ public record MetallicMaterial(@NotNull Texture texture, double fuzz) implements public @NotNull Optional scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) { var newDirection = Vec3.reflect(ray.direction(), hit.normal()); if (fuzz > 0) { - newDirection = newDirection.unit().plus(Vec3.random(random).times(fuzz)); + newDirection = Vec3.fma(fuzz, Vec3.random(random), newDirection.unit()); } var attenuation = texture.get(hit); return Optional.of(new SpecularScatterResult(attenuation, new Ray(hit.position(), newDirection)));