rework interface between materials and rgb colors

feature/spectral
jbb01 5 months ago
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…
Cancel
Save