rework interface between materials and rgb colors
This commit is contained in:
parent
9eb8afcb59
commit
b8aae8c2e5
@ -55,11 +55,11 @@ public class Examples {
|
||||
var cs = ColorSpaces.sRGB;
|
||||
return new Example(
|
||||
new Scene(getSkyBox(), List.of(
|
||||
new Sphere(new Vec3(0, -100.5, -1.0), 100.0, new LambertianMaterial(new ColorRGB(0.8, 0.8, 0.0), cs)),
|
||||
new Sphere(new Vec3(0, 0, -1.2), 0.5, new LambertianMaterial(new ColorRGB(0.1, 0.2, 0.5), cs)),
|
||||
new Sphere(new Vec3(0, -100.5, -1.0), 100.0, new LambertianMaterial(cs.albedo(0.8, 0.8, 0.0))),
|
||||
new Sphere(new Vec3(0, 0, -1.2), 0.5, new LambertianMaterial(cs.albedo(0.1, 0.2, 0.5))),
|
||||
new Sphere(new Vec3(-1.0, 0, -1.2), 0.5, new DielectricMaterial(1.5)),
|
||||
new Sphere(new Vec3(-1.0, 0, -1.2), 0.4, new DielectricMaterial(1 / 1.5)),
|
||||
new Sphere(new Vec3(1.0, 0, -1.2), 0.5, new MetallicMaterial(new ColorRGB(0.8, 0.6, 0.2), cs, 0.0))
|
||||
new Sphere(new Vec3(1.0, 0, -1.2), 0.5, new MetallicMaterial(cs.albedo(0.8, 0.6, 0.2)))
|
||||
)),
|
||||
SimpleCamera.builder()
|
||||
.withImage(height * 16 / 9, height)
|
||||
@ -92,12 +92,12 @@ public class Examples {
|
||||
if (rnd < 0.8) {
|
||||
// diffuse
|
||||
var albedo = ColorRGB.random(rng).times(ColorRGB.random(rng));
|
||||
material = new LambertianMaterial(albedo, cs);
|
||||
material = new LambertianMaterial(cs.albedo(albedo));
|
||||
} else if (rnd < 0.95) {
|
||||
// metal
|
||||
var albedo = ColorRGB.random(rng, 0.5, 1.0);
|
||||
var fuzz = rng.nextDouble() * 0.5;
|
||||
material = new MetallicMaterial(albedo, cs, fuzz);
|
||||
material = new MetallicMaterial(cs.albedo(albedo), fuzz);
|
||||
} else {
|
||||
// glass
|
||||
material = new DielectricMaterial(1.5);
|
||||
@ -108,8 +108,8 @@ public class Examples {
|
||||
}
|
||||
|
||||
objects.add(new Sphere(new Vec3(0, 1, 0), 1.0, new DielectricMaterial(1.5)));
|
||||
objects.add(new Sphere(new Vec3(-4, 1, 0), 1.0, new LambertianMaterial(new ColorRGB(0.4, 0.2, 0.1), cs)));
|
||||
objects.add(new Sphere(new Vec3(4, 1, 0), 1.0, new MetallicMaterial(new ColorRGB(0.7, 0.6, 0.5), cs)));
|
||||
objects.add(new Sphere(new Vec3(-4, 1, 0), 1.0, new LambertianMaterial(cs.albedo(0.4, 0.2, 0.1))));
|
||||
objects.add(new Sphere(new Vec3(4, 1, 0), 1.0, new MetallicMaterial(cs.albedo(0.7, 0.6, 0.5))));
|
||||
|
||||
var camera = SimpleCamera.builder()
|
||||
.withImage(height * 16 / 9, height)
|
||||
@ -128,11 +128,11 @@ public class Examples {
|
||||
var cs = ColorSpaces.sRGB;
|
||||
return new Example(
|
||||
new Scene(getSkyBox(), List.of(
|
||||
new Parallelogram(new Vec3(-3, -2, 5), new Vec3(0, 0, -4), new Vec3(0, 4, 0), new LambertianMaterial(new ColorRGB(1.0, 0.2, 0.2), cs)),
|
||||
new Parallelogram(new Vec3(-2, -2, 0), new Vec3(4, 0, 0), new Vec3(0, 4, 0), new LambertianMaterial(new ColorRGB(0.2, 1.0, 0.2), cs)),
|
||||
new Parallelogram(new Vec3(3, -2, 1), new Vec3(0, 0, 4), new Vec3(0, 4, 0), new LambertianMaterial(new ColorRGB(0.2, 0.2, 1.0), cs)),
|
||||
new Parallelogram(new Vec3(-2, 3, 1), new Vec3(4, 0, 0), new Vec3(0, 0, 4), new LambertianMaterial(new ColorRGB(1.0, 0.5, 0.0), cs)),
|
||||
new Parallelogram(new Vec3(-2, -3, 5), new Vec3(4, 0, 0), new Vec3(0, 0, -4), new LambertianMaterial(new ColorRGB(0.2, 0.8, 0.8), cs))
|
||||
new Parallelogram(new Vec3(-3, -2, 5), new Vec3(0, 0, -4), new Vec3(0, 4, 0), new LambertianMaterial(cs.albedo(1.0, 0.2, 0.2))),
|
||||
new Parallelogram(new Vec3(-2, -2, 0), new Vec3(4, 0, 0), new Vec3(0, 4, 0), new LambertianMaterial(cs.albedo(0.2, 1.0, 0.2))),
|
||||
new Parallelogram(new Vec3(3, -2, 1), new Vec3(0, 0, 4), new Vec3(0, 4, 0), new LambertianMaterial(cs.albedo(0.2, 0.2, 1.0))),
|
||||
new Parallelogram(new Vec3(-2, 3, 1), new Vec3(4, 0, 0), new Vec3(0, 0, 4), new LambertianMaterial(cs.albedo(1.0, 0.5, 0.0))),
|
||||
new Parallelogram(new Vec3(-2, -3, 5), new Vec3(4, 0, 0), new Vec3(0, 0, -4), new LambertianMaterial(cs.albedo(0.2, 0.8, 0.8)))
|
||||
)),
|
||||
SimpleCamera.builder()
|
||||
.withImage(height, height)
|
||||
@ -148,10 +148,10 @@ public class Examples {
|
||||
var cs = ColorSpaces.sRGB;
|
||||
return new Example(
|
||||
new Scene(List.of(
|
||||
new Sphere(new Vec3(0, -1000, 0), 1000, new LambertianMaterial(new ColorRGB(0.2, 0.2, 0.2), cs)),
|
||||
new Sphere(new Vec3(0, 2, 0), 2, new LambertianMaterial(new ColorRGB(0.2, 0.2, 0.2), cs)),
|
||||
new Parallelogram(new Vec3(3, 1, -2), new Vec3(2, 0, 0), new Vec3(0, 2, 0), new DiffuseLight(new ColorRGB(4.0, 4.0, 4.0), cs)),
|
||||
new Sphere(new Vec3(0, 7, 0), 2, new DiffuseLight(new ColorRGB(4.0, 4.0, 4.0), cs))
|
||||
new Sphere(new Vec3(0, -1000, 0), 1000, new LambertianMaterial(cs.albedo(0.2, 0.2, 0.2))),
|
||||
new Sphere(new Vec3(0, 2, 0), 2, new LambertianMaterial(cs.albedo(0.2, 0.2, 0.2))),
|
||||
new Parallelogram(new Vec3(3, 1, -2), new Vec3(2, 0, 0), new Vec3(0, 2, 0), new DiffuseLight(cs.illuminant(4.0))),
|
||||
new Sphere(new Vec3(0, 7, 0), 2, new DiffuseLight(cs.illuminant(4.0)))
|
||||
)),
|
||||
SimpleCamera.builder()
|
||||
.withImage(height * 16 / 9, height)
|
||||
@ -166,10 +166,10 @@ public class Examples {
|
||||
if (height <= 0) height = 600;
|
||||
|
||||
var cs = ColorSpaces.sRGB;
|
||||
var red = new LambertianMaterial(new ColorRGB(.65, .05, .05), cs);
|
||||
var white = new LambertianMaterial(new ColorRGB(.73, .73, .73), cs);
|
||||
var green = new LambertianMaterial(new ColorRGB(.12, .45, .15), cs);
|
||||
var light = new DiffuseLight(new ColorRGB(15.0, 15.0, 15.0), cs);
|
||||
var red = new LambertianMaterial(cs.albedo(.65, .05, .05));
|
||||
var white = new LambertianMaterial(cs.albedo(.73, .73, .73));
|
||||
var green = new LambertianMaterial(cs.albedo(.12, .45, .15));
|
||||
var light = new DiffuseLight(cs.illuminant(15.0));
|
||||
|
||||
return new Example(
|
||||
new Scene(List.of(
|
||||
@ -194,10 +194,10 @@ public class Examples {
|
||||
public static @NotNull Example getCornellBoxSmoke(int height) {
|
||||
if (height <= 0) height = 600;
|
||||
var cs = ColorSpaces.sRGB;
|
||||
var red = new LambertianMaterial(new ColorRGB(.65, .05, .05), cs);
|
||||
var white = new LambertianMaterial(new ColorRGB(.73, .73, .73), cs);
|
||||
var green = new LambertianMaterial(new ColorRGB(.12, .45, .15), cs);
|
||||
var light = new DiffuseLight(new ColorRGB(15.0, 15.0, 15.0), cs);
|
||||
var red = new LambertianMaterial(cs.albedo(.65, .05, .05));
|
||||
var white = new LambertianMaterial(cs.albedo(.73, .73, .73));
|
||||
var green = new LambertianMaterial(cs.albedo(.12, .45, .15));
|
||||
var light = new DiffuseLight(cs.illuminant(15.0));
|
||||
|
||||
return new Example(
|
||||
new Scene(List.of(
|
||||
@ -207,13 +207,13 @@ public class Examples {
|
||||
new Box(new Vec3(0, 0, 0), new Vec3(165, 330, 165), white)
|
||||
.rotateY(Math.toRadians(15))
|
||||
.translate(new Vec3(265, 0, 295)),
|
||||
0.01, new IsotropicMaterial(ColorRGB.BLACK, cs)
|
||||
0.01, new IsotropicMaterial(cs.albedo(ColorRGB.BLACK))
|
||||
),
|
||||
new ConstantMedium(
|
||||
new Box(new Vec3(0, 0, 0), new Vec3(165, 165, 165), white)
|
||||
.rotateY(Math.toRadians(-18))
|
||||
.translate(new Vec3(130, 0, 65)),
|
||||
0.01, new IsotropicMaterial(ColorRGB.WHITE, cs)
|
||||
0.01, new IsotropicMaterial(cs.albedo(ColorRGB.WHITE))
|
||||
)
|
||||
)),
|
||||
SimpleCamera.builder()
|
||||
@ -229,10 +229,10 @@ public class Examples {
|
||||
if (height <= 0) height = 600;
|
||||
|
||||
var cs = ColorSpaces.sRGB;
|
||||
var red = new LambertianMaterial(new ColorRGB(.65, .05, .05), cs);
|
||||
var white = new LambertianMaterial(new ColorRGB(.73, .73, .73), cs);
|
||||
var green = new LambertianMaterial(new ColorRGB(.12, .45, .15), cs);
|
||||
var light = new DiffuseLight(new ColorRGB(7.0, 7.0, 7.0), cs);
|
||||
var red = new LambertianMaterial(cs.albedo(.65, .05, .05));
|
||||
var white = new LambertianMaterial(cs.albedo(.73, .73, .73));
|
||||
var green = new LambertianMaterial(cs.albedo(.12, .45, .15));
|
||||
var light = new DiffuseLight(cs.illuminant(7.0));
|
||||
var glass = new DielectricMaterial(1.5);
|
||||
|
||||
var room = new Box(new Vec3(0, 0, 0), new Vec3(555, 555, 555), white, white, red, green, white, null);
|
||||
@ -259,15 +259,15 @@ public class Examples {
|
||||
var cs = ColorSpaces.sRGB;
|
||||
record Partei(String name, ColorRGB color, double stimmen) { }
|
||||
var data = List.of(
|
||||
new Partei("CDU", new ColorRGB(0x00, 0x4B, 0x76), 18.9),
|
||||
new Partei("SPD", new ColorRGB(0xC0, 0x00, 0x3C), 25.7),
|
||||
new Partei("AfD", new ColorRGB(0x80, 0xCD, 0xEC), 10.3),
|
||||
new Partei("FDP", new ColorRGB(0xF7, 0xBB, 0x3D), 11.5),
|
||||
new Partei("DIE LINKE", new ColorRGB(0x5F, 0x31, 0x6E), 4.9),
|
||||
new Partei("GRÜNE", new ColorRGB(0x00, 0x85, 0x4A), 14.8),
|
||||
new Partei("CSU", new ColorRGB(0x00, 0x77, 0xB6), 5.2)
|
||||
new Partei("CDU", new ColorRGB(0x004B76), 18.9),
|
||||
new Partei("SPD", new ColorRGB(0xC0003C), 25.7),
|
||||
new Partei("AfD", new ColorRGB(0x80CDEC), 10.3),
|
||||
new Partei("FDP", new ColorRGB(0xF7BB3D), 11.5),
|
||||
new Partei("DIE LINKE", new ColorRGB(0x5F316E), 4.9),
|
||||
new Partei("GRÜNE", new ColorRGB(0x00854A), 14.8),
|
||||
new Partei("CSU", new ColorRGB(0x0077B6), 5.2)
|
||||
);
|
||||
var white = new LambertianMaterial(new ColorRGB(.99, .99, .99), cs);
|
||||
var white = new LambertianMaterial(cs.albedo(.99, .99, .99));
|
||||
|
||||
var count = data.size();
|
||||
var size = 75d;
|
||||
@ -287,7 +287,7 @@ public class Examples {
|
||||
objects.add(new Box(
|
||||
new Vec3((i + 1) * spacing + i * size, 0, spacing),
|
||||
new Vec3((i + 1) * spacing + (i + 1) * size, partei.stimmen() * 15, spacing + size),
|
||||
new DielectricMaterial(1.5, partei.color(), cs)
|
||||
new DielectricMaterial(1.5, cs.albedo(partei.color()))
|
||||
));
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ public class Examples {
|
||||
|
||||
// boxes
|
||||
var boxes = new ArrayList<Hittable>();
|
||||
var ground = new LambertianMaterial(new ColorRGB(0.48, 0.83, 0.53), cs);
|
||||
var ground = new LambertianMaterial(cs.albedo(0.48, 0.83, 0.53));
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int j = 0; j < 20; j++) {
|
||||
var w = 100.0;
|
||||
@ -364,23 +364,23 @@ public class Examples {
|
||||
// light
|
||||
objects.add(new Parallelogram(
|
||||
new Vec3(123, 554, 147), new Vec3(300, 0, 0), new Vec3(0, 0, 265),
|
||||
new DiffuseLight(new ColorRGB(7., 7., 7.), cs)
|
||||
new DiffuseLight(cs.illuminant(7.0))
|
||||
));
|
||||
|
||||
// spheres with different materials
|
||||
objects.add(new Sphere(new Vec3(400, 400, 200), 50, new LambertianMaterial(new ColorRGB(0.7, 0.3, 0.1), cs)));
|
||||
objects.add(new Sphere(new Vec3(400, 400, 200), 50, new LambertianMaterial(cs.albedo(0.7, 0.3, 0.1))));
|
||||
objects.add(new Sphere(new Vec3(260, 150, 45), 50, new DielectricMaterial(1.5)));
|
||||
objects.add(new Sphere(new Vec3(0, 150, 145), 50, new MetallicMaterial(new ColorRGB(0.8, 0.8, 0.9), cs, 1.0)));
|
||||
objects.add(new Sphere(new Vec3(0, 150, 145), 50, new MetallicMaterial(cs.albedo(0.8, 0.8, 0.9), 1.0)));
|
||||
|
||||
// glass sphere filled with gas
|
||||
var boundary = new Sphere(new Vec3(360, 150, 145), 70, new DielectricMaterial(1.5));
|
||||
objects.add(boundary);
|
||||
objects.add(new ConstantMedium(boundary, 0.2, new IsotropicMaterial(new ColorRGB(0.2, 0.4, 0.9), cs)));
|
||||
objects.add(new ConstantMedium(boundary, 0.2, new IsotropicMaterial(cs.albedo(0.2, 0.4, 0.9))));
|
||||
|
||||
// put the world in a glass sphere
|
||||
objects.add(new ConstantMedium(
|
||||
new Sphere(new Vec3(0, 0, 0), 5000, new DielectricMaterial(1.5)),
|
||||
0.0001, new IsotropicMaterial(new ColorRGB(1., 1., 1.), cs)
|
||||
0.0001, new IsotropicMaterial(cs.albedo(1.0, 1.0, 1.0))
|
||||
));
|
||||
|
||||
// textures spheres
|
||||
@ -388,7 +388,7 @@ public class Examples {
|
||||
objects.add(new Sphere(new Vec3(220, 280, 300), 80, new LambertianMaterial(new PerlinTexture(0.2))));
|
||||
|
||||
// box from spheres
|
||||
var white = new LambertianMaterial(new ColorRGB(.73, .73, .73), cs);
|
||||
var white = new LambertianMaterial(cs.albedo(.73, .73, .73));
|
||||
var spheres = new ArrayList<Hittable>();
|
||||
for (int j = 0; j < 1000; j++) {
|
||||
spheres.add(new Sphere(new Vec3(random.nextDouble(165), random.nextDouble(165), random.nextDouble(165)), 10, white));
|
||||
|
@ -23,11 +23,7 @@ public record ColorRGB(double r, double g, double b) implements IVec3<ColorRGB>
|
||||
}
|
||||
|
||||
public ColorRGB(int rgb) {
|
||||
this((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
|
||||
}
|
||||
|
||||
public ColorRGB(int red, int green, int blue) {
|
||||
this(red / 255f, green / 255f, blue / 255f);
|
||||
this(((rgb >> 16) & 0xFF) / 255d, ((rgb >> 8) & 0xFF) / 255d, (rgb & 0xFF) / 255d);
|
||||
}
|
||||
|
||||
public ColorRGB {
|
||||
|
@ -2,8 +2,7 @@ package eu.jonahbauer.raytracing.render.color;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Matrix3;
|
||||
import eu.jonahbauer.raytracing.math.Vec3;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.DenselySampledSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.Spectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -85,7 +84,7 @@ public final class ColorSpace {
|
||||
}
|
||||
}
|
||||
|
||||
public @NotNull SigmoidPolynomial toSpectrum(@NotNull ColorRGB rgb) {
|
||||
public @NotNull SigmoidPolynomial toPolynomial(@NotNull ColorRGB rgb) {
|
||||
return RGBtoSpectrumTable.get(new ColorRGB(
|
||||
Math.max(0, rgb.r()),
|
||||
Math.max(0, rgb.g()),
|
||||
@ -93,6 +92,38 @@ public final class ColorSpace {
|
||||
));
|
||||
}
|
||||
|
||||
public @NotNull Spectrum toSpectrum(@NotNull ColorRGB rgb, @NotNull Spectrum.Type type) {
|
||||
return switch (type) {
|
||||
case ALBEDO -> new RGBAlbedoSpectrum(this, rgb);
|
||||
case ILLUMINANT -> new RGBIlluminantSpectrum(this, rgb);
|
||||
case UNBOUNDED -> new RGBUnboundedSpectrum(this, rgb);
|
||||
};
|
||||
}
|
||||
|
||||
public @NotNull Spectrum albedo(double r, double g, double b) {
|
||||
return albedo(new ColorRGB(r, g, b));
|
||||
}
|
||||
|
||||
public @NotNull Spectrum albedo(@NotNull ColorRGB rgb) {
|
||||
return toSpectrum(rgb, Spectrum.Type.ALBEDO);
|
||||
}
|
||||
|
||||
public @NotNull Spectrum illuminant(double intensity) {
|
||||
return illuminant.scale(intensity);
|
||||
}
|
||||
|
||||
public @NotNull Spectrum illuminant(double r, double g, double b) {
|
||||
return illuminant(new ColorRGB(r, g, b));
|
||||
}
|
||||
|
||||
public @NotNull Spectrum illuminant(@NotNull ColorRGB rgb) {
|
||||
return toSpectrum(rgb, Spectrum.Type.ILLUMINANT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessors
|
||||
*/
|
||||
|
||||
public @NotNull Chromaticity r() {
|
||||
return r;
|
||||
}
|
||||
|
@ -2,9 +2,6 @@ package eu.jonahbauer.raytracing.render.material;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.math.Vec3;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorRGB;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpace;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBAlbedoSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.Spectra;
|
||||
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
@ -14,25 +11,34 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.random.RandomGenerator;
|
||||
|
||||
public record DielectricMaterial(double refractionIndex, @NotNull Texture texture) implements Material {
|
||||
public DielectricMaterial(double refractionIndex) {
|
||||
this(refractionIndex, Spectra.WHITE);
|
||||
}
|
||||
|
||||
public record DielectricMaterial(@NotNull RefractiveIndex ri, @NotNull Texture texture) implements Material {
|
||||
public DielectricMaterial {
|
||||
Objects.requireNonNull(ri, "ri");
|
||||
Objects.requireNonNull(texture, "texture");
|
||||
}
|
||||
|
||||
public DielectricMaterial(double refractionIndex, @NotNull ColorRGB color, @NotNull ColorSpace cs) {
|
||||
this(refractionIndex, new RGBAlbedoSpectrum(cs, color));
|
||||
public DielectricMaterial(@NotNull RefractiveIndex ri) {
|
||||
this(ri, Spectra.WHITE);
|
||||
}
|
||||
|
||||
public DielectricMaterial(double ri) {
|
||||
this(new ConstantRefractiveIndex(ri), Spectra.WHITE);
|
||||
}
|
||||
|
||||
public DielectricMaterial(double ri, @NotNull Texture texture) {
|
||||
this(new ConstantRefractiveIndex(ri), texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||
var ri = hit.isFrontFace() ? (1 / refractionIndex) : refractionIndex;
|
||||
var ri = switch (this.ri) {
|
||||
case ConstantRefractiveIndex(var x) -> x;
|
||||
case RefractiveIndex x -> x.get(ray.lambda().collapse());
|
||||
};
|
||||
if (hit.isFrontFace()) ri = 1 / ri;
|
||||
|
||||
var cosTheta = Math.min(- ray.direction().unit().dot(hit.normal()), 1.0);
|
||||
var reflectance = reflectance(cosTheta);
|
||||
var reflectance = reflectance(cosTheta, ri);
|
||||
var reflect = reflectance > random.nextDouble();
|
||||
|
||||
var newDirection = (reflect ? Optional.<Vec3>empty() : Vec3.refract(ray.direction(), hit.normal(), ri))
|
||||
@ -42,10 +48,38 @@ public record DielectricMaterial(double refractionIndex, @NotNull Texture textur
|
||||
return Optional.of(new SpecularScatterResult(attenuation, new Ray(hit.position(), newDirection, ray.lambda())));
|
||||
}
|
||||
|
||||
private double reflectance(double cos) {
|
||||
private double reflectance(double cos, double ri) {
|
||||
// use schlick's approximation for reflectance
|
||||
var r0 = (1 - refractionIndex) / (1 + refractionIndex);
|
||||
var r0 = (1 - ri) / (1 + ri);
|
||||
r0 = r0 * r0;
|
||||
return r0 + (1 - r0) * (1 - cos) * (1 - cos) * (1 - cos) * (1 - cos) * (1 - cos);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RefractiveIndex {
|
||||
double get(double lambda);
|
||||
}
|
||||
|
||||
public record ConstantRefractiveIndex(double ri) implements RefractiveIndex {
|
||||
|
||||
@Override
|
||||
public double get(double lambda) {
|
||||
return ri;
|
||||
}
|
||||
}
|
||||
|
||||
public record SellmeierRefractiveIndex(
|
||||
double B1, double B2, double B3,
|
||||
double C1, double C2, double C3
|
||||
) implements RefractiveIndex {
|
||||
|
||||
@Override
|
||||
public double get(double lambda) {
|
||||
var l2 = lambda * lambda * 1E-6; // square and convert to µm
|
||||
var x = 1 + B1 * l2 / (l2 - C1)
|
||||
+ B2 * l2 / (l2 - C2)
|
||||
+ B3 * l2 / (l2 - C3);
|
||||
return Math.sqrt(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
package eu.jonahbauer.raytracing.render.material;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorRGB;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpace;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBIlluminantSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.Spectrum;
|
||||
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
@ -18,10 +15,6 @@ public record DiffuseLight(@NotNull Texture texture) implements Material {
|
||||
Objects.requireNonNull(texture, "texture");
|
||||
}
|
||||
|
||||
public DiffuseLight(@NotNull ColorRGB color, @NotNull ColorSpace cs) {
|
||||
this(new RGBIlluminantSpectrum(cs, color));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||
return Optional.empty();
|
||||
|
@ -2,9 +2,6 @@ package eu.jonahbauer.raytracing.render.material;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.render.renderer.pdf.SphereProbabilityDensityFunction;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorRGB;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpace;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBAlbedoSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.Spectrum;
|
||||
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
@ -19,10 +16,6 @@ public record IsotropicMaterial(@NotNull Spectrum albedo) implements Material {
|
||||
Objects.requireNonNull(albedo, "albedo");
|
||||
}
|
||||
|
||||
public IsotropicMaterial(@NotNull ColorRGB color, @NotNull ColorSpace cs) {
|
||||
this(new RGBAlbedoSpectrum(cs, color));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||
return Optional.of(new PdfScatterResult(albedo(), new SphereProbabilityDensityFunction()));
|
||||
|
@ -2,9 +2,6 @@ package eu.jonahbauer.raytracing.render.material;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.render.renderer.pdf.CosineProbabilityDensityFunction;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorRGB;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpace;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBAlbedoSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -18,10 +15,6 @@ public record LambertianMaterial(@NotNull Texture texture) implements Material {
|
||||
Objects.requireNonNull(texture, "texture");
|
||||
}
|
||||
|
||||
public LambertianMaterial(@NotNull ColorRGB color, @NotNull ColorSpace cs) {
|
||||
this(new RGBAlbedoSpectrum(cs, color));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||
var attenuation = texture.get(hit);
|
||||
|
@ -0,0 +1,25 @@
|
||||
package eu.jonahbauer.raytracing.render.material;
|
||||
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpaces;
|
||||
import eu.jonahbauer.raytracing.render.material.DielectricMaterial.SellmeierRefractiveIndex;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.Spectra;
|
||||
import eu.jonahbauer.raytracing.render.texture.CheckerTexture;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class Materials {
|
||||
public static final @NotNull Material GLASS = new DielectricMaterial(new SellmeierRefractiveIndex(
|
||||
1.0361212, 0.231792344, 1.01046945,
|
||||
6.00069867E-3, 2.00179144E-2, 1.03560653E2
|
||||
));
|
||||
|
||||
public static final @NotNull Material MIRROR = new MetallicMaterial(ColorSpaces.sRGB.albedo(0.7, 0.7, 0.7));
|
||||
|
||||
public static final @NotNull Material DEBUG = new DirectionalMaterial(
|
||||
new LambertianMaterial(new CheckerTexture(50.0, ColorSpaces.sRGB.albedo(1.0, 0.0, 1.0), Spectra.BLACK)),
|
||||
new LambertianMaterial(new CheckerTexture(50.0, ColorSpaces.sRGB.albedo(1.0, 1.0, 1.0), Spectra.BLACK))
|
||||
);
|
||||
|
||||
private Materials() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@ -2,9 +2,6 @@ package eu.jonahbauer.raytracing.render.material;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.math.Vec3;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorRGB;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpace;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBAlbedoSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -19,14 +16,6 @@ public record MetallicMaterial(@NotNull Texture texture, double fuzz) implements
|
||||
this(texture, 0);
|
||||
}
|
||||
|
||||
public MetallicMaterial(@NotNull ColorRGB color, @NotNull ColorSpace cs) {
|
||||
this(color, cs, 0);
|
||||
}
|
||||
|
||||
public MetallicMaterial(@NotNull ColorRGB color, @NotNull ColorSpace cs, double fuzz) {
|
||||
this(new RGBAlbedoSpectrum(cs, color), fuzz);
|
||||
}
|
||||
|
||||
public MetallicMaterial {
|
||||
Objects.requireNonNull(texture, "texture");
|
||||
if (fuzz < 0 || !Double.isFinite(fuzz)) throw new IllegalArgumentException("fuzz must be non-negative");
|
||||
|
@ -12,7 +12,7 @@ public final class RGBAlbedoSpectrum implements Spectrum {
|
||||
if (rgb.r() < 0 || rgb.r() > 1 || rgb.g() < 0 || rgb.g() > 1 || rgb.b() < 0 || rgb.b() > 1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.polynomial = cs.toSpectrum(rgb);
|
||||
this.polynomial = cs.toPolynomial(rgb);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -20,7 +20,7 @@ public final class RGBIlluminantSpectrum implements Spectrum {
|
||||
}
|
||||
var max = Math.max(rgb.r(), Math.max(rgb.g(), rgb.b()));
|
||||
this.scale = 2 * max;
|
||||
this.polynomial = cs.toSpectrum(scale != 0 ? rgb.div(scale) : ColorRGB.BLACK);
|
||||
this.polynomial = cs.toPolynomial(scale != 0 ? rgb.div(scale) : ColorRGB.BLACK);
|
||||
this.illuminant = cs.illuminant();
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ public final class RGBUnboundedSpectrum implements Spectrum {
|
||||
}
|
||||
var max = Math.max(rgb.r(), Math.max(rgb.g(), rgb.b()));
|
||||
this.scale = 2 * max;
|
||||
this.polynomial = cs.toSpectrum(scale != 0 ? rgb.div(scale) : ColorRGB.BLACK);
|
||||
this.polynomial = cs.toPolynomial(scale != 0 ? rgb.div(scale) : ColorRGB.BLACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,4 +72,8 @@ public interface Spectrum extends Texture, SkyBox {
|
||||
default @NotNull SampledSpectrum getColor(@NotNull Ray ray) {
|
||||
return this.sample(ray.lambda());
|
||||
}
|
||||
|
||||
enum Type {
|
||||
ALBEDO, ILLUMINANT, UNBOUNDED
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ package eu.jonahbauer.raytracing.render.texture;
|
||||
import eu.jonahbauer.raytracing.math.Vec3;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorRGB;
|
||||
import eu.jonahbauer.raytracing.render.color.ColorSpace;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBAlbedoSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.RGBIlluminantSpectrum;
|
||||
import eu.jonahbauer.raytracing.render.spectrum.Spectrum;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -21,7 +19,7 @@ public final class ImageTexture implements Texture {
|
||||
private final int height;
|
||||
private final @NotNull Spectrum[][] spectra;
|
||||
|
||||
public ImageTexture(@NotNull BufferedImage image, @NotNull ColorSpace cs, @NotNull Type type, boolean gamma) {
|
||||
public ImageTexture(@NotNull BufferedImage image, @NotNull ColorSpace cs, @NotNull Spectrum.Type type, boolean gamma) {
|
||||
this.width = image.getWidth();
|
||||
this.height = image.getHeight();
|
||||
this.spectra = new Spectrum[height][width];
|
||||
@ -30,13 +28,13 @@ public final class ImageTexture implements Texture {
|
||||
for (int x = 0; x < width; x++) {
|
||||
var rgb = new ColorRGB(image.getRGB(x, y));
|
||||
if (gamma) rgb = ColorRGB.inverseGamma(rgb);
|
||||
spectra[y][x] = type.newSpectrum(cs, rgb);
|
||||
spectra[y][x] = cs.toSpectrum(rgb, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ImageTexture(@NotNull String path, @NotNull ColorSpace cs) {
|
||||
this(read(path), cs, Type.ALBEDO, true);
|
||||
this(read(path), cs, Spectrum.Type.ALBEDO, true);
|
||||
}
|
||||
|
||||
private static @NotNull BufferedImage read(@NotNull String path) {
|
||||
@ -55,22 +53,4 @@ public final class ImageTexture implements Texture {
|
||||
int y = (int) (v * (height - 1));
|
||||
return spectra[y][x];
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
ALBEDO {
|
||||
@Override
|
||||
protected @NotNull Spectrum newSpectrum(@NotNull ColorSpace cs, @NotNull ColorRGB rgb) {
|
||||
return new RGBAlbedoSpectrum(cs, rgb);
|
||||
}
|
||||
},
|
||||
ILLUMINANT {
|
||||
@Override
|
||||
protected @NotNull Spectrum newSpectrum(@NotNull ColorSpace cs, @NotNull ColorRGB rgb) {
|
||||
return new RGBIlluminantSpectrum(cs, rgb);
|
||||
}
|
||||
},
|
||||
;
|
||||
|
||||
protected abstract @NotNull Spectrum newSpectrum(@NotNull ColorSpace cs, @NotNull ColorRGB rgb);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user