auto-git:
[add] tests/domain/celestial-shadows.test.ts
This commit is contained in:
143
tests/domain/celestial-shadows.test.ts
Normal file
143
tests/domain/celestial-shadows.test.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import {
|
||||
OrthographicCamera,
|
||||
PerspectiveCamera
|
||||
} from "three";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
fitCelestialDirectionalShadow,
|
||||
resolveDominantCelestialShadowCaster
|
||||
} from "../../src/rendering/celestial-shadows";
|
||||
|
||||
describe("celestial shadows", () => {
|
||||
it("chooses one deterministic dominant celestial shadow caster", () => {
|
||||
const sun = {
|
||||
colorHex: "#fff1d5",
|
||||
intensity: 1.6,
|
||||
direction: {
|
||||
x: 0.45,
|
||||
y: 0.88,
|
||||
z: 0.15
|
||||
}
|
||||
};
|
||||
const moon = {
|
||||
colorHex: "#99b5ff",
|
||||
intensity: 0.4,
|
||||
direction: {
|
||||
x: -0.45,
|
||||
y: 0.72,
|
||||
z: -0.2
|
||||
}
|
||||
};
|
||||
|
||||
expect(resolveDominantCelestialShadowCaster(sun, moon)?.key).toBe("sun");
|
||||
expect(
|
||||
resolveDominantCelestialShadowCaster(
|
||||
{
|
||||
...sun,
|
||||
intensity: 0.1
|
||||
},
|
||||
{
|
||||
...moon,
|
||||
intensity: 0.35
|
||||
}
|
||||
)?.key
|
||||
).toBe("moon");
|
||||
expect(
|
||||
resolveDominantCelestialShadowCaster(
|
||||
{
|
||||
...sun,
|
||||
intensity: 0
|
||||
},
|
||||
null
|
||||
)
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("fits a bounded perspective shadow volume around the active view", () => {
|
||||
const camera = new PerspectiveCamera(60, 16 / 9, 0.1, 1000);
|
||||
camera.position.set(0, 12, 24);
|
||||
camera.lookAt(0, 4, 0);
|
||||
camera.updateMatrixWorld();
|
||||
|
||||
const fit = fitCelestialDirectionalShadow({
|
||||
activeCamera: camera,
|
||||
focusTarget: {
|
||||
center: {
|
||||
x: 0,
|
||||
y: 4,
|
||||
z: 0
|
||||
},
|
||||
radius: 6
|
||||
},
|
||||
lightDirection: {
|
||||
x: 0.45,
|
||||
y: 0.88,
|
||||
z: 0.15
|
||||
},
|
||||
mapSize: 2048,
|
||||
sceneBounds: {
|
||||
min: {
|
||||
x: -500,
|
||||
y: -10,
|
||||
z: -500
|
||||
},
|
||||
max: {
|
||||
x: 500,
|
||||
y: 40,
|
||||
z: 500
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(fit).not.toBeNull();
|
||||
expect(fit?.cameraBounds.right).toBeGreaterThan(0);
|
||||
expect(fit?.cameraBounds.top).toBeGreaterThan(0);
|
||||
expect((fit?.cameraBounds.right ?? 0) - (fit?.cameraBounds.left ?? 0)).toBeGreaterThan(30);
|
||||
expect((fit?.cameraBounds.right ?? 0) - (fit?.cameraBounds.left ?? 0)).toBeLessThan(280);
|
||||
expect(fit?.cameraBounds.far).toBeGreaterThan(fit?.cameraBounds.near ?? 0);
|
||||
expect(fit?.normalBias ?? 0).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("fits orthographic viewport shadows without collapsing depth coverage", () => {
|
||||
const camera = new OrthographicCamera(-12, 12, 10, -10, 0.1, 1000);
|
||||
camera.position.set(0, 30, 0);
|
||||
camera.lookAt(0, 0, 0);
|
||||
camera.updateMatrixWorld();
|
||||
|
||||
const fit = fitCelestialDirectionalShadow({
|
||||
activeCamera: camera,
|
||||
focusTarget: {
|
||||
center: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
radius: 8
|
||||
},
|
||||
lightDirection: {
|
||||
x: -0.25,
|
||||
y: 0.92,
|
||||
z: 0.3
|
||||
},
|
||||
mapSize: 1024,
|
||||
sceneBounds: {
|
||||
min: {
|
||||
x: -40,
|
||||
y: -2,
|
||||
z: -40
|
||||
},
|
||||
max: {
|
||||
x: 40,
|
||||
y: 18,
|
||||
z: 40
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(fit).not.toBeNull();
|
||||
expect((fit?.cameraBounds.right ?? 0) - (fit?.cameraBounds.left ?? 0)).toBeGreaterThan(20);
|
||||
expect((fit?.cameraBounds.top ?? 0) - (fit?.cameraBounds.bottom ?? 0)).toBeGreaterThan(20);
|
||||
expect(fit?.cameraBounds.far).toBeGreaterThan(20);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user