mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-11 22:02:21 +00:00
Merge branch 'german/refactor-e5-navara-mesh-colour' into german/navara-refactor
This commit is contained in:
commit
5b27f26e14
7 files changed
+129
-107
No files matched your search
@@ -538,9 +538,10 @@ Cesium draws a synchronous Primitive with a flat material, no back-face
|
|||||||
culling and no depth writes. Colour, image and visibility changes retain the
|
culling and no depth writes. Colour, image and visibility changes retain the
|
||||||
primitive; geometry, pick-id and depth-test changes replace it. The engine
|
primitive; geometry, pick-id and depth-test changes replace it. The engine
|
||||||
requests frames while the primitive or its image is preparing. Navara draws
|
requests frames while the primitive or its image is preparing. Navara draws
|
||||||
local coordinates relative to a double-precision world origin in its
|
local coordinates relative to a double-precision world origin in the shared
|
||||||
transparent scene pass after tone mapping, with scene depth and triangle
|
overlay pass after tone mapping and anti-aliasing, the pass that draws sprites
|
||||||
picking. Their authored colours are blended in display space.
|
and lines, with scene depth and triangle picking. Their authored colours are
|
||||||
|
blended in display space.
|
||||||
Both engines own geometry, material and texture disposal. The fake engine
|
Both engines own geometry, material and texture disposal. The fake engine
|
||||||
keeps the same state and tests triangle intersections for picks.
|
keeps the same state and tests triangle intersections for picks.
|
||||||
|
|
||||||
|
|||||||
@@ -237,12 +237,6 @@ async function runOn(browser, kind) {
|
|||||||
outcome.push({ name, skipped: owner[1] });
|
outcome.push({ name, skipped: owner[1] });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const knownFailure =
|
|
||||||
engine.kind === 'navara' &&
|
|
||||||
name ===
|
|
||||||
'meshes.createMesh: a single colour draws as asked within 10 per channel'
|
|
||||||
? 'Meshes are drawn before tone mapping'
|
|
||||||
: null;
|
|
||||||
try {
|
try {
|
||||||
await run();
|
await run();
|
||||||
outcome.push({ name, ok: true });
|
outcome.push({ name, ok: true });
|
||||||
@@ -250,10 +244,6 @@ async function runOn(browser, kind) {
|
|||||||
outcome.push({
|
outcome.push({
|
||||||
name,
|
name,
|
||||||
ok: false,
|
ok: false,
|
||||||
...(knownFailure &&
|
|
||||||
String(error?.message).startsWith(
|
|
||||||
'mesh colour within 10 per channel',
|
|
||||||
) && { knownFailure }),
|
|
||||||
error: String(error?.message ?? error),
|
error: String(error?.message ?? error),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export async function createNavaraGlobe({ container, search, hd = false }) {
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
lines: createNavaraLines(view, { overlay }),
|
lines: createNavaraLines(view, { overlay }),
|
||||||
meshes: (parts) => createNavaraMeshes(view, { MeshDesc, ...parts }),
|
meshes: (parts) => createNavaraMeshes(view, { overlay, ...parts }),
|
||||||
ground: createNavaraGround(view, {
|
ground: createNavaraGround(view, {
|
||||||
createPass: createGroundPass,
|
createPass: createGroundPass,
|
||||||
pulseField: (options) =>
|
pulseField: (options) =>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import {
|
|||||||
BufferAttribute,
|
BufferAttribute,
|
||||||
BufferGeometry,
|
BufferGeometry,
|
||||||
CanvasTexture,
|
CanvasTexture,
|
||||||
Color,
|
|
||||||
DoubleSide,
|
DoubleSide,
|
||||||
Group,
|
Group,
|
||||||
Mesh,
|
Mesh,
|
||||||
@@ -14,39 +13,11 @@ import {
|
|||||||
} from 'three';
|
} from 'three';
|
||||||
import { createMeshRegistry } from '../meshes.js';
|
import { createMeshRegistry } from '../meshes.js';
|
||||||
import { cartesian3 } from '../../geo/index.js';
|
import { cartesian3 } from '../../geo/index.js';
|
||||||
import { attachSceneDepth, createSceneDepthTest } from './sceneDepth.js';
|
import { createSceneDepthTest } from './sceneDepth.js';
|
||||||
|
|
||||||
const KIND = 'gevWorldMesh';
|
|
||||||
const NEAR_SURFACE_M = 2;
|
const NEAR_SURFACE_M = 2;
|
||||||
const registered = new WeakSet();
|
|
||||||
|
|
||||||
export function createNavaraMeshes(view, { MeshDesc, camera, picker }) {
|
export function createNavaraMeshes(view, { overlay, camera, picker }) {
|
||||||
if (!registered.has(view)) {
|
|
||||||
view.registerMesh(
|
|
||||||
KIND,
|
|
||||||
class extends MeshDesc {
|
|
||||||
constructor(owner, ctx, config) {
|
|
||||||
super(owner, ctx, config);
|
|
||||||
this.resource = config[KIND];
|
|
||||||
}
|
|
||||||
// Transparent, drawn after the effects: the colours are the ones
|
|
||||||
// asked for (as Cesium draws them), not tone-mapped with the look.
|
|
||||||
// The scene-depth test hides a mesh behind terrain, tiles and Earth.
|
|
||||||
getPassKey() {
|
|
||||||
return 'transparent';
|
|
||||||
}
|
|
||||||
createMesh() {
|
|
||||||
attachSceneDepth(this.resource.group, this.ctx);
|
|
||||||
return this.resource.group;
|
|
||||||
}
|
|
||||||
onDestroy() {
|
|
||||||
this.resource.dispose();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
registered.add(view);
|
|
||||||
}
|
|
||||||
const registry = createMeshRegistry(
|
const registry = createMeshRegistry(
|
||||||
(state) => {
|
(state) => {
|
||||||
const group = new Group();
|
const group = new Group();
|
||||||
@@ -60,18 +31,14 @@ export function createNavaraMeshes(view, { MeshDesc, camera, picker }) {
|
|||||||
const mesh = new Mesh(geometry, material);
|
const mesh = new Mesh(geometry, material);
|
||||||
const sceneDepth = createSceneDepthTest();
|
const sceneDepth = createSceneDepthTest();
|
||||||
sceneDepth.material(material);
|
sceneDepth.material(material);
|
||||||
sceneDepth.object(group);
|
|
||||||
sceneDepth.object(mesh);
|
sceneDepth.object(mesh);
|
||||||
let depthFree = false;
|
let depthFree = false;
|
||||||
const pigment = new Color();
|
|
||||||
const bindDepth = mesh.onBeforeRender;
|
const bindDepth = mesh.onBeforeRender;
|
||||||
mesh.onBeforeRender = function onBeforeRender(...args) {
|
mesh.onBeforeRender = function onBeforeRender(...args) {
|
||||||
|
// The overlay context can arrive after the mesh is created.
|
||||||
|
sceneDepth.attach(overlay.ctx);
|
||||||
bindDepth.apply(this, args);
|
bindDepth.apply(this, args);
|
||||||
if (depthFree) sceneDepth.uniforms.uGevSceneDepthOn.value = 0;
|
if (depthFree) sceneDepth.uniforms.uGevSceneDepthOn.value = 0;
|
||||||
// The pass still scales by the view's exposure: undo it.
|
|
||||||
material.color
|
|
||||||
.copy(pigment)
|
|
||||||
.multiplyScalar(1 / Math.max(1, view.toneMappingExposure ?? 1));
|
|
||||||
};
|
};
|
||||||
group.frustumCulled = mesh.frustumCulled = false;
|
group.frustumCulled = mesh.frustumCulled = false;
|
||||||
group.add(mesh);
|
group.add(mesh);
|
||||||
@@ -116,17 +83,15 @@ export function createNavaraMeshes(view, { MeshDesc, camera, picker }) {
|
|||||||
material.needsUpdate = true;
|
material.needsUpdate = true;
|
||||||
} else if (texture && !texture.isVideoTexture && 'image' in patch)
|
} else if (texture && !texture.isVideoTexture && 'image' in patch)
|
||||||
texture.needsUpdate = true;
|
texture.needsUpdate = true;
|
||||||
pigment.setRGB(...next.color.slice(0, 3), SRGBColorSpace);
|
material.color.setRGB(...next.color.slice(0, 3), SRGBColorSpace);
|
||||||
material.color.copy(pigment);
|
|
||||||
material.opacity = next.color[3];
|
material.opacity = next.color[3];
|
||||||
depthFree = next.depthTest === 'always';
|
depthFree = next.depthTest === 'always';
|
||||||
material.depthTest = !depthFree;
|
material.depthTest = !depthFree;
|
||||||
group.visible = next.show;
|
group.visible = next.show;
|
||||||
}
|
}
|
||||||
let holder;
|
|
||||||
try {
|
try {
|
||||||
update(state, state);
|
update(state, state);
|
||||||
holder = view.addMesh({ [KIND]: { group, dispose } });
|
overlay.add(group);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispose();
|
dispose();
|
||||||
throw error;
|
throw error;
|
||||||
@@ -137,7 +102,7 @@ export function createNavaraMeshes(view, { MeshDesc, camera, picker }) {
|
|||||||
update,
|
update,
|
||||||
destroy() {
|
destroy() {
|
||||||
try {
|
try {
|
||||||
holder.delete();
|
overlay.remove(group);
|
||||||
} finally {
|
} finally {
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import { Group, Vector3 } from 'three';
|
import {
|
||||||
|
Color,
|
||||||
|
Group,
|
||||||
|
RGBADepthPacking,
|
||||||
|
ShaderLib,
|
||||||
|
SRGBColorSpace,
|
||||||
|
Vector3,
|
||||||
|
} from 'three';
|
||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
import { createNavaraMeshes } from './meshes.js';
|
import { createNavaraMeshes } from './meshes.js';
|
||||||
import { createCctvMeshes } from '../../layers/cctv/render/meshes.js';
|
import { createCctvMeshes } from '../../layers/cctv/render/meshes.js';
|
||||||
@@ -8,40 +15,30 @@ import { viewshedColors } from '../../data/cctvViewshed.js';
|
|||||||
|
|
||||||
function harness() {
|
function harness() {
|
||||||
const scene = new Group();
|
const scene = new Group();
|
||||||
const kinds = new Map();
|
|
||||||
const handles = new Set();
|
const handles = new Set();
|
||||||
let requests = 0;
|
let requests = 0;
|
||||||
let fail = false;
|
let fail = false;
|
||||||
let failedGeometryDisposals = 0;
|
let failedGeometryDisposals = 0;
|
||||||
class MeshDesc {
|
|
||||||
onDestroy() {}
|
|
||||||
}
|
|
||||||
const view = {
|
const view = {
|
||||||
forceUpdate: () => requests++,
|
forceUpdate: () => requests++,
|
||||||
registerMesh: (kind, desc) => kinds.set(kind, desc),
|
toneMappingExposure: 1,
|
||||||
addMesh(config) {
|
};
|
||||||
|
const overlay = {
|
||||||
|
ctx: null,
|
||||||
|
add(object) {
|
||||||
if (fail) {
|
if (fail) {
|
||||||
config.gevWorldMesh.group.children[0].geometry.addEventListener(
|
object.children[0].geometry.addEventListener(
|
||||||
'dispose',
|
'dispose',
|
||||||
() => failedGeometryDisposals++,
|
() => failedGeometryDisposals++,
|
||||||
);
|
);
|
||||||
throw new Error('descriptor failed');
|
throw new Error('overlay failed');
|
||||||
}
|
}
|
||||||
const kind = Object.keys(config)[0];
|
|
||||||
const desc = new (kinds.get(kind))(view, {}, config);
|
|
||||||
// After the effects, depth-tested against the scene's packed depth.
|
|
||||||
assert.equal(desc.getPassKey(), 'transparent');
|
|
||||||
const object = desc.createMesh();
|
|
||||||
scene.add(object);
|
scene.add(object);
|
||||||
const handle = {
|
handles.add(object);
|
||||||
delete() {
|
},
|
||||||
handles.delete(handle);
|
remove(object) {
|
||||||
scene.remove(object);
|
scene.remove(object);
|
||||||
desc.onDestroy();
|
handles.delete(object);
|
||||||
},
|
|
||||||
};
|
|
||||||
handles.add(handle);
|
|
||||||
return handle;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const pickers = new Set();
|
const pickers = new Set();
|
||||||
@@ -57,7 +54,7 @@ function harness() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const port = createNavaraMeshes(view, {
|
const port = createNavaraMeshes(view, {
|
||||||
MeshDesc,
|
overlay,
|
||||||
camera: engine.camera,
|
camera: engine.camera,
|
||||||
picker: engine.picker,
|
picker: engine.picker,
|
||||||
});
|
});
|
||||||
@@ -66,6 +63,8 @@ function harness() {
|
|||||||
return {
|
return {
|
||||||
owner,
|
owner,
|
||||||
port,
|
port,
|
||||||
|
view,
|
||||||
|
overlay,
|
||||||
drawn: () => scene.children.at(-1)?.children[0],
|
drawn: () => scene.children.at(-1)?.children[0],
|
||||||
engine,
|
engine,
|
||||||
scene,
|
scene,
|
||||||
@@ -82,6 +81,83 @@ const positions = { capCenter: { x: 6378137, y: 1234, z: 5678 } };
|
|||||||
const identity = { x: 0, y: 0, z: 0, w: 1 };
|
const identity = { x: 0, y: 0, z: 0, w: 1 };
|
||||||
const canvas = () => ({ width: 8, height: 8, tagName: 'CANVAS' });
|
const canvas = () => ({ width: 8, height: 8, tagName: 'CANVAS' });
|
||||||
|
|
||||||
|
test('solid and textured overlay meshes keep authored colours through landscape exposure changes', () => {
|
||||||
|
const h = harness();
|
||||||
|
for (const image of [null, canvas()]) {
|
||||||
|
const handle = h.engine.meshes.createMesh({
|
||||||
|
id: image ? 'textured' : 'solid',
|
||||||
|
positions: [6378137, 0, 0, 6378137, 10, 0, 6378137, 0, 10],
|
||||||
|
indices: [0, 1, 2],
|
||||||
|
uv: [0, 0, 1, 0, 0, 1],
|
||||||
|
image,
|
||||||
|
});
|
||||||
|
const mesh = h.drawn();
|
||||||
|
assert.equal(mesh.parent.parent, h.scene);
|
||||||
|
assert.equal(mesh.material.toneMapped, false);
|
||||||
|
assert.equal(mesh.material.transparent, true);
|
||||||
|
assert.equal(mesh.material.depthWrite, false);
|
||||||
|
if (image) assert.equal(mesh.material.map.colorSpace, SRGBColorSpace);
|
||||||
|
for (const color of [
|
||||||
|
[0, 1, 0, 1],
|
||||||
|
[0.25, 0.5, 0.75, 0.4],
|
||||||
|
]) {
|
||||||
|
handle.update({ color });
|
||||||
|
const expected = new Color().setRGB(...color.slice(0, 3), SRGBColorSpace);
|
||||||
|
for (const exposure of [1, 10, 1]) {
|
||||||
|
h.view.toneMappingExposure = exposure;
|
||||||
|
mesh.onBeforeRender({});
|
||||||
|
assert.deepEqual(mesh.material.color, expected);
|
||||||
|
assert.equal(mesh.material.opacity, color[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handle.destroy();
|
||||||
|
assert.equal(h.scene.children.length, 0);
|
||||||
|
}
|
||||||
|
h.port.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('overlay meshes bind late and replaced scene depth and honour depth-test updates', () => {
|
||||||
|
const h = harness();
|
||||||
|
const plane = h.owner.createPlane(
|
||||||
|
'depth',
|
||||||
|
h.owner.createMaterial(canvas()),
|
||||||
|
shape,
|
||||||
|
positions,
|
||||||
|
identity,
|
||||||
|
);
|
||||||
|
const mesh = h.drawn();
|
||||||
|
const shader = {
|
||||||
|
uniforms: {},
|
||||||
|
fragmentShader: ShaderLib.basic.fragmentShader,
|
||||||
|
};
|
||||||
|
mesh.material.onBeforeCompile(shader, null);
|
||||||
|
assert.match(shader.fragmentShader, /packedDepthOccluded/);
|
||||||
|
const renderer = { getRenderTarget: () => ({ width: 640, height: 360 }) };
|
||||||
|
const { tGevSceneDepth, uGevSceneDepthOn, uGevTargetSize } = shader.uniforms;
|
||||||
|
mesh.onBeforeRender(renderer);
|
||||||
|
assert.equal(uGevSceneDepthOn.value, 0);
|
||||||
|
const mrt = { depthBuffer: {}, depthBufferPacking: RGBADepthPacking };
|
||||||
|
h.overlay.ctx = { findEffect: (key) => (key === 'mrt' ? mrt : null) };
|
||||||
|
mesh.onBeforeRender(renderer);
|
||||||
|
assert.equal(tGevSceneDepth.value, mrt.depthBuffer);
|
||||||
|
assert.equal(uGevSceneDepthOn.value, 1);
|
||||||
|
assert.deepEqual(uGevTargetSize.value.toArray(), [640, 360]);
|
||||||
|
plane.mesh.update({ depthTest: 'always' });
|
||||||
|
mesh.onBeforeRender(renderer);
|
||||||
|
assert.equal(uGevSceneDepthOn.value, 0);
|
||||||
|
assert.equal(mesh.material.depthTest, false);
|
||||||
|
plane.mesh.update({ depthTest: 'normal' });
|
||||||
|
mrt.depthBuffer = {};
|
||||||
|
mesh.onBeforeRender({ getDrawingBufferSize: (size) => size.set(1280, 720) });
|
||||||
|
assert.equal(tGevSceneDepth.value, mrt.depthBuffer);
|
||||||
|
assert.equal(uGevSceneDepthOn.value, 1);
|
||||||
|
assert.equal(mesh.material.depthTest, true);
|
||||||
|
assert.deepEqual(uGevTargetSize.value.toArray(), [1280, 720]);
|
||||||
|
h.owner.destroy();
|
||||||
|
h.port.destroy();
|
||||||
|
assert.equal(h.scene.children.length, 0);
|
||||||
|
});
|
||||||
|
|
||||||
test('Navara CCTV plane preserves native rotated geometry, UVs and metre precision', (t) => {
|
test('Navara CCTV plane preserves native rotated geometry, UVs and metre precision', (t) => {
|
||||||
const h = harness();
|
const h = harness();
|
||||||
t.after(() => {
|
t.after(() => {
|
||||||
@@ -213,7 +289,7 @@ test('world meshes release replaced images and video callbacks exactly once', ()
|
|||||||
assert.equal(finalDisposed, 1);
|
assert.equal(finalDisposed, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('world mesh descriptor failure releases geometry and rejects later creates after teardown', () => {
|
test('world mesh overlay failure releases geometry and rejects later creates after teardown', () => {
|
||||||
const h = harness();
|
const h = harness();
|
||||||
h.fail();
|
h.fail();
|
||||||
assert.throws(
|
assert.throws(
|
||||||
@@ -225,7 +301,7 @@ test('world mesh descriptor failure releases geometry and rejects later creates
|
|||||||
positions,
|
positions,
|
||||||
identity,
|
identity,
|
||||||
),
|
),
|
||||||
/descriptor failed/,
|
/overlay failed/,
|
||||||
);
|
);
|
||||||
assert.equal(h.failedGeometryDisposals(), 1);
|
assert.equal(h.failedGeometryDisposals(), 1);
|
||||||
assert.equal(h.handles.size, 0);
|
assert.equal(h.handles.size, 0);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// gev's screen overlays on Navara: sprites, points and lines (engine.movers
|
// gev's screen overlays on Navara: sprites, points, lines and world meshes
|
||||||
// and engine.lines) drawn into the frame after Navara's tone mapping,
|
// (engine.movers, engine.lines and engine.meshes) drawn after tone mapping,
|
||||||
// anti-aliasing (SMAA/FXAA) and the gev sharpening, so their
|
// anti-aliasing (SMAA/FXAA) and the gev sharpening, so their
|
||||||
// colours are the colours asked for (as Cesium draws billboards and
|
// colours are the colours asked for (as Cesium draws billboards and
|
||||||
// polylines), not tone-mapped or graded with the look. A public Navara
|
// polylines), not tone-mapped or graded with the look. A public Navara
|
||||||
|
|||||||
@@ -78,34 +78,25 @@ test('the test binds the MRT pass packed depth before each draw, and only packed
|
|||||||
assert.equal(depth.uniforms.tGevSceneDepth.value, null);
|
assert.equal(depth.uniforms.tGevSceneDepth.value, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
/** A Navara view that builds each descriptor as the SDK does. */
|
/** An overlay that exposes the scene's packed depth to its meshes. */
|
||||||
function fakeView() {
|
function fakeView() {
|
||||||
const kinds = new Map();
|
|
||||||
const created = [];
|
const created = [];
|
||||||
const mrt = {
|
const mrt = {
|
||||||
depthBuffer: new DataTexture(),
|
depthBuffer: new DataTexture(),
|
||||||
depthBufferPacking: RGBADepthPacking,
|
depthBufferPacking: RGBADepthPacking,
|
||||||
};
|
};
|
||||||
const ctx = { findEffect: (key) => (key === 'mrt' ? mrt : undefined) };
|
const ctx = { findEffect: (key) => (key === 'mrt' ? mrt : undefined) };
|
||||||
class MeshDesc {
|
|
||||||
constructor(view, context, config) {
|
|
||||||
this.ctx = context;
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
onDestroy() {}
|
|
||||||
}
|
|
||||||
const view = {
|
const view = {
|
||||||
forceUpdate() {},
|
forceUpdate() {},
|
||||||
registerMesh: (kind, desc) => kinds.set(kind, desc),
|
|
||||||
addMesh(config) {
|
|
||||||
const kind = Object.keys(config)[0];
|
|
||||||
const desc = new (kinds.get(kind))(view, ctx, config);
|
|
||||||
const object = desc.createMesh();
|
|
||||||
created.push({ kind, pass: desc.getPassKey(), object });
|
|
||||||
return { delete: () => desc.onDestroy() };
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
return { view, MeshDesc, created, mrt };
|
const overlay = {
|
||||||
|
ctx,
|
||||||
|
add(object) {
|
||||||
|
created.push(object);
|
||||||
|
},
|
||||||
|
remove() {},
|
||||||
|
};
|
||||||
|
return { view, overlay, created, mrt };
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Every renderable under an object compiles with the test and binds depth. */
|
/** Every renderable under an object compiles with the test and binds depth. */
|
||||||
@@ -141,11 +132,11 @@ function assertTested(object, mrt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test('pack meshes stay transparent and test the scene depth', () => {
|
test('pack meshes draw in the overlay and test the scene depth', () => {
|
||||||
const packs = fakeView();
|
const packs = fakeView();
|
||||||
const owned = [];
|
const owned = [];
|
||||||
const port = createNavaraMeshes(packs.view, {
|
const port = createNavaraMeshes(packs.view, {
|
||||||
MeshDesc: packs.MeshDesc,
|
overlay: packs.overlay,
|
||||||
camera: {},
|
camera: {},
|
||||||
picker: { registerMeshPicker: () => () => {} },
|
picker: { registerMeshPicker: () => () => {} },
|
||||||
});
|
});
|
||||||
@@ -156,9 +147,8 @@ test('pack meshes stay transparent and test the scene depth', () => {
|
|||||||
{ own: (fn) => owned.push(fn) },
|
{ own: (fn) => owned.push(fn) },
|
||||||
);
|
);
|
||||||
assert.equal(packs.created.length, 1);
|
assert.equal(packs.created.length, 1);
|
||||||
assert.equal(packs.created[0].pass, 'transparent');
|
assertTested(packs.created[0], packs.mrt);
|
||||||
assertTested(packs.created[0].object, packs.mrt);
|
assert.equal(packs.created[0].children[0].material.depthTest, true);
|
||||||
assert.equal(packs.created[0].object.children[0].material.depthTest, true);
|
|
||||||
for (const release of owned) release();
|
for (const release of owned) release();
|
||||||
port.destroy();
|
port.destroy();
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user