@flighthq/scene3d-wgpu 0.2.1-next.840.857425c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anisotropyPbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/anisotropyPbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/anisotropyPbrWgpuMeshMaterialRenderer.js +52 -0
- package/dist/anisotropyPbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/blinnPhongWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/blinnPhongWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/blinnPhongWgpuMeshMaterialRenderer.js +66 -0
- package/dist/blinnPhongWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/clearcoatPbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/clearcoatPbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/clearcoatPbrWgpuMeshMaterialRenderer.js +52 -0
- package/dist/clearcoatPbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/customShaderWgpuMeshMaterialRenderer.d.ts +7 -0
- package/dist/customShaderWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/customShaderWgpuMeshMaterialRenderer.js +225 -0
- package/dist/customShaderWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/depthWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/depthWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/depthWgpuMeshMaterialRenderer.js +42 -0
- package/dist/depthWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/drawWgpuScene3D.d.ts +4 -0
- package/dist/drawWgpuScene3D.d.ts.map +1 -0
- package/dist/drawWgpuScene3D.js +171 -0
- package/dist/drawWgpuScene3D.js.map +1 -0
- package/dist/emissiveWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/emissiveWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/emissiveWgpuMeshMaterialRenderer.js +51 -0
- package/dist/emissiveWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/enableWgpuScene3DCustomShaderGuards.d.ts +5 -0
- package/dist/enableWgpuScene3DCustomShaderGuards.d.ts.map +1 -0
- package/dist/enableWgpuScene3DCustomShaderGuards.js +56 -0
- package/dist/enableWgpuScene3DCustomShaderGuards.js.map +1 -0
- package/dist/enableWgpuScene3DForwardLightSelectionGuards.d.ts +4 -0
- package/dist/enableWgpuScene3DForwardLightSelectionGuards.d.ts.map +1 -0
- package/dist/enableWgpuScene3DForwardLightSelectionGuards.js +17 -0
- package/dist/enableWgpuScene3DForwardLightSelectionGuards.js.map +1 -0
- package/dist/explainWgpuScene3DForwardLightSelection.d.ts +3 -0
- package/dist/explainWgpuScene3DForwardLightSelection.d.ts.map +1 -0
- package/dist/explainWgpuScene3DForwardLightSelection.js +18 -0
- package/dist/explainWgpuScene3DForwardLightSelection.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/iridescencePbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/iridescencePbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/iridescencePbrWgpuMeshMaterialRenderer.js +60 -0
- package/dist/iridescencePbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/lambertWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/lambertWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/lambertWgpuMeshMaterialRenderer.js +61 -0
- package/dist/lambertWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/matcapWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/matcapWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/matcapWgpuMeshMaterialRenderer.js +54 -0
- package/dist/matcapWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/normalWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/normalWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/normalWgpuMeshMaterialRenderer.js +47 -0
- package/dist/normalWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/phongWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/phongWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/phongWgpuMeshMaterialRenderer.js +63 -0
- package/dist/phongWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/prepareWgpuScene3DForwardLights.d.ts +3 -0
- package/dist/prepareWgpuScene3DForwardLights.d.ts.map +1 -0
- package/dist/prepareWgpuScene3DForwardLights.js +110 -0
- package/dist/prepareWgpuScene3DForwardLights.js.map +1 -0
- package/dist/registerStandardPbrWgpuMaterial.d.ts +3 -0
- package/dist/registerStandardPbrWgpuMaterial.d.ts.map +1 -0
- package/dist/registerStandardPbrWgpuMaterial.js +11 -0
- package/dist/registerStandardPbrWgpuMaterial.js.map +1 -0
- package/dist/shadedWgpuMeshMaterialRenderer.d.ts +11 -0
- package/dist/shadedWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/shadedWgpuMeshMaterialRenderer.js +47 -0
- package/dist/shadedWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/sheenPbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/sheenPbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/sheenPbrWgpuMeshMaterialRenderer.js +58 -0
- package/dist/sheenPbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/specularGlossinessPbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/specularGlossinessPbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/specularGlossinessPbrWgpuMeshMaterialRenderer.js +126 -0
- package/dist/specularGlossinessPbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/specularPbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/specularPbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/specularPbrWgpuMeshMaterialRenderer.js +65 -0
- package/dist/specularPbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/standardPbrWgpuMeshMaterialRenderer.d.ts +9 -0
- package/dist/standardPbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/standardPbrWgpuMeshMaterialRenderer.js +174 -0
- package/dist/standardPbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/subsurfacePbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/subsurfacePbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/subsurfacePbrWgpuMeshMaterialRenderer.js +68 -0
- package/dist/subsurfacePbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/toonWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/toonWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/toonWgpuMeshMaterialRenderer.js +71 -0
- package/dist/toonWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/transmissionVolumePbrWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/transmissionVolumePbrWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/transmissionVolumePbrWgpuMeshMaterialRenderer.js +74 -0
- package/dist/transmissionVolumePbrWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/unlitWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/unlitWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/unlitWgpuMeshMaterialRenderer.js +57 -0
- package/dist/unlitWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/vertexColorWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/vertexColorWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/vertexColorWgpuMeshMaterialRenderer.js +55 -0
- package/dist/vertexColorWgpuMeshMaterialRenderer.js.map +1 -0
- package/dist/wgpuClassicPrelude.d.ts +8 -0
- package/dist/wgpuClassicPrelude.d.ts.map +1 -0
- package/dist/wgpuClassicPrelude.js +319 -0
- package/dist/wgpuClassicPrelude.js.map +1 -0
- package/dist/wgpuCustomMaterialAbi.d.ts +3 -0
- package/dist/wgpuCustomMaterialAbi.d.ts.map +1 -0
- package/dist/wgpuCustomMaterialAbi.js +5 -0
- package/dist/wgpuCustomMaterialAbi.js.map +1 -0
- package/dist/wgpuDebugPrelude.d.ts +7 -0
- package/dist/wgpuDebugPrelude.d.ts.map +1 -0
- package/dist/wgpuDebugPrelude.js +133 -0
- package/dist/wgpuDebugPrelude.js.map +1 -0
- package/dist/wgpuEnvironmentCube.d.ts +4 -0
- package/dist/wgpuEnvironmentCube.d.ts.map +1 -0
- package/dist/wgpuEnvironmentCube.js +66 -0
- package/dist/wgpuEnvironmentCube.js.map +1 -0
- package/dist/wgpuEnvironmentIblBake.d.ts +4 -0
- package/dist/wgpuEnvironmentIblBake.d.ts.map +1 -0
- package/dist/wgpuEnvironmentIblBake.js +458 -0
- package/dist/wgpuEnvironmentIblBake.js.map +1 -0
- package/dist/wgpuEnvironmentSkybox.d.ts +3 -0
- package/dist/wgpuEnvironmentSkybox.d.ts.map +1 -0
- package/dist/wgpuEnvironmentSkybox.js +159 -0
- package/dist/wgpuEnvironmentSkybox.js.map +1 -0
- package/dist/wgpuMatcapPrelude.d.ts +7 -0
- package/dist/wgpuMatcapPrelude.d.ts.map +1 -0
- package/dist/wgpuMatcapPrelude.js +134 -0
- package/dist/wgpuMatcapPrelude.js.map +1 -0
- package/dist/wgpuMeshMaterialRegistry.d.ts +5 -0
- package/dist/wgpuMeshMaterialRegistry.d.ts.map +1 -0
- package/dist/wgpuMeshMaterialRegistry.js +29 -0
- package/dist/wgpuMeshMaterialRegistry.js.map +1 -0
- package/dist/wgpuMeshPipeline.d.ts +43 -0
- package/dist/wgpuMeshPipeline.d.ts.map +1 -0
- package/dist/wgpuMeshPipeline.js +1007 -0
- package/dist/wgpuMeshPipeline.js.map +1 -0
- package/dist/wgpuMeshUpload.d.ts +3 -0
- package/dist/wgpuMeshUpload.d.ts.map +1 -0
- package/dist/wgpuMeshUpload.js +58 -0
- package/dist/wgpuMeshUpload.js.map +1 -0
- package/dist/wgpuParticleEmitter3D.d.ts +4 -0
- package/dist/wgpuParticleEmitter3D.d.ts.map +1 -0
- package/dist/wgpuParticleEmitter3D.js +403 -0
- package/dist/wgpuParticleEmitter3D.js.map +1 -0
- package/dist/wgpuPbrPipelineCache.d.ts +4 -0
- package/dist/wgpuPbrPipelineCache.d.ts.map +1 -0
- package/dist/wgpuPbrPipelineCache.js +52 -0
- package/dist/wgpuPbrPipelineCache.js.map +1 -0
- package/dist/wgpuPbrPrelude.d.ts +7 -0
- package/dist/wgpuPbrPrelude.d.ts.map +1 -0
- package/dist/wgpuPbrPrelude.js +551 -0
- package/dist/wgpuPbrPrelude.js.map +1 -0
- package/dist/wgpuScene3DRuntime.d.ts +5 -0
- package/dist/wgpuScene3DRuntime.d.ts.map +1 -0
- package/dist/wgpuScene3DRuntime.js +81 -0
- package/dist/wgpuScene3DRuntime.js.map +1 -0
- package/dist/wgpuScene3DTestHelper.d.ts +14 -0
- package/dist/wgpuScene3DTestHelper.d.ts.map +1 -0
- package/dist/wgpuScene3DTestHelper.js +121 -0
- package/dist/wgpuScene3DTestHelper.js.map +1 -0
- package/dist/wgpuScene3DTime.d.ts +4 -0
- package/dist/wgpuScene3DTime.d.ts.map +1 -0
- package/dist/wgpuScene3DTime.js +11 -0
- package/dist/wgpuScene3DTime.js.map +1 -0
- package/dist/wgpuShadedModifierSnippet.d.ts +4 -0
- package/dist/wgpuShadedModifierSnippet.d.ts.map +1 -0
- package/dist/wgpuShadedModifierSnippet.js +18 -0
- package/dist/wgpuShadedModifierSnippet.js.map +1 -0
- package/dist/wgpuShadedPrelude.d.ts +16 -0
- package/dist/wgpuShadedPrelude.d.ts.map +1 -0
- package/dist/wgpuShadedPrelude.js +625 -0
- package/dist/wgpuShadedPrelude.js.map +1 -0
- package/dist/wgpuShadowMap.d.ts +4 -0
- package/dist/wgpuShadowMap.d.ts.map +1 -0
- package/dist/wgpuShadowMap.js +155 -0
- package/dist/wgpuShadowMap.js.map +1 -0
- package/dist/wgpuSkinPalette.d.ts +7 -0
- package/dist/wgpuSkinPalette.d.ts.map +1 -0
- package/dist/wgpuSkinPalette.js +173 -0
- package/dist/wgpuSkinPalette.js.map +1 -0
- package/dist/wgpuToonPrelude.d.ts +8 -0
- package/dist/wgpuToonPrelude.d.ts.map +1 -0
- package/dist/wgpuToonPrelude.js +192 -0
- package/dist/wgpuToonPrelude.js.map +1 -0
- package/dist/wgpuUnlitPrelude.d.ts +9 -0
- package/dist/wgpuUnlitPrelude.d.ts.map +1 -0
- package/dist/wgpuUnlitPrelude.js +142 -0
- package/dist/wgpuUnlitPrelude.js.map +1 -0
- package/dist/wgpuWireframePrelude.d.ts +6 -0
- package/dist/wgpuWireframePrelude.d.ts.map +1 -0
- package/dist/wgpuWireframePrelude.js +77 -0
- package/dist/wgpuWireframePrelude.js.map +1 -0
- package/dist/wgpuWireframeUpload.d.ts +3 -0
- package/dist/wgpuWireframeUpload.d.ts.map +1 -0
- package/dist/wgpuWireframeUpload.js +68 -0
- package/dist/wgpuWireframeUpload.js.map +1 -0
- package/dist/wireframeWgpuMeshMaterialRenderer.d.ts +4 -0
- package/dist/wireframeWgpuMeshMaterialRenderer.d.ts.map +1 -0
- package/dist/wireframeWgpuMeshMaterialRenderer.js +69 -0
- package/dist/wireframeWgpuMeshMaterialRenderer.js.map +1 -0
- package/package.json +57 -0
- package/src/anisotropyPbrWgpuMeshMaterialRenderer.test.ts +90 -0
- package/src/blinnPhongWgpuMeshMaterialRenderer.test.ts +82 -0
- package/src/clearcoatPbrWgpuMeshMaterialRenderer.test.ts +90 -0
- package/src/customShaderWgpuMeshMaterialRenderer.test.ts +207 -0
- package/src/depthWgpuMeshMaterialRenderer.test.ts +69 -0
- package/src/drawWgpuScene3D.test.ts +247 -0
- package/src/emissiveWgpuMeshMaterialRenderer.test.ts +64 -0
- package/src/enableWgpuScene3DCustomShaderGuards.test.ts +73 -0
- package/src/enableWgpuScene3DForwardLightSelectionGuards.test.ts +39 -0
- package/src/explainWgpuScene3DForwardLightSelection.test.ts +15 -0
- package/src/iridescencePbrWgpuMeshMaterialRenderer.test.ts +90 -0
- package/src/lambertWgpuMeshMaterialRenderer.test.ts +77 -0
- package/src/matcapWgpuMeshMaterialRenderer.test.ts +69 -0
- package/src/normalWgpuMeshMaterialRenderer.test.ts +69 -0
- package/src/phongWgpuMeshMaterialRenderer.test.ts +79 -0
- package/src/prepareWgpuScene3DForwardLights.test.ts +84 -0
- package/src/registerStandardPbrWgpuMaterial.test.ts +15 -0
- package/src/shadedWgpuMeshMaterialRenderer.test.ts +63 -0
- package/src/sheenPbrWgpuMeshMaterialRenderer.test.ts +87 -0
- package/src/specularGlossinessPbrWgpuMeshMaterialRenderer.test.ts +100 -0
- package/src/specularPbrWgpuMeshMaterialRenderer.test.ts +90 -0
- package/src/standardPbrWgpuMeshMaterialRenderer.test.ts +172 -0
- package/src/subsurfacePbrWgpuMeshMaterialRenderer.test.ts +90 -0
- package/src/toonWgpuMeshMaterialRenderer.test.ts +89 -0
- package/src/transmissionVolumePbrWgpuMeshMaterialRenderer.test.ts +97 -0
- package/src/unlitWgpuMeshMaterialRenderer.test.ts +94 -0
- package/src/vertexColorWgpuMeshMaterialRenderer.test.ts +62 -0
- package/src/wgpuClassicPrelude.test.ts +176 -0
- package/src/wgpuDebugPrelude.test.ts +79 -0
- package/src/wgpuEnvironmentCube.test.ts +86 -0
- package/src/wgpuEnvironmentIblBake.test.ts +79 -0
- package/src/wgpuEnvironmentSkybox.test.ts +56 -0
- package/src/wgpuMatcapPrelude.test.ts +70 -0
- package/src/wgpuMeshMaterialRegistry.test.ts +55 -0
- package/src/wgpuMeshPipeline.test.ts +844 -0
- package/src/wgpuMeshUpload.test.ts +177 -0
- package/src/wgpuParticleEmitter3D.test.ts +200 -0
- package/src/wgpuPbrPipelineCache.test.ts +67 -0
- package/src/wgpuPbrPrelude.test.ts +162 -0
- package/src/wgpuScene3DRuntime.test.ts +35 -0
- package/src/wgpuScene3DTime.test.ts +20 -0
- package/src/wgpuShadedModifierSnippet.test.ts +33 -0
- package/src/wgpuShadedPrelude.test.ts +394 -0
- package/src/wgpuShadowMap.test.ts +169 -0
- package/src/wgpuSkinPalette.test.ts +88 -0
- package/src/wgpuToonPrelude.test.ts +93 -0
- package/src/wgpuUnlitPrelude.test.ts +102 -0
- package/src/wgpuWireframePrelude.test.ts +54 -0
- package/src/wgpuWireframeUpload.test.ts +36 -0
- package/src/wireframeWgpuMeshMaterialRenderer.test.ts +69 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createNormalMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { NormalMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import { normalWgpuMeshMaterialRenderer, registerNormalWgpuMaterial } from './normalWgpuMeshMaterialRenderer';
|
|
9
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
10
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
11
|
+
|
|
12
|
+
function makeCamera(): Camera3D {
|
|
13
|
+
return createCamera3D({ far: 100, near: 0.1, projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' } });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const NO_LIGHTS: Scene3DLightBlock = {
|
|
17
|
+
ambientCount: 0,
|
|
18
|
+
data: new Float32Array(12),
|
|
19
|
+
directionalCount: 0,
|
|
20
|
+
hemisphereCount: 0,
|
|
21
|
+
pointCount: 0,
|
|
22
|
+
spotCount: 0,
|
|
23
|
+
version: 1,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
27
|
+
const geometry = createBoxMeshGeometry();
|
|
28
|
+
return {
|
|
29
|
+
material: createNormalMaterial(),
|
|
30
|
+
normalMatrix: createMatrix3(),
|
|
31
|
+
subset: geometry.subsets[0],
|
|
32
|
+
worldMatrix: createMatrix4(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('normalWgpuMeshMaterialRenderer', () => {
|
|
37
|
+
it('bind selects the normal pipeline and writes the frame + material uniforms', () => {
|
|
38
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
39
|
+
normalWgpuMeshMaterialRenderer.bind(state, createNormalMaterial({ normalScale: 2 }), NO_LIGHTS, makeCamera());
|
|
40
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
41
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
42
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
43
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('draw issues an indexed draw over the subset after bind', () => {
|
|
47
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
48
|
+
const proxy = makeProxy();
|
|
49
|
+
normalWgpuMeshMaterialRenderer.bind(state, proxy.material, NO_LIGHTS, makeCamera());
|
|
50
|
+
normalWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
51
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
52
|
+
expect(drawCall).toBeDefined();
|
|
53
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
57
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
58
|
+
normalWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
59
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('registerNormalWgpuMaterial', () => {
|
|
64
|
+
it('installs the renderer for NormalMaterialKind', () => {
|
|
65
|
+
const { state } = makeWgpuScene3DState();
|
|
66
|
+
registerNormalWgpuMaterial(state);
|
|
67
|
+
expect(getWgpuMeshMaterialRenderer(state, NormalMaterialKind)).toBe(normalWgpuMeshMaterialRenderer);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createPhongMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { PhongMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import { phongWgpuMeshMaterialRenderer, registerPhongWgpuMaterial } from './phongWgpuMeshMaterialRenderer';
|
|
9
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
10
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
11
|
+
|
|
12
|
+
function makeCamera(): Camera3D {
|
|
13
|
+
return createCamera3D({ far: 100, near: 0.1, projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' } });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function makeLights(): Scene3DLightBlock {
|
|
17
|
+
const data = new Float32Array(12);
|
|
18
|
+
data[0] = 0;
|
|
19
|
+
data[1] = -1;
|
|
20
|
+
data[2] = 0;
|
|
21
|
+
data[4] = 1;
|
|
22
|
+
data[5] = 1;
|
|
23
|
+
data[6] = 1;
|
|
24
|
+
data[8] = 0.1;
|
|
25
|
+
data[9] = 0.1;
|
|
26
|
+
data[10] = 0.1;
|
|
27
|
+
return { ambientCount: 1, data, directionalCount: 1, hemisphereCount: 0, pointCount: 0, spotCount: 0, version: 1 };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
31
|
+
const geometry = createBoxMeshGeometry();
|
|
32
|
+
return {
|
|
33
|
+
material: createPhongMaterial(),
|
|
34
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
35
|
+
subset: geometry.subsets[0],
|
|
36
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe('phongWgpuMeshMaterialRenderer', () => {
|
|
41
|
+
it('bind selects a phong pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
42
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
43
|
+
phongWgpuMeshMaterialRenderer.bind(state, createPhongMaterial(), makeLights(), makeCamera());
|
|
44
|
+
|
|
45
|
+
const moduleCall = fake.calls.find((c) => c.name === 'createShaderModule');
|
|
46
|
+
const code = (moduleCall!.args[0] as { code: string }).code;
|
|
47
|
+
expect(code).toContain('const LIGHTING_PHONG : bool = true;');
|
|
48
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
49
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
50
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
54
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
55
|
+
const proxy = makeProxy();
|
|
56
|
+
const geometry = createBoxMeshGeometry();
|
|
57
|
+
phongWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
58
|
+
phongWgpuMeshMaterialRenderer.draw(state, proxy, geometry);
|
|
59
|
+
|
|
60
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
61
|
+
expect(drawCall).toBeDefined();
|
|
62
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
63
|
+
expect(drawCall!.args[2]).toBe(proxy.subset.indexOffset);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
67
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
68
|
+
phongWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
69
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('registerPhongWgpuMaterial', () => {
|
|
74
|
+
it('installs the renderer for PhongMaterialKind', () => {
|
|
75
|
+
const { state } = makeWgpuScene3DState();
|
|
76
|
+
registerPhongWgpuMaterial(state);
|
|
77
|
+
expect(getWgpuMeshMaterialRenderer(state, PhongMaterialKind)).toBe(phongWgpuMeshMaterialRenderer);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createCamera3D, setCamera3DViewMatrix4FromLookAt } from '@flighthq/camera';
|
|
2
|
+
import { createPointLight, createSpotLight } from '@flighthq/lighting';
|
|
3
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
4
|
+
import { addNodeChild } from '@flighthq/node';
|
|
5
|
+
import { prepareScene3DRender } from '@flighthq/render';
|
|
6
|
+
import { createMesh, createNode3D, Node3DKind } from '@flighthq/scene3d';
|
|
7
|
+
import type { Camera3D, Scene3DLightsLike } from '@flighthq/types';
|
|
8
|
+
import { SCENE_LIGHT_POINT_OFFSET } from '@flighthq/types';
|
|
9
|
+
|
|
10
|
+
import { prepareWgpuScene3DForwardLights } from './prepareWgpuScene3DForwardLights';
|
|
11
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
12
|
+
|
|
13
|
+
function camera(): Camera3D {
|
|
14
|
+
const result = createCamera3D({
|
|
15
|
+
far: 100,
|
|
16
|
+
near: 0.1,
|
|
17
|
+
projection: { aspect: 1, fovY: Math.PI / 2, kind: 'perspective' },
|
|
18
|
+
});
|
|
19
|
+
setCamera3DViewMatrix4FromLookAt(result, { x: 4, y: 0, z: 20 }, { x: 4, y: 0, z: 0 }, { x: 0, y: 1, z: 0 });
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function clusteredLights(): Scene3DLightsLike {
|
|
24
|
+
return {
|
|
25
|
+
ambient: null,
|
|
26
|
+
directional: null,
|
|
27
|
+
point: [8, 8, 8, 8, 0, 0, 0, 0].map((x, index) =>
|
|
28
|
+
createPointLight({ position: { x, y: index % 4, z: 0 }, range: -1 }),
|
|
29
|
+
),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('prepareWgpuScene3DForwardLights', () => {
|
|
34
|
+
it('packs independent four-light point and spot budgets', () => {
|
|
35
|
+
const { state } = makeWgpuScene3DState();
|
|
36
|
+
const scene = createNode3D(Node3DKind);
|
|
37
|
+
addNodeChild(scene, createMesh(createBoxMeshGeometry(), []));
|
|
38
|
+
const lights: Scene3DLightsLike = {
|
|
39
|
+
ambient: null,
|
|
40
|
+
directional: null,
|
|
41
|
+
point: Array.from({ length: 6 }, (_, index) =>
|
|
42
|
+
createPointLight({ position: { x: index + 1, y: 0, z: 0 }, range: -1 }),
|
|
43
|
+
),
|
|
44
|
+
spot: Array.from({ length: 6 }, (_, index) =>
|
|
45
|
+
createSpotLight({
|
|
46
|
+
direction: { x: -1, y: 0, z: 0 },
|
|
47
|
+
innerConeDegrees: 45,
|
|
48
|
+
outerConeDegrees: 60,
|
|
49
|
+
position: { x: index + 1, y: 0, z: 0 },
|
|
50
|
+
range: -1,
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
};
|
|
54
|
+
const block = prepareWgpuScene3DForwardLights(state, prepareScene3DRender(state, scene, camera(), lights), lights)
|
|
55
|
+
.meshLightBlocks[0];
|
|
56
|
+
expect(block.pointCount).toBe(4);
|
|
57
|
+
expect(block.spotCount).toBe(4);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('selects per visible mesh, deduplicates tuples, and reuses scratch', () => {
|
|
61
|
+
const { state } = makeWgpuScene3DState();
|
|
62
|
+
const scene = createNode3D(Node3DKind);
|
|
63
|
+
const nearA = createMesh(createBoxMeshGeometry(), []);
|
|
64
|
+
const nearB = createMesh(createBoxMeshGeometry(), []);
|
|
65
|
+
nearB.position.x = 0.1;
|
|
66
|
+
const far = createMesh(createBoxMeshGeometry(), []);
|
|
67
|
+
far.position.x = 8;
|
|
68
|
+
addNodeChild(scene, nearA);
|
|
69
|
+
addNodeChild(scene, nearB);
|
|
70
|
+
addNodeChild(scene, far);
|
|
71
|
+
const lights = clusteredLights();
|
|
72
|
+
const renderList = prepareScene3DRender(state, scene, camera(), lights);
|
|
73
|
+
const first = prepareWgpuScene3DForwardLights(state, renderList, lights);
|
|
74
|
+
const blocks = first.meshLightBlocks;
|
|
75
|
+
|
|
76
|
+
expect(first.meshCount).toBe(3);
|
|
77
|
+
expect(blocks[0]).toBe(blocks[1]);
|
|
78
|
+
expect(blocks[0]).not.toBe(blocks[2]);
|
|
79
|
+
expect(blocks[0].data[SCENE_LIGHT_POINT_OFFSET]).toBe(0);
|
|
80
|
+
expect(blocks[2].data[SCENE_LIGHT_POINT_OFFSET]).toBe(8);
|
|
81
|
+
expect(prepareWgpuScene3DForwardLights(state, renderList, lights)).toBe(first);
|
|
82
|
+
expect(first.meshLightBlocks).toBe(blocks);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StandardPbrMaterialKind } from '@flighthq/types';
|
|
2
|
+
|
|
3
|
+
import { registerStandardPbrWgpuMaterial } from './registerStandardPbrWgpuMaterial';
|
|
4
|
+
import { standardPbrWgpuMeshMaterialRenderer } from './standardPbrWgpuMeshMaterialRenderer';
|
|
5
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
6
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
7
|
+
|
|
8
|
+
describe('registerStandardPbrWgpuMaterial', () => {
|
|
9
|
+
it('registers the StandardPbr renderer for StandardPbrMaterialKind', () => {
|
|
10
|
+
const { state } = makeWgpuScene3DState();
|
|
11
|
+
expect(getWgpuMeshMaterialRenderer(state, StandardPbrMaterialKind)).toBeNull();
|
|
12
|
+
registerStandardPbrWgpuMaterial(state);
|
|
13
|
+
expect(getWgpuMeshMaterialRenderer(state, StandardPbrMaterialKind)).toBe(standardPbrWgpuMeshMaterialRenderer);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createShadedMaterial } from '@flighthq/shading';
|
|
3
|
+
import type { Scene3DLightBlock } from '@flighthq/types';
|
|
4
|
+
import { ShadedMaterialKind } from '@flighthq/types';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
getWgpuShadedBaseFlags,
|
|
8
|
+
registerShadedWgpuMaterial,
|
|
9
|
+
shadedWgpuMeshMaterialRenderer,
|
|
10
|
+
} from './shadedWgpuMeshMaterialRenderer';
|
|
11
|
+
|
|
12
|
+
describe('getWgpuShadedBaseFlags', () => {
|
|
13
|
+
it('resolves the base pipeline flags from a material', () => {
|
|
14
|
+
const material = createShadedMaterial();
|
|
15
|
+
material.alphaMode = 'mask';
|
|
16
|
+
material.doubleSided = true;
|
|
17
|
+
expect(getWgpuShadedBaseFlags(material)).toEqual({
|
|
18
|
+
alphaMaskEnabled: true,
|
|
19
|
+
doubleSided: true,
|
|
20
|
+
hasDiffuseMap: false,
|
|
21
|
+
hasNormalMap: false,
|
|
22
|
+
hasSpecularMap: false,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
27
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
28
|
+
|
|
29
|
+
describe('registerShadedWgpuMaterial', () => {
|
|
30
|
+
it('installs the renderer for ShadedMaterialKind', () => {
|
|
31
|
+
const { state } = makeWgpuScene3DState();
|
|
32
|
+
registerShadedWgpuMaterial(state);
|
|
33
|
+
expect(getWgpuMeshMaterialRenderer(state, ShadedMaterialKind)).toBe(shadedWgpuMeshMaterialRenderer);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('shadedWgpuMeshMaterialRenderer', () => {
|
|
38
|
+
it('bind compiles a shaded module and binds frame, material, and sample groups', () => {
|
|
39
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
40
|
+
const camera = createCamera3D({
|
|
41
|
+
far: 100,
|
|
42
|
+
near: 0.1,
|
|
43
|
+
projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' },
|
|
44
|
+
});
|
|
45
|
+
shadedWgpuMeshMaterialRenderer.bind(state, createShadedMaterial(), LIGHTS, camera);
|
|
46
|
+
const module = fake.calls.find((call) => call.name === 'createShaderModule');
|
|
47
|
+
expect(module).toBeDefined();
|
|
48
|
+
expect((module!.args[0] as { code: string }).code).toContain('struct ClassicMaterial');
|
|
49
|
+
expect((module!.args[0] as { code: string }).code).not.toContain('modifierData');
|
|
50
|
+
expect(fake.calls.some((call) => call.name === 'setPipeline')).toBe(true);
|
|
51
|
+
expect(fake.calls.filter((call) => call.name === 'setBindGroup').length).toBeGreaterThanOrEqual(3);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const LIGHTS: Scene3DLightBlock = {
|
|
56
|
+
ambientCount: 0,
|
|
57
|
+
data: new Float32Array(128),
|
|
58
|
+
directionalCount: 0,
|
|
59
|
+
hemisphereCount: 0,
|
|
60
|
+
pointCount: 0,
|
|
61
|
+
spotCount: 0,
|
|
62
|
+
version: 1,
|
|
63
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createSheenPbrMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { SheenPbrMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import { registerSheenPbrWgpuMaterial, sheenPbrWgpuMeshMaterialRenderer } from './sheenPbrWgpuMeshMaterialRenderer';
|
|
9
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
10
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
11
|
+
|
|
12
|
+
function makeCamera(): Camera3D {
|
|
13
|
+
return createCamera3D({ far: 100, near: 0.1, projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' } });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function makeLights(): Scene3DLightBlock {
|
|
17
|
+
const data = new Float32Array(12);
|
|
18
|
+
data[1] = -1;
|
|
19
|
+
data[4] = 1;
|
|
20
|
+
data[5] = 1;
|
|
21
|
+
data[6] = 1;
|
|
22
|
+
data[8] = 0.1;
|
|
23
|
+
data[9] = 0.1;
|
|
24
|
+
data[10] = 0.1;
|
|
25
|
+
return { ambientCount: 1, data, directionalCount: 1, hemisphereCount: 0, pointCount: 0, spotCount: 0, version: 1 };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
29
|
+
const geometry = createBoxMeshGeometry();
|
|
30
|
+
return {
|
|
31
|
+
material: createSheenPbrMaterial({ sheenColor: 0xffffffff }),
|
|
32
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
33
|
+
subset: geometry.subsets[0],
|
|
34
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('registerSheenPbrWgpuMaterial', () => {
|
|
39
|
+
it('installs the renderer for SheenPbrMaterialKind', () => {
|
|
40
|
+
const { state } = makeWgpuScene3DState();
|
|
41
|
+
registerSheenPbrWgpuMaterial(state);
|
|
42
|
+
expect(getWgpuMeshMaterialRenderer(state, SheenPbrMaterialKind)).toBe(sheenPbrWgpuMeshMaterialRenderer);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('sheenPbrWgpuMeshMaterialRenderer', () => {
|
|
47
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
48
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
49
|
+
sheenPbrWgpuMeshMaterialRenderer.bind(
|
|
50
|
+
state,
|
|
51
|
+
createSheenPbrMaterial({ sheenColor: 0xffffffff }),
|
|
52
|
+
makeLights(),
|
|
53
|
+
makeCamera(),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
57
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
58
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
59
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('bind compiles the SHEEN extension variant', () => {
|
|
63
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
64
|
+
sheenPbrWgpuMeshMaterialRenderer.bind(state, createSheenPbrMaterial(), makeLights(), makeCamera());
|
|
65
|
+
const moduleCall = fake.calls.find((c) => c.name === 'createShaderModule');
|
|
66
|
+
const code = (moduleCall!.args[0] as { code: string }).code;
|
|
67
|
+
expect(code).toContain('const SHEEN : bool = true;');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
71
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
72
|
+
const proxy = makeProxy();
|
|
73
|
+
sheenPbrWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
74
|
+
sheenPbrWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
75
|
+
|
|
76
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
77
|
+
expect(drawCall).toBeDefined();
|
|
78
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
79
|
+
expect(drawCall!.args[2]).toBe(proxy.subset.indexOffset);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
83
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
84
|
+
sheenPbrWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
85
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createSpecularGlossinessPbrMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { SpecularGlossinessPbrMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
registerSpecularGlossinessPbrWgpuMaterial,
|
|
10
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer,
|
|
11
|
+
} from './specularGlossinessPbrWgpuMeshMaterialRenderer';
|
|
12
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
13
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
14
|
+
|
|
15
|
+
function makeCamera(): Camera3D {
|
|
16
|
+
return createCamera3D({ far: 100, near: 0.1, projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' } });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function makeLights(): Scene3DLightBlock {
|
|
20
|
+
const data = new Float32Array(12);
|
|
21
|
+
data[1] = -1;
|
|
22
|
+
data[4] = 1;
|
|
23
|
+
data[5] = 1;
|
|
24
|
+
data[6] = 1;
|
|
25
|
+
data[8] = 0.1;
|
|
26
|
+
data[9] = 0.1;
|
|
27
|
+
data[10] = 0.1;
|
|
28
|
+
return { ambientCount: 1, data, directionalCount: 1, hemisphereCount: 0, pointCount: 0, spotCount: 0, version: 1 };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
32
|
+
const geometry = createBoxMeshGeometry();
|
|
33
|
+
return {
|
|
34
|
+
material: createSpecularGlossinessPbrMaterial({ glossiness: 0.7 }),
|
|
35
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
36
|
+
subset: geometry.subsets[0],
|
|
37
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('registerSpecularGlossinessPbrWgpuMaterial', () => {
|
|
42
|
+
it('installs the renderer for SpecularGlossinessPbrMaterialKind', () => {
|
|
43
|
+
const { state } = makeWgpuScene3DState();
|
|
44
|
+
registerSpecularGlossinessPbrWgpuMaterial(state);
|
|
45
|
+
expect(getWgpuMeshMaterialRenderer(state, SpecularGlossinessPbrMaterialKind)).toBe(
|
|
46
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer,
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('specularGlossinessPbrWgpuMeshMaterialRenderer', () => {
|
|
52
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
53
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
54
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer.bind(
|
|
55
|
+
state,
|
|
56
|
+
createSpecularGlossinessPbrMaterial(),
|
|
57
|
+
makeLights(),
|
|
58
|
+
makeCamera(),
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
62
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
63
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
64
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('drives the base PBR program with no extension flag (CPU spec-gloss conversion)', () => {
|
|
68
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
69
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer.bind(
|
|
70
|
+
state,
|
|
71
|
+
createSpecularGlossinessPbrMaterial(),
|
|
72
|
+
makeLights(),
|
|
73
|
+
makeCamera(),
|
|
74
|
+
);
|
|
75
|
+
const moduleCall = fake.calls.find((c) => c.name === 'createShaderModule');
|
|
76
|
+
const code = (moduleCall!.args[0] as { code: string }).code;
|
|
77
|
+
expect(code).toContain('const CLEARCOAT : bool = false;');
|
|
78
|
+
expect(code).toContain('const SHEEN : bool = false;');
|
|
79
|
+
expect(code).toContain('const SPECULAR_EXT : bool = false;');
|
|
80
|
+
expect(code).toContain('const TRANSMISSION : bool = false;');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
84
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
85
|
+
const proxy = makeProxy();
|
|
86
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
87
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
88
|
+
|
|
89
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
90
|
+
expect(drawCall).toBeDefined();
|
|
91
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
92
|
+
expect(drawCall!.args[2]).toBe(proxy.subset.indexOffset);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
96
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
97
|
+
specularGlossinessPbrWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
98
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createSpecularPbrMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { SpecularPbrMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
registerSpecularPbrWgpuMaterial,
|
|
10
|
+
specularPbrWgpuMeshMaterialRenderer,
|
|
11
|
+
} from './specularPbrWgpuMeshMaterialRenderer';
|
|
12
|
+
import { getWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
|
|
13
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
14
|
+
|
|
15
|
+
function makeCamera(): Camera3D {
|
|
16
|
+
return createCamera3D({ far: 100, near: 0.1, projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' } });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function makeLights(): Scene3DLightBlock {
|
|
20
|
+
const data = new Float32Array(12);
|
|
21
|
+
data[1] = -1;
|
|
22
|
+
data[4] = 1;
|
|
23
|
+
data[5] = 1;
|
|
24
|
+
data[6] = 1;
|
|
25
|
+
data[8] = 0.1;
|
|
26
|
+
data[9] = 0.1;
|
|
27
|
+
data[10] = 0.1;
|
|
28
|
+
return { ambientCount: 1, data, directionalCount: 1, hemisphereCount: 0, pointCount: 0, spotCount: 0, version: 1 };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
32
|
+
const geometry = createBoxMeshGeometry();
|
|
33
|
+
return {
|
|
34
|
+
material: createSpecularPbrMaterial({ specular: 0.5 }),
|
|
35
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
36
|
+
subset: geometry.subsets[0],
|
|
37
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('registerSpecularPbrWgpuMaterial', () => {
|
|
42
|
+
it('installs the renderer for SpecularPbrMaterialKind', () => {
|
|
43
|
+
const { state } = makeWgpuScene3DState();
|
|
44
|
+
registerSpecularPbrWgpuMaterial(state);
|
|
45
|
+
expect(getWgpuMeshMaterialRenderer(state, SpecularPbrMaterialKind)).toBe(specularPbrWgpuMeshMaterialRenderer);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('specularPbrWgpuMeshMaterialRenderer', () => {
|
|
50
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
51
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
52
|
+
specularPbrWgpuMeshMaterialRenderer.bind(
|
|
53
|
+
state,
|
|
54
|
+
createSpecularPbrMaterial({ specular: 0.5 }),
|
|
55
|
+
makeLights(),
|
|
56
|
+
makeCamera(),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
60
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
61
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
62
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('bind compiles the SPECULAR_EXT extension variant', () => {
|
|
66
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
67
|
+
specularPbrWgpuMeshMaterialRenderer.bind(state, createSpecularPbrMaterial(), makeLights(), makeCamera());
|
|
68
|
+
const moduleCall = fake.calls.find((c) => c.name === 'createShaderModule');
|
|
69
|
+
const code = (moduleCall!.args[0] as { code: string }).code;
|
|
70
|
+
expect(code).toContain('const SPECULAR_EXT : bool = true;');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
74
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
75
|
+
const proxy = makeProxy();
|
|
76
|
+
specularPbrWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
77
|
+
specularPbrWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
78
|
+
|
|
79
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
80
|
+
expect(drawCall).toBeDefined();
|
|
81
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
82
|
+
expect(drawCall!.args[2]).toBe(proxy.subset.indexOffset);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
86
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
87
|
+
specularPbrWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
88
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
});
|