fixed point light

This commit is contained in:
Sven Vogel 2023-02-22 13:19:13 +01:00
parent a3db520517
commit 9d745a4fd6
8 changed files with 41 additions and 11 deletions

View File

@ -104,6 +104,10 @@ public class Vector {
return this.scale(k).add(other.scale(1.0 - k)); return this.scale(k).add(other.scale(1.0 - k));
} }
public double distance(Vector vector) {
return this.sub(vector).length();
}
public enum SwizzleMask { public enum SwizzleMask {
XYZ, XYZ,
YXZ, YXZ,

View File

@ -35,7 +35,7 @@ public class Scene {
scene.addMesh(new BasicMesh(new BasicMaterial(new Color(1, 1, 1), 0.2, new Color(1.0)), new Plane(new Vector(1, 0, 0), 1.0))); scene.addMesh(new BasicMesh(new BasicMaterial(new Color(1, 1, 1), 0.2, new Color(1.0)), new Plane(new Vector(1, 0, 0), 1.0)));
scene.addMesh(new BasicMesh(new BasicMaterial(new Color(1, 1, 1), 0.0, new Color(1.0)), new Plane(new Vector(0, 1, 0), 1.0))); scene.addMesh(new BasicMesh(new BasicMaterial(new Color(1, 1, 1), 0.0, new Color(1.0)), new Plane(new Vector(0, 1, 0), 1.0)));
//scene.addLight(new Point(new Color(0.9, 0, 0), new Vector(8,3,-2))); scene.addLight(new Point(new Color(0.9, 0, 0), new Vector(8,3,-2)));
scene.addLight(new Point(new Color(0,0.8,0), new Vector(4,3,2))); scene.addLight(new Point(new Color(0,0.8,0), new Vector(4,3,2)));
//scene.addLight(new Directional(new Color(1), new Vector(1, 1, 0).normalize())); //scene.addLight(new Directional(new Color(1), new Vector(1, 1, 0).normalize()));

View File

@ -1,5 +1,7 @@
package optics.light; package optics.light;
import basics.math.algebra.Vector;
public class Color { public class Color {
public static final Color BLACK = new Color(0,0,0); public static final Color BLACK = new Color(0,0,0);
@ -24,6 +26,10 @@ public class Color {
return new Color(k, k, k); return new Color(k, k, k);
} }
public static Color fromVector(Vector vector) {
return new Color(vector.x, vector.y, vector.z);
}
public Color add(Color other) { public Color add(Color other) {
return new Color(this.r + other.r, this.g + other.g, this.b + other.b); return new Color(this.r + other.r, this.g + other.g, this.b + other.b);
} }

View File

@ -19,4 +19,9 @@ public class Directional extends LightSource {
public Vector getDirection(Vector point) { public Vector getDirection(Vector point) {
return orientation; return orientation;
} }
@Override
public double getDistance(Vector point) {
return Double.POSITIVE_INFINITY;
}
} }

View File

@ -19,4 +19,6 @@ public abstract class LightSource {
} }
public abstract Vector getDirection(Vector point); public abstract Vector getDirection(Vector point);
public abstract double getDistance(Vector point);
} }

View File

@ -14,4 +14,9 @@ public class Point extends LightSource {
public Vector getDirection(Vector point) { public Vector getDirection(Vector point) {
return position.sub(point).normalize(); return position.sub(point).normalize();
} }
@Override
public double getDistance(Vector point) {
return this.position.distance(point);
}
} }

View File

@ -17,8 +17,8 @@ public class Raytracer implements Renderer {
private Camera camera = new PinholeCamera(new Vector(0,0,-4), Vector.origin(), 90, 1e-3, 1e3); private Camera camera = new PinholeCamera(new Vector(0,0,-4), Vector.origin(), 90, 1e-3, 1e3);
private Scene scene = Scene.generateExampleScene(); private Scene scene = Scene.generateExampleScene();
private double traceShadow(Vector point, Vector sun) { private double traceShadow(Vector point, Vector direction, double distance) {
Ray shadowRay = new Ray(point, sun, 1e-3, 1e3); Ray shadowRay = new Ray(point, direction, 1e-3, distance);
Optional<Hit> result = scene.intersect(shadowRay); Optional<Hit> result = scene.intersect(shadowRay);
@ -49,17 +49,17 @@ public class Raytracer implements Renderer {
// indirect light sum // indirect light sum
Color incoming = new Color(0,0,0); Color incoming = new Color(0,0,0);
Color reflectedLight = reflectedLight(directRay, material, normal, intersection, depth);
for (LightSource light : scene.getLights()) { for (LightSource light : scene.getLights()) {
double directInfluence = castShadow(light, intersection, normal); double directInfluence = castShadow(light, intersection, normal);
Color directLight = material.getDiffuse().scale(directInfluence).mul(light.getColor()); Color directLight = material.getDiffuse().scale(directInfluence).mul(light.getColor());
Color reflectedLight = reflectedLight(directRay, material, normal, intersection, depth); incoming = incoming.add(directLight).add(reflectedLight);
incoming = incoming.add(directLight);
} }
return incoming; return incoming.add(reflectedLight);
} }
private Color reflectedLight(Ray incomingRay, BasicMaterial material, Vector normal, Vector point, int depth) { private Color reflectedLight(Ray incomingRay, BasicMaterial material, Vector normal, Vector point, int depth) {
@ -74,7 +74,8 @@ public class Raytracer implements Renderer {
private double castShadow(LightSource target, Vector point, Vector surfaceNormal) { private double castShadow(LightSource target, Vector point, Vector surfaceNormal) {
Vector lightDirection = target.getDirection(point); Vector lightDirection = target.getDirection(point);
double shadow = traceShadow(point, lightDirection); double distance = target.getDistance(point);
double shadow = traceShadow(point.add(surfaceNormal.scale(1e-3)), lightDirection, distance);
return Math.max(surfaceNormal.dot(lightDirection), 0.0) * shadow; return Math.max(surfaceNormal.dot(lightDirection), 0.0) * shadow;
} }

View File

@ -48,12 +48,19 @@ public class ContributionBuffer {
} }
} }
private double tonemap(double x) {
final double g = 5;
final double k = 4;
return x < g ? 1 - 1 / Math.pow(g, k) * Math.pow(x - g, k) : 1.0;
}
private int getRGB(int x, int y) { private int getRGB(int x, int y) {
Color linearRGB = buffer[x][y].scale(1.0 / samples[x][y]); Color linearRGB = buffer[x][y].scale(1.0 / samples[x][y]);
int red = (int) (linearRGB.r * 255.0); int red = (int) (tonemap(linearRGB.r) * 255.0);
int green = (int) (linearRGB.g * 255.0); int green = (int) (tonemap(linearRGB.g) * 255.0);
int blue = (int) (linearRGB.b * 255.0); int blue = (int) (tonemap(linearRGB.b) * 255.0);
red = Math.max(Math.min(red, 255), 0); red = Math.max(Math.min(red, 255), 0);
green = Math.max(Math.min(green, 255), 0); green = Math.max(Math.min(green, 255), 0);