fixed refraction direction generation
This commit is contained in:
parent
4d3c45c111
commit
3d3bc7bd95
|
@ -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);
|
||||||
return Vector.origin();
|
double etaI = 1;
|
||||||
|
double etaT = ior;
|
||||||
|
|
||||||
return incoming.scale(ior).sub(normal.scale(ior * len2 + Math.sqrt(k)));
|
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();
|
||||||
|
} else {
|
||||||
|
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) {
|
||||||
|
|
|
@ -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)));
|
||||||
|
|
Reference in New Issue