add total internal reflection
This commit is contained in:
parent
088263b344
commit
82b38d4501
@ -17,7 +17,7 @@ public class Main {
|
||||
var scene = new Scene(
|
||||
new Sphere(0, -100.5, 1, 100, new LambertianMaterial(new Color(0.8, 0.8, 0.0))),
|
||||
new Sphere(0, 0, 1.2, 0.5, new LambertianMaterial(new Color(0.1, 0.2, 0.5))),
|
||||
new Sphere(-1, 0, 1, 0.5, new DielectricMaterial(1.5)),
|
||||
new Sphere(-1, 0, 1, 0.5, new DielectricMaterial(0.75)),
|
||||
new Sphere(1, 0, 1, 0.5, new MetallicMaterial(new Color(0.8, 0.6, 0.2), 1.0))
|
||||
);
|
||||
var camera = new Camera(512, 2, 16 / 9d);
|
||||
|
@ -12,7 +12,21 @@ public record DielectricMaterial(double refractionIndex) implements Material {
|
||||
@Override
|
||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit) {
|
||||
var ri = hit.frontFace() ? (1 / refractionIndex) : refractionIndex;
|
||||
var refracted = Vec3.refract(ray.direction(), hit.normal(), ri);
|
||||
return Optional.of(new ScatterResult(new Ray(hit.position(), refracted), Color.WHITE));
|
||||
|
||||
var cosTheta = Math.min(- ray.direction().unit().times(hit.normal()), 1.0);
|
||||
var reflectance = reflectance(cosTheta);
|
||||
var reflect = reflectance > Math.random();
|
||||
|
||||
var newDirection = (reflect ? Optional.<Vec3>empty() : Vec3.refract(ray.direction(), hit.normal(), ri))
|
||||
.orElseGet(() -> Vec3.reflect(ray.direction(), hit.normal()));
|
||||
|
||||
return Optional.of(new ScatterResult(new Ray(hit.position(), newDirection), Color.WHITE));
|
||||
}
|
||||
|
||||
private double reflectance(double cos) {
|
||||
// use schlick's approximation for reflectance
|
||||
var r0 = (1 - refractionIndex) / (1 + refractionIndex);
|
||||
r0 = r0 * r0;
|
||||
return r0 + (1 - r0) * (1 - cos) * (1 - cos) * (1 - cos) * (1 - cos) * (1 - cos);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package eu.jonahbauer.raytracing.math;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public record Vec3(double x, double y, double z) {
|
||||
public static final Vec3 ZERO = new Vec3(0, 0, 0);
|
||||
public static final Vec3 UNIT_X = new Vec3(1, 0, 0);
|
||||
@ -31,12 +33,15 @@ public record Vec3(double x, double y, double z) {
|
||||
return vec.minus(normal.times(2 * normal.times(vec)));
|
||||
}
|
||||
|
||||
public static @NotNull Vec3 refract(@NotNull Vec3 vec, @NotNull Vec3 normal, double index) {
|
||||
public static @NotNull Optional<Vec3> refract(@NotNull Vec3 vec, @NotNull Vec3 normal, double ri) {
|
||||
vec = vec.unit();
|
||||
var cosTheta = Math.min(- vec.times(normal), 1.0);
|
||||
var rOutPerp = vec.plus(normal.times(cosTheta)).times(index);
|
||||
var sinTheta = Math.sqrt(1 - cosTheta * cosTheta);
|
||||
if (ri * sinTheta > 1) return Optional.empty();
|
||||
|
||||
var rOutPerp = vec.plus(normal.times(cosTheta)).times(ri);
|
||||
var rOutParallel = normal.times(- Math.sqrt(Math.abs(1 - rOutPerp.squared())));
|
||||
return rOutPerp.plus(rOutParallel);
|
||||
return Optional.of(rOutPerp.plus(rOutParallel));
|
||||
}
|
||||
|
||||
public @NotNull Vec3 plus(@NotNull Vec3 b) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user