@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,172 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createStandardPbrMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy, Texture } from '@flighthq/types';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
buildWgpuPbrStandardDefineKey,
|
|
9
|
+
ensureWgpuPbrMaterialBindGroup,
|
|
10
|
+
getWgpuPbrMaterialScratch,
|
|
11
|
+
standardPbrWgpuMeshMaterialRenderer,
|
|
12
|
+
WGPU_PBR_MATERIAL_UNIFORM_FLOATS,
|
|
13
|
+
writeWgpuPbrMaterialUniform,
|
|
14
|
+
writeWgpuPbrStandardBlock,
|
|
15
|
+
} from './standardPbrWgpuMeshMaterialRenderer';
|
|
16
|
+
import { ensureWgpuPbrPipeline } from './wgpuPbrPipelineCache';
|
|
17
|
+
import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
|
|
18
|
+
|
|
19
|
+
function makeCamera(): Camera3D {
|
|
20
|
+
return createCamera3D({ far: 100, near: 0.1, projection: { aspect: 1, fovY: Math.PI / 3, kind: 'perspective' } });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function makeLights(): Scene3DLightBlock {
|
|
24
|
+
const data = new Float32Array(12);
|
|
25
|
+
data[0] = 0;
|
|
26
|
+
data[1] = -1;
|
|
27
|
+
data[2] = 0;
|
|
28
|
+
data[4] = 1;
|
|
29
|
+
data[5] = 1;
|
|
30
|
+
data[6] = 1;
|
|
31
|
+
data[8] = 0.1;
|
|
32
|
+
data[9] = 0.1;
|
|
33
|
+
data[10] = 0.1;
|
|
34
|
+
return { ambientCount: 1, data, directionalCount: 1, hemisphereCount: 0, pointCount: 0, spotCount: 0, version: 1 };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
38
|
+
const geometry = createBoxMeshGeometry();
|
|
39
|
+
return {
|
|
40
|
+
material: createStandardPbrMaterial(),
|
|
41
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
42
|
+
subset: geometry.subsets[0],
|
|
43
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe('buildWgpuPbrStandardDefineKey', () => {
|
|
48
|
+
it('reads the alpha mode + double-sidedness and leaves every extension flag off', () => {
|
|
49
|
+
const material = createStandardPbrMaterial();
|
|
50
|
+
material.alphaMode = 'mask';
|
|
51
|
+
material.doubleSided = true;
|
|
52
|
+
const key = buildWgpuPbrStandardDefineKey(material, material);
|
|
53
|
+
expect(key.alphaMaskEnabled).toBe(true);
|
|
54
|
+
expect(key.doubleSided).toBe(true);
|
|
55
|
+
expect(key.clearcoatEnabled).toBe(false);
|
|
56
|
+
expect(key.transmissionEnabled).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('returns all-false flags for a null surface', () => {
|
|
60
|
+
const key = buildWgpuPbrStandardDefineKey(null, null);
|
|
61
|
+
expect(key.alphaMaskEnabled).toBe(false);
|
|
62
|
+
expect(key.hasBaseColorMap).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('derives the five standard map flags from the material maps that carry an image source', () => {
|
|
66
|
+
const material = createStandardPbrMaterial();
|
|
67
|
+
// A texture is "present" only when it carries a GPU-uploadable image source; a structural stub of
|
|
68
|
+
// exactly that shape is enough to exercise the flag derivation without a real GPU texture upload.
|
|
69
|
+
const sourced = { image: { source: {} } } as unknown as Texture;
|
|
70
|
+
material.baseColorMap = sourced;
|
|
71
|
+
material.metallicRoughnessMap = sourced;
|
|
72
|
+
const key = buildWgpuPbrStandardDefineKey(material, material);
|
|
73
|
+
expect(key.hasBaseColorMap).toBe(true);
|
|
74
|
+
expect(key.hasMetallicRoughnessMap).toBe(true);
|
|
75
|
+
expect(key.hasNormalMap).toBe(false);
|
|
76
|
+
expect(key.hasOcclusionMap).toBe(false);
|
|
77
|
+
expect(key.hasEmissiveMap).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('ensureWgpuPbrMaterialBindGroup', () => {
|
|
82
|
+
it('creates a material bind group once per key and reuses it', () => {
|
|
83
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
84
|
+
const pipeline = ensureWgpuPbrPipeline(state, buildWgpuPbrStandardDefineKey(null, null), 'bgra8unorm');
|
|
85
|
+
const cacheKey = {};
|
|
86
|
+
const a = ensureWgpuPbrMaterialBindGroup(state, pipeline, cacheKey, null);
|
|
87
|
+
const groups = fake.calls.filter((c) => c.name === 'createBindGroup').length;
|
|
88
|
+
const b = ensureWgpuPbrMaterialBindGroup(state, pipeline, cacheKey, null);
|
|
89
|
+
expect(b).toBe(a);
|
|
90
|
+
expect(fake.calls.filter((c) => c.name === 'createBindGroup').length).toBe(groups);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('getWgpuPbrMaterialScratch', () => {
|
|
95
|
+
it('returns the shared 48-float MaterialBlock scratch', () => {
|
|
96
|
+
expect(getWgpuPbrMaterialScratch().length).toBe(WGPU_PBR_MATERIAL_UNIFORM_FLOATS);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('standardPbrWgpuMeshMaterialRenderer', () => {
|
|
101
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
102
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
103
|
+
standardPbrWgpuMeshMaterialRenderer.bind(state, createStandardPbrMaterial(), makeLights(), makeCamera());
|
|
104
|
+
|
|
105
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
106
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
107
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
108
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('bind compiles a cull-none pipeline for a double-sided material', () => {
|
|
112
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
113
|
+
const material = createStandardPbrMaterial();
|
|
114
|
+
material.doubleSided = true;
|
|
115
|
+
standardPbrWgpuMeshMaterialRenderer.bind(state, material, makeLights(), makeCamera());
|
|
116
|
+
const pipelineCall = fake.calls.find((c) => c.name === 'createRenderPipeline');
|
|
117
|
+
const descriptor = pipelineCall!.args[0] as { primitive: { cullMode: string } };
|
|
118
|
+
expect(descriptor.primitive.cullMode).toBe('none');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
122
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
123
|
+
const proxy = makeProxy();
|
|
124
|
+
const geometry = createBoxMeshGeometry();
|
|
125
|
+
standardPbrWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
126
|
+
standardPbrWgpuMeshMaterialRenderer.draw(state, proxy, geometry);
|
|
127
|
+
|
|
128
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
129
|
+
expect(drawCall).toBeDefined();
|
|
130
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
131
|
+
expect(drawCall!.args[2]).toBe(proxy.subset.indexOffset);
|
|
132
|
+
expect(fake.calls.some((c) => c.name === 'setIndexBuffer')).toBe(true);
|
|
133
|
+
expect(fake.calls.some((c) => c.name === 'setVertexBuffer')).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
137
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
138
|
+
standardPbrWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
139
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('WGPU_PBR_MATERIAL_UNIFORM_FLOATS', () => {
|
|
144
|
+
it('is the 48-float (192-byte) MaterialBlock size', () => {
|
|
145
|
+
expect(WGPU_PBR_MATERIAL_UNIFORM_FLOATS).toBe(48);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('writeWgpuPbrMaterialUniform', () => {
|
|
150
|
+
it('writes the scratch into the binding buffer', () => {
|
|
151
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
152
|
+
const pipeline = ensureWgpuPbrPipeline(state, buildWgpuPbrStandardDefineKey(null, null), 'bgra8unorm');
|
|
153
|
+
const binding = ensureWgpuPbrMaterialBindGroup(state, pipeline, {}, null);
|
|
154
|
+
const writes = fake.calls.filter((c) => c.name === 'writeBuffer').length;
|
|
155
|
+
writeWgpuPbrMaterialUniform(state, binding);
|
|
156
|
+
expect(fake.calls.filter((c) => c.name === 'writeBuffer').length).toBe(writes + 1);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('writeWgpuPbrStandardBlock', () => {
|
|
161
|
+
it('packs the base color + alpha cutoff, and uses neutral defaults for a null block', () => {
|
|
162
|
+
const out = new Float32Array(WGPU_PBR_MATERIAL_UNIFORM_FLOATS);
|
|
163
|
+
writeWgpuPbrStandardBlock(out, createStandardPbrMaterial({ baseColor: 0xff0000ff }), 0.25);
|
|
164
|
+
expect(out[0]).toBeGreaterThan(0.9); // red channel ~1 in linear
|
|
165
|
+
expect(out[12]).toBe(0.25); // alphaCutoff
|
|
166
|
+
|
|
167
|
+
const neutral = new Float32Array(WGPU_PBR_MATERIAL_UNIFORM_FLOATS);
|
|
168
|
+
writeWgpuPbrStandardBlock(neutral, null, 0.5);
|
|
169
|
+
expect(neutral[0]).toBe(1);
|
|
170
|
+
expect(neutral[9]).toBe(1); // roughness default
|
|
171
|
+
});
|
|
172
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createSubsurfacePbrMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { SubsurfacePbrMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
registerSubsurfacePbrWgpuMaterial,
|
|
10
|
+
subsurfacePbrWgpuMeshMaterialRenderer,
|
|
11
|
+
} from './subsurfacePbrWgpuMeshMaterialRenderer';
|
|
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: createSubsurfacePbrMaterial({ subsurface: 0.8 }),
|
|
35
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
36
|
+
subset: geometry.subsets[0],
|
|
37
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('registerSubsurfacePbrWgpuMaterial', () => {
|
|
42
|
+
it('installs the renderer for SubsurfacePbrMaterialKind', () => {
|
|
43
|
+
const { state } = makeWgpuScene3DState();
|
|
44
|
+
registerSubsurfacePbrWgpuMaterial(state);
|
|
45
|
+
expect(getWgpuMeshMaterialRenderer(state, SubsurfacePbrMaterialKind)).toBe(subsurfacePbrWgpuMeshMaterialRenderer);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('subsurfacePbrWgpuMeshMaterialRenderer', () => {
|
|
50
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
51
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
52
|
+
subsurfacePbrWgpuMeshMaterialRenderer.bind(
|
|
53
|
+
state,
|
|
54
|
+
createSubsurfacePbrMaterial({ subsurface: 0.8 }),
|
|
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 SUBSURFACE extension variant', () => {
|
|
66
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
67
|
+
subsurfacePbrWgpuMeshMaterialRenderer.bind(state, createSubsurfacePbrMaterial(), 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 SUBSURFACE : 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
|
+
subsurfacePbrWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
77
|
+
subsurfacePbrWgpuMeshMaterialRenderer.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
|
+
subsurfacePbrWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
88
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createToonMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { ToonMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import { registerToonWgpuMaterial, toonWgpuMeshMaterialRenderer } from './toonWgpuMeshMaterialRenderer';
|
|
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: createToonMaterial(),
|
|
34
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
35
|
+
subset: geometry.subsets[0],
|
|
36
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe('registerToonWgpuMaterial', () => {
|
|
41
|
+
it('installs the toon renderer for ToonMaterialKind', () => {
|
|
42
|
+
const { state } = makeWgpuScene3DState();
|
|
43
|
+
registerToonWgpuMaterial(state);
|
|
44
|
+
expect(getWgpuMeshMaterialRenderer(state, ToonMaterialKind)).toBe(toonWgpuMeshMaterialRenderer);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('toonWgpuMeshMaterialRenderer', () => {
|
|
49
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
50
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
51
|
+
toonWgpuMeshMaterialRenderer.bind(state, createToonMaterial(), makeLights(), makeCamera());
|
|
52
|
+
|
|
53
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
54
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
55
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
56
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('bind compiles a cull-none pipeline for a double-sided material', () => {
|
|
60
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
61
|
+
const material = createToonMaterial();
|
|
62
|
+
material.doubleSided = true;
|
|
63
|
+
toonWgpuMeshMaterialRenderer.bind(state, material, makeLights(), makeCamera());
|
|
64
|
+
const pipelineCall = fake.calls.find((c) => c.name === 'createRenderPipeline');
|
|
65
|
+
const descriptor = pipelineCall!.args[0] as { primitive: { cullMode: string } };
|
|
66
|
+
expect(descriptor.primitive.cullMode).toBe('none');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
70
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
71
|
+
const proxy = makeProxy();
|
|
72
|
+
const geometry = createBoxMeshGeometry();
|
|
73
|
+
toonWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
74
|
+
toonWgpuMeshMaterialRenderer.draw(state, proxy, geometry);
|
|
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
|
+
expect(fake.calls.some((c) => c.name === 'setIndexBuffer')).toBe(true);
|
|
81
|
+
expect(fake.calls.some((c) => c.name === 'setVertexBuffer')).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
85
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
86
|
+
toonWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
87
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createTransmissionVolumePbrMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Matrix3, Matrix4, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { TransmissionVolumePbrMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
registerTransmissionVolumePbrWgpuMaterial,
|
|
10
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer,
|
|
11
|
+
} from './transmissionVolumePbrWgpuMeshMaterialRenderer';
|
|
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: createTransmissionVolumePbrMaterial({ transmission: 0.9 }),
|
|
35
|
+
normalMatrix: createMatrix3() as Matrix3,
|
|
36
|
+
subset: geometry.subsets[0],
|
|
37
|
+
worldMatrix: createMatrix4() as Matrix4,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('registerTransmissionVolumePbrWgpuMaterial', () => {
|
|
42
|
+
it('installs the renderer for TransmissionVolumePbrMaterialKind', () => {
|
|
43
|
+
const { state } = makeWgpuScene3DState();
|
|
44
|
+
registerTransmissionVolumePbrWgpuMaterial(state);
|
|
45
|
+
expect(getWgpuMeshMaterialRenderer(state, TransmissionVolumePbrMaterialKind)).toBe(
|
|
46
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer,
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('transmissionVolumePbrWgpuMeshMaterialRenderer', () => {
|
|
52
|
+
it('bind selects a pipeline and binds frame + material groups + uploads uniforms', () => {
|
|
53
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
54
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer.bind(
|
|
55
|
+
state,
|
|
56
|
+
createTransmissionVolumePbrMaterial({ transmission: 0.9 }),
|
|
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('bind compiles the TRANSMISSION extension variant', () => {
|
|
68
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
69
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer.bind(
|
|
70
|
+
state,
|
|
71
|
+
createTransmissionVolumePbrMaterial(),
|
|
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 TRANSMISSION : bool = true;');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('draw uploads geometry and issues an indexed draw over the subset range', () => {
|
|
81
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
82
|
+
const proxy = makeProxy();
|
|
83
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer.bind(state, proxy.material, makeLights(), makeCamera());
|
|
84
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
85
|
+
|
|
86
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
87
|
+
expect(drawCall).toBeDefined();
|
|
88
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
89
|
+
expect(drawCall!.args[2]).toBe(proxy.subset.indexOffset);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
93
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
94
|
+
transmissionVolumePbrWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
95
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createUnlitMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Scene3DLightBlock, Scene3DRenderProxy, VideoTexture } from '@flighthq/types';
|
|
6
|
+
import { UnlitMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import { registerUnlitWgpuMaterial, unlitWgpuMeshMaterialRenderer } from './unlitWgpuMeshMaterialRenderer';
|
|
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: createUnlitMaterial(),
|
|
30
|
+
normalMatrix: createMatrix3(),
|
|
31
|
+
subset: geometry.subsets[0],
|
|
32
|
+
worldMatrix: createMatrix4(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('registerUnlitWgpuMaterial', () => {
|
|
37
|
+
it('installs the renderer for UnlitMaterialKind', () => {
|
|
38
|
+
const { state } = makeWgpuScene3DState();
|
|
39
|
+
registerUnlitWgpuMaterial(state);
|
|
40
|
+
expect(getWgpuMeshMaterialRenderer(state, UnlitMaterialKind)).toBe(unlitWgpuMeshMaterialRenderer);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('unlitWgpuMeshMaterialRenderer', () => {
|
|
45
|
+
it('bind selects a pipeline and binds the frame + material groups', () => {
|
|
46
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
47
|
+
unlitWgpuMeshMaterialRenderer.bind(state, createUnlitMaterial(), NO_LIGHTS, makeCamera());
|
|
48
|
+
expect(fake.calls.some((c) => c.name === 'createRenderPipeline')).toBe(true);
|
|
49
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
50
|
+
expect(fake.calls.filter((c) => c.name === 'setBindGroup').length).toBeGreaterThanOrEqual(2);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('uploads a ready dynamic video map into the color-map slot', () => {
|
|
54
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
55
|
+
const material = createUnlitMaterial();
|
|
56
|
+
material.baseColorVideoMap = {
|
|
57
|
+
frameId: 1,
|
|
58
|
+
sampler: {
|
|
59
|
+
anisotropy: 1,
|
|
60
|
+
magFilter: 'linear',
|
|
61
|
+
minFilter: 'linear',
|
|
62
|
+
mipmaps: false,
|
|
63
|
+
wrapU: 'clamp-to-edge',
|
|
64
|
+
wrapV: 'clamp-to-edge',
|
|
65
|
+
},
|
|
66
|
+
source: {
|
|
67
|
+
element: { readyState: 4, videoHeight: 120, videoWidth: 160 } as HTMLVideoElement,
|
|
68
|
+
},
|
|
69
|
+
flipX: false,
|
|
70
|
+
flipY: false,
|
|
71
|
+
uvOffset: { x: 0, y: 0 },
|
|
72
|
+
uvRotation: 0,
|
|
73
|
+
uvScale: { x: 1, y: 1 },
|
|
74
|
+
} as unknown as VideoTexture;
|
|
75
|
+
unlitWgpuMeshMaterialRenderer.bind(state, material, NO_LIGHTS, makeCamera());
|
|
76
|
+
expect(fake.calls.some((c) => c.name === 'copyExternalImageToTexture')).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('draw issues an indexed draw over the subset after bind', () => {
|
|
80
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
81
|
+
const proxy = makeProxy();
|
|
82
|
+
unlitWgpuMeshMaterialRenderer.bind(state, proxy.material, NO_LIGHTS, makeCamera());
|
|
83
|
+
unlitWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
84
|
+
const drawCall = fake.calls.find((c) => c.name === 'drawIndexed');
|
|
85
|
+
expect(drawCall).toBeDefined();
|
|
86
|
+
expect(drawCall!.args[0]).toBe(proxy.subset.indexCount);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('draw is a no-op when bind has not selected a pipeline', () => {
|
|
90
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
91
|
+
unlitWgpuMeshMaterialRenderer.draw(state, makeProxy(), createBoxMeshGeometry());
|
|
92
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createCamera3D } from '@flighthq/camera';
|
|
2
|
+
import { createMatrix3, createMatrix4 } from '@flighthq/geometry';
|
|
3
|
+
import { createVertexColorMaterial } from '@flighthq/materials';
|
|
4
|
+
import { createBoxMeshGeometry } from '@flighthq/mesh';
|
|
5
|
+
import type { Camera3D, Scene3DLightBlock, Scene3DRenderProxy } from '@flighthq/types';
|
|
6
|
+
import { VertexColorMaterialKind } from '@flighthq/types';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
registerVertexColorWgpuMaterial,
|
|
10
|
+
vertexColorWgpuMeshMaterialRenderer,
|
|
11
|
+
} from './vertexColorWgpuMeshMaterialRenderer';
|
|
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
|
+
const NO_LIGHTS: Scene3DLightBlock = {
|
|
20
|
+
ambientCount: 0,
|
|
21
|
+
data: new Float32Array(12),
|
|
22
|
+
directionalCount: 0,
|
|
23
|
+
hemisphereCount: 0,
|
|
24
|
+
pointCount: 0,
|
|
25
|
+
spotCount: 0,
|
|
26
|
+
version: 1,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function makeProxy(): Scene3DRenderProxy {
|
|
30
|
+
const geometry = createBoxMeshGeometry();
|
|
31
|
+
return {
|
|
32
|
+
material: createVertexColorMaterial(),
|
|
33
|
+
normalMatrix: createMatrix3(),
|
|
34
|
+
subset: geometry.subsets[0],
|
|
35
|
+
worldMatrix: createMatrix4(),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('registerVertexColorWgpuMaterial', () => {
|
|
40
|
+
it('installs the renderer for VertexColorMaterialKind', () => {
|
|
41
|
+
const { state } = makeWgpuScene3DState();
|
|
42
|
+
registerVertexColorWgpuMaterial(state);
|
|
43
|
+
expect(getWgpuMeshMaterialRenderer(state, VertexColorMaterialKind)).toBe(vertexColorWgpuMeshMaterialRenderer);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('vertexColorWgpuMeshMaterialRenderer', () => {
|
|
48
|
+
it('bind selects a pipeline and uploads the tint', () => {
|
|
49
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
50
|
+
vertexColorWgpuMeshMaterialRenderer.bind(state, createVertexColorMaterial(), NO_LIGHTS, makeCamera());
|
|
51
|
+
expect(fake.calls.some((c) => c.name === 'setPipeline')).toBe(true);
|
|
52
|
+
expect(fake.calls.some((c) => c.name === 'writeBuffer')).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('draw issues an indexed draw over the subset after bind', () => {
|
|
56
|
+
const { fake, state } = makeWgpuScene3DState();
|
|
57
|
+
const proxy = makeProxy();
|
|
58
|
+
vertexColorWgpuMeshMaterialRenderer.bind(state, proxy.material, NO_LIGHTS, makeCamera());
|
|
59
|
+
vertexColorWgpuMeshMaterialRenderer.draw(state, proxy, createBoxMeshGeometry());
|
|
60
|
+
expect(fake.calls.some((c) => c.name === 'drawIndexed')).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
});
|