add a material that looks different on both sides
This commit is contained in:
parent
a22b1cb238
commit
f7d9153ad8
@ -22,7 +22,7 @@ public record DielectricMaterial(double refractionIndex, @NotNull Texture textur
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||||
var ri = hit.frontFace() ? (1 / refractionIndex) : refractionIndex;
|
var ri = hit.isFrontFace() ? (1 / refractionIndex) : refractionIndex;
|
||||||
|
|
||||||
var cosTheta = Math.min(- ray.direction().unit().times(hit.normal()), 1.0);
|
var cosTheta = Math.min(- ray.direction().unit().times(hit.normal()), 1.0);
|
||||||
var reflectance = reflectance(cosTheta);
|
var reflectance = reflectance(cosTheta);
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package eu.jonahbauer.raytracing.render.material;
|
||||||
|
|
||||||
|
import eu.jonahbauer.raytracing.math.Ray;
|
||||||
|
import eu.jonahbauer.raytracing.math.Vec3;
|
||||||
|
import eu.jonahbauer.raytracing.render.texture.Color;
|
||||||
|
import eu.jonahbauer.raytracing.render.texture.Texture;
|
||||||
|
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.random.RandomGenerator;
|
||||||
|
|
||||||
|
public final class DirectionalMaterial implements Material {
|
||||||
|
private final @Nullable Material front;
|
||||||
|
private final @Nullable Material back;
|
||||||
|
|
||||||
|
private final @NotNull Texture texture;
|
||||||
|
|
||||||
|
public DirectionalMaterial(@Nullable Material front, @Nullable Material back) {
|
||||||
|
this.front = front;
|
||||||
|
this.back = back;
|
||||||
|
this.texture = new DirectionalTexture(
|
||||||
|
front != null ? front.texture() : null,
|
||||||
|
back != null ? back.texture() : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Texture texture() {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||||
|
if (hit.isFrontFace()) {
|
||||||
|
if (front != null) return front.scatter(ray, hit, random);
|
||||||
|
} else {
|
||||||
|
if (back != null) return back.scatter(ray, hit, random);
|
||||||
|
}
|
||||||
|
// let the ray pass through without obstruction
|
||||||
|
return Optional.of(new ScatterResult(new Ray(ray.at(hit.t()), ray.direction()), Color.WHITE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Color emitted(@NotNull HitResult hit) {
|
||||||
|
if (hit.isFrontFace()) {
|
||||||
|
if (front != null) return front.emitted(hit);
|
||||||
|
} else {
|
||||||
|
if (back != null) return back.emitted(hit);
|
||||||
|
}
|
||||||
|
return Color.BLACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private record DirectionalTexture(@Nullable Texture front, @Nullable Texture back) implements Texture {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Color get(double u, double v, @NotNull Vec3 p) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUVRequired() {
|
||||||
|
return front() != null && front().isUVRequired() || back() != null && back().isUVRequired();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public record HitResult(
|
public record HitResult(
|
||||||
double t, @NotNull Vec3 position, @NotNull Vec3 normal,
|
double t, @NotNull Vec3 position, @NotNull Vec3 normal,
|
||||||
@NotNull Material material, double u, double v, boolean frontFace
|
@NotNull Material material, double u, double v, boolean isFrontFace
|
||||||
) implements Comparable<HitResult> {
|
) implements Comparable<HitResult> {
|
||||||
public HitResult {
|
public HitResult {
|
||||||
Objects.requireNonNull(position, "position");
|
Objects.requireNonNull(position, "position");
|
||||||
@ -16,7 +16,7 @@ public record HitResult(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull HitResult withPositionAndNormal(@NotNull Vec3 position, @NotNull Vec3 normal) {
|
public @NotNull HitResult withPositionAndNormal(@NotNull Vec3 position, @NotNull Vec3 normal) {
|
||||||
return new HitResult(t, position, normal, material, u, v, frontFace);
|
return new HitResult(t, position, normal, material, u, v, isFrontFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,7 +32,7 @@ public record ConstantMedium(@NotNull Hittable boundary, double density, @NotNul
|
|||||||
if (hitDistance > distance) return Optional.empty();
|
if (hitDistance > distance) return Optional.empty();
|
||||||
|
|
||||||
var t = tmin + hitDistance / length;
|
var t = tmin + hitDistance / length;
|
||||||
return Optional.of(new HitResult(t, ray.at(t), Vec3.UNIT_X, material, 0, 0, true)); // arbitrary normal and frontFace
|
return Optional.of(new HitResult(t, ray.at(t), Vec3.UNIT_X, material, 0, 0, true)); // arbitrary normal, u, v and isFrontFace
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user