add Vec3#fma to improve performance

main
jbb01 6 months ago
parent 89c4340821
commit e2c9609e0e

@ -11,11 +11,7 @@ public record Ray(@NotNull Vec3 origin, @NotNull Vec3 direction) {
} }
public @NotNull Vec3 at(double t) { public @NotNull Vec3 at(double t) {
return new Vec3( return Vec3.fma(t, direction, origin);
Math.fma(t, direction.x(), origin.x()),
Math.fma(t, direction.y(), origin.y()),
Math.fma(t, direction.z(), origin.z())
);
} }
public int vmask() { public int vmask() {

@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull;
import java.util.Optional; import java.util.Optional;
import java.util.random.RandomGenerator; import java.util.random.RandomGenerator;
import static eu.jonahbauer.raytracing.Main.DEBUG;
public record Vec3(double x, double y, double z) { public record Vec3(double x, double y, double z) {
public static final Vec3 ZERO = new Vec3(0, 0, 0); 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); 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 static final Vec3 UNIT_Z = new Vec3(0, 0, 1);
public Vec3 { 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) { public static @NotNull Vec3 reflect(@NotNull Vec3 vec, @NotNull Vec3 normal) {
var factor = - 2 * normal.times(vec); var factor = - 2 * normal.times(vec);
return new Vec3( return Vec3.fma(factor, normal, vec);
Math.fma(factor, normal.x(), vec.x()),
Math.fma(factor, normal.y(), vec.y()),
Math.fma(factor, normal.z(), vec.z())
);
} }
public static @NotNull Optional<Vec3> refract(@NotNull Vec3 vec, @NotNull Vec3 normal, double ri) { public static @NotNull Optional<Vec3> 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) { public @NotNull Vec3 plus(double x, double y, double z) {
return new Vec3(this.x + x, this.y + y, this.z + z); return new Vec3(this.x + x, this.y + y, this.z + z);
} }

@ -60,7 +60,7 @@ public final class SimpleCamera implements Camera {
this.pixel00 = origin.plus(direction.times(builder.focusDistance)) this.pixel00 = origin.plus(direction.times(builder.focusDistance))
.minus(u.times(0.5 * viewportWidth)).minus(v.times(0.5 * viewportHeight)) .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));
} }
/** /**

@ -25,7 +25,7 @@ public record MetallicMaterial(@NotNull Texture texture, double fuzz) implements
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) {
var newDirection = Vec3.reflect(ray.direction(), hit.normal()); var newDirection = Vec3.reflect(ray.direction(), hit.normal());
if (fuzz > 0) { 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); var attenuation = texture.get(hit);
return Optional.of(new SpecularScatterResult(attenuation, new Ray(hit.position(), newDirection))); return Optional.of(new SpecularScatterResult(attenuation, new Ray(hit.position(), newDirection)));

Loading…
Cancel
Save