fixed refraction direction generation

This commit is contained in:
Sven Vogel 2023-03-04 15:58:56 +01:00
parent 4d3c45c111
commit 3d3bc7bd95
2 changed files with 26 additions and 8 deletions

View File

@ -100,14 +100,31 @@ public class Vector {
return this.sub(normal.scale(this.dot(normal) * 2.0)); return this.sub(normal.scale(this.dot(normal) * 2.0));
} }
// based on https://bheisler.github.io/post/writing-raytracer-in-rust-part-3/
public Vector refract(Vector normal, Vector incoming, double ior) { public Vector refract(Vector normal, Vector incoming, double ior) {
double len2 = normal.dot(incoming);
double k = 1.0 - ior * ior * (1.0 - len2 * len2);
if (k < 0) double iDotN = incoming.dot(normal);
double etaI = 1;
double etaT = ior;
Vector refraction_n = normal;
if (iDotN < 0) {
iDotN = -iDotN;
} else {
refraction_n = normal.negate();
etaT = 1.0;
etaI = ior;
}
double eta = etaI / etaT;
double k = 1.0 - (eta * eta) * (1.0 - iDotN * iDotN);
if (k < 0.0) {
return Vector.origin(); return Vector.origin();
} else {
return incoming.scale(ior).sub(normal.scale(ior * len2 + Math.sqrt(k))); return incoming.add(refraction_n.scale(iDotN)).scale(eta).sub(refraction_n).scale(Math.sqrt(k));
}
} }
public Vector lerp(Vector other, double k) { public Vector lerp(Vector other, double k) {

View File

@ -32,13 +32,14 @@ public class Scene {
public static Scene generateExampleScene() { public static Scene generateExampleScene() {
Scene scene = new Scene(new LinearList()); Scene scene = new Scene(new LinearList());
BasicMaterial mirror = new BasicMaterial(Color.BLACK, 1.0, Color.WHITE, true); BasicMaterial glass = new BasicMaterial(Color.BLACK, 1.0, Color.WHITE, true);
BasicMaterial mirror = new BasicMaterial(Color.BLACK, 1.0, Color.WHITE, false);
BasicMaterial white = new BasicMaterial(new Color(0.8, 0.8, 0.8), 0.1, new Color(0.8, 0.8, 0.8), false); BasicMaterial white = new BasicMaterial(new Color(0.8, 0.8, 0.8), 0.1, new Color(0.8, 0.8, 0.8), false);
BasicMaterial red = new BasicMaterial(new Color(0.8, 0.0, 0.0), 0.1, new Color(0.8, 0.8, 0.8), false); BasicMaterial red = new BasicMaterial(new Color(0.8, 0.0, 0.0), 0.1, new Color(0.8, 0.8, 0.8), false);
BasicMaterial green = new BasicMaterial(new Color(0.0, 0.8, 0.0), 0.1, new Color(0.8, 0.8, 0.8), false); BasicMaterial green = new BasicMaterial(new Color(0.0, 0.8, 0.0), 0.1, new Color(0.8, 0.8, 0.8), false);
BasicMaterial blue = new BasicMaterial(new Color(0.0, 0.0, 0.8), 0.1, new Color(0.8, 0.8, 0.8), false); BasicMaterial blue = new BasicMaterial(new Color(0.0, 0.0, 0.8), 0.1, new Color(0.8, 0.8, 0.8), false);
scene.addMesh(new BasicMesh(mirror, new Sphere(new Vector(0,1.5,0), 1.0))); scene.addMesh(new BasicMesh(glass, new Sphere(new Vector(0,0,0), 1.0)));
scene.addMesh(new BasicMesh(white, new Sphere(new Vector(3,2,0), 0.25))); scene.addMesh(new BasicMesh(white, new Sphere(new Vector(3,2,0), 0.25)));
scene.addMesh(new BasicMesh(red, new Sphere(new Vector(2.5,2,-3), 0.33))); scene.addMesh(new BasicMesh(red, new Sphere(new Vector(2.5,2,-3), 0.33)));
@ -49,7 +50,7 @@ public class Scene {
scene.addMesh(new BasicMesh(green, new Plane(new Vector(1, 0, 0), 4))); scene.addMesh(new BasicMesh(green, new Plane(new Vector(1, 0, 0), 4)));
scene.addMesh(new BasicMesh(blue, new Plane(new Vector(0, 0, 1), 5))); scene.addMesh(new BasicMesh(blue, new Plane(new Vector(0, 0, 1), 5)));
scene.addMesh(new BasicMesh(white, new Plane(new Vector(0, 0, 1), -4))); scene.addMesh(new BasicMesh(mirror, new Plane(new Vector(0, 0, 1), -4)));
scene.addLight(new Point(Color.WHITE.scale(0.5), new Vector(0, 4, 0))); scene.addLight(new Point(Color.WHITE.scale(0.5), new Vector(0, 4, 0)));
scene.addLight(new Point(Color.WHITE.scale(0.5), new Vector(1, 3, 1))); scene.addLight(new Point(Color.WHITE.scale(0.5), new Vector(1, 3, 1)));