@babylonjs/lite 1.11.0 → 1.12.0
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/CHANGELOG.md +22 -0
- package/dist/index.js +444 -368
- package/dist/index.js.map +1 -1
- package/index.d.ts +191 -4
- package/lib/audio/index.js +1 -0
- package/lib/audio/index.js.map +1 -1
- package/lib/audio/media-stream-output.js +44 -0
- package/lib/audio/media-stream-output.js.map +1 -0
- package/lib/engine/engine.js +1 -1
- package/lib/frame-graph/render-task.js +1 -1
- package/lib/frame-graph/render-task.js.map +1 -1
- package/lib/frame-graph/shadow-inputs.js +10 -1
- package/lib/frame-graph/shadow-inputs.js.map +1 -1
- package/lib/frame-graph/transmission.js +1 -16
- package/lib/frame-graph/transmission.js.map +1 -1
- package/lib/index.js +5 -3
- package/lib/index.js.map +1 -1
- package/lib/loader-gltf/gltf-json-asset.js +1 -1
- package/lib/loader-gltf/gltf-json-asset.js.map +1 -1
- package/lib/loader-gltf/gltf-multi-buffer.js +2 -10
- package/lib/loader-gltf/gltf-multi-buffer.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder-ext.js +4 -18
- package/lib/loader-gltf/gltf-pbr-builder-ext.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder.js +17 -14
- package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
- package/lib/loader-gltf/gltf-sampler-desc.js +3 -16
- package/lib/loader-gltf/gltf-sampler-desc.js.map +1 -1
- package/lib/material/node/blocks/ambient-occlusion-block.js +1 -4
- package/lib/material/node/blocks/ambient-occlusion-block.js.map +1 -1
- package/lib/material/node/blocks/biplanar-block.js +3 -6
- package/lib/material/node/blocks/biplanar-block.js.map +1 -1
- package/lib/material/node/blocks/image-source.js +2 -5
- package/lib/material/node/blocks/image-source.js.map +1 -1
- package/lib/material/node/blocks/input-block.js +5 -26
- package/lib/material/node/blocks/input-block.js.map +1 -1
- package/lib/material/node/blocks/pbr-mr-helper-full.js +5 -8
- package/lib/material/node/blocks/pbr-mr-helper-full.js.map +1 -1
- package/lib/material/node/blocks/reflection-texture-block.js +1 -4
- package/lib/material/node/blocks/reflection-texture-block.js.map +1 -1
- package/lib/material/node/blocks/texture-block.js +2 -5
- package/lib/material/node/blocks/texture-block.js.map +1 -1
- package/lib/material/node/blocks/triplanar-block.js +3 -6
- package/lib/material/node/blocks/triplanar-block.js.map +1 -1
- package/lib/material/node/node-emitter.js +24 -1
- package/lib/material/node/node-emitter.js.map +1 -1
- package/lib/material/node/node-geometry-renderable.js +2 -2
- package/lib/material/node/node-material.js +1 -22
- package/lib/material/node/node-material.js.map +1 -1
- package/lib/material/node/node-types.js.map +1 -1
- package/lib/material/pbr/fragments/shadow-only-fragment.js +68 -0
- package/lib/material/pbr/fragments/shadow-only-fragment.js.map +1 -0
- package/lib/material/pbr/pbr-flag-bits.js.map +1 -1
- package/lib/material/pbr/pbr-material.js.map +1 -1
- package/lib/material/pbr/pbr-renderable.js +3 -0
- package/lib/material/pbr/pbr-renderable.js.map +1 -1
- package/lib/material/pbr/pbr-template.js +1 -0
- package/lib/material/pbr/pbr-template.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-mesh.js +2 -8
- package/lib/mesh/GaussianSplatting/gaussian-splatting-mesh.js.map +1 -1
- package/lib/mesh/mesh-dispose.js +2 -0
- package/lib/mesh/mesh-dispose.js.map +1 -1
- package/lib/mesh/mesh.js +2 -8
- package/lib/mesh/mesh.js.map +1 -1
- package/lib/mesh/thin-instance-cull-binding.js +54 -3
- package/lib/mesh/thin-instance-cull-binding.js.map +1 -1
- package/lib/mesh/thin-instance-gpu-culling.js +241 -24
- package/lib/mesh/thin-instance-gpu-culling.js.map +1 -1
- package/lib/mesh/thin-instance.js +112 -1
- package/lib/mesh/thin-instance.js.map +1 -1
- package/lib/picking/gpu-picker.js +4 -2
- package/lib/picking/gpu-picker.js.map +1 -1
- package/lib/picking/picking-pipeline.js +1 -1
- package/lib/picking/picking-pipeline.js.map +1 -1
- package/lib/picking/picking-shader.js +38 -16
- package/lib/picking/picking-shader.js.map +1 -1
- package/lib/scene/scene-core.js +3 -0
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/scene/scene-node.js +2 -6
- package/lib/scene/scene-node.js.map +1 -1
- package/lib/scene/transform-node.js +3 -0
- package/lib/scene/transform-node.js.map +1 -1
- package/lib/scene/world-matrix-state.js +7 -1
- package/lib/scene/world-matrix-state.js.map +1 -1
- package/lib/shadow/csm-directional-shadow-generator.js +22 -1
- package/lib/shadow/csm-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/csm-shadow-task-hooks.js +19 -11
- package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
- package/lib/shadow/esm-directional-shadow-generator.js +2 -51
- package/lib/shadow/esm-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/pcf-directional-shadow-generator.js +2 -48
- package/lib/shadow/pcf-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/shadow-base.js +48 -1
- package/lib/shadow/shadow-base.js.map +1 -1
- package/lib/text/text-renderable.js +2 -10
- package/lib/text/text-renderable.js.map +1 -1
- package/lib/texture/texture-array.js +96 -0
- package/lib/texture/texture-array.js.map +1 -0
- package/package.json +3 -3
|
@@ -33,6 +33,20 @@ function uploadTex(engine, bitmap, srgb, sampler, generateMipmaps, fallback) {
|
|
|
33
33
|
engine._dlr?.b(result, bitmap, srgb, !!bitmap, fallback);
|
|
34
34
|
return result;
|
|
35
35
|
}
|
|
36
|
+
function uploadBaseColorFactorTexture(engine, factor, sampler, generateMipmaps) {
|
|
37
|
+
return uploadTex(
|
|
38
|
+
engine,
|
|
39
|
+
null,
|
|
40
|
+
true,
|
|
41
|
+
sampler,
|
|
42
|
+
generateMipmaps,
|
|
43
|
+
new U8([linearToSrgbByte(factor[0]), linearToSrgbByte(factor[1]), linearToSrgbByte(factor[2]), Math.round(Math.max(0, Math.min(1, factor[3])) * 255)])
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
function uploadOrmFactorTexture(engine, roughness, metallic, sampler, generateMipmaps) {
|
|
47
|
+
const clamp = (value) => Math.round(Math.max(0, Math.min(1, value)) * 255);
|
|
48
|
+
return uploadTex(engine, null, false, sampler, generateMipmaps, new U8([255, clamp(roughness), clamp(metallic), 255]));
|
|
49
|
+
}
|
|
36
50
|
function assemblePbrProps(mat, baseColorTexture, ormTexture, normalTexture, emissiveTexture, extLayers) {
|
|
37
51
|
const ef = mat._emissiveFactor;
|
|
38
52
|
const defaultFactor = ef[0] === 0 && ef[1] === 0 && ef[2] === 0 || !!emissiveTexture && ef[0] === 1 && ef[1] === 1 && ef[2] === 1;
|
|
@@ -60,17 +74,7 @@ function isDefaultBaseColorFactor(f) {
|
|
|
60
74
|
return f[0] === 1 && f[1] === 1 && f[2] === 1 && f[3] === 1;
|
|
61
75
|
}
|
|
62
76
|
function buildDefaultPbrTextures(engine, mat, sampler, generateMipmaps, getCachedTex) {
|
|
63
|
-
const baseColorTexture = mat._baseColorImage ? getCachedTex(mat._baseColorImage, true) : (
|
|
64
|
-
const f = mat._baseColorFactor;
|
|
65
|
-
return uploadTex(
|
|
66
|
-
engine,
|
|
67
|
-
null,
|
|
68
|
-
true,
|
|
69
|
-
sampler,
|
|
70
|
-
generateMipmaps,
|
|
71
|
-
new U8([linearToSrgbByte(f[0]), linearToSrgbByte(f[1]), linearToSrgbByte(f[2]), Math.round(Math.max(0, Math.min(1, f[3])) * 255)])
|
|
72
|
-
);
|
|
73
|
-
})();
|
|
77
|
+
const baseColorTexture = mat._baseColorImage ? getCachedTex(mat._baseColorImage, true) : uploadBaseColorFactorTexture(engine, mat._baseColorFactor, sampler, generateMipmaps);
|
|
74
78
|
const normalTexture = mat._normalImage ? getCachedTex(mat._normalImage, false) : void 0;
|
|
75
79
|
const emissiveTexture = mat._emissiveImage ? getCachedTex(mat._emissiveImage, true) : void 0;
|
|
76
80
|
const single = mat._metallicRoughnessImage ?? mat._occlusionImage;
|
|
@@ -78,13 +82,12 @@ function buildDefaultPbrTextures(engine, mat, sampler, generateMipmaps, getCache
|
|
|
78
82
|
if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {
|
|
79
83
|
ormTexture = getCachedTex(single, false);
|
|
80
84
|
} else if (!single) {
|
|
81
|
-
|
|
82
|
-
ormTexture = uploadTex(engine, null, false, sampler, generateMipmaps, new U8([255, clamp(mat._roughnessFactor), clamp(mat._metallicFactor), 255]));
|
|
85
|
+
ormTexture = uploadOrmFactorTexture(engine, mat._roughnessFactor, mat._metallicFactor, sampler, generateMipmaps);
|
|
83
86
|
} else {
|
|
84
87
|
ormTexture = getCachedTex(mat._metallicRoughnessImage, false);
|
|
85
88
|
}
|
|
86
89
|
return { baseColorTexture, ormTexture, normalTexture, emissiveTexture };
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
export { assemblePbrProps, buildDefaultPbrTextures, identityTexWrap, uploadTex };
|
|
92
|
+
export { assemblePbrProps, buildDefaultPbrTextures, identityTexWrap, uploadBaseColorFactorTexture, uploadOrmFactorTexture, uploadTex };
|
|
90
93
|
//# sourceMappingURL=gltf-pbr-builder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gltf-pbr-builder.js","sources":["../../../src/loader-gltf/gltf-pbr-builder.ts"],"sourcesContent":["/** Shared PBR-material assembly + texture upload + ext-layer merging.\n * Used by both the core loader (`load-gltf.ts`) and the variants loader\n * (`gltf-variants.ts`) so they can't drift. */\n\nimport { U8 } from \"../engine/typed-arrays.js\";\nimport { TU } from \"../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { PbrMaterialProps } from \"../material/pbr/pbr-material.js\";\nimport { getPbrGroupBuilder } from \"../material/pbr/pbr-material.js\";\nimport type { GltfMaterialData } from \"./gltf-material.js\";\nimport { mipLevelCount } from \"../texture/mip-count.js\";\nimport { linearToSrgbByte } from \"../math/color.js\";\n\n/** Texture post-processor composed from every active feature's `wrapTexture`\n * hook. Identity when no feature contributes one (common case). Kept simple\n * so the core loader stays feature-agnostic and tree-shakes cleanly. */\nexport type TextureWrapFn = (tex: Texture2D, texInfo: unknown) => Texture2D;\nexport const identityTexWrap: TextureWrapFn = (tex) => tex;\n\nexport type GenerateMipmapsFn = (engine: EngineContext, texture: GPUTexture, face?: number) => void;\n\nexport function uploadTex(\n engine: EngineContext,\n bitmap: ImageBitmap | null,\n srgb: boolean,\n sampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n fallback?: Uint8Array\n): Texture2D {\n const device = engine._device;\n const w = bitmap?.width ?? 1;\n const h = bitmap?.height ?? 1;\n const fmt: GPUTextureFormat = srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n const mips = bitmap ? mipLevelCount(w, h) : 1;\n const tex = device.createTexture({\n size: { width: w, height: h },\n format: fmt,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.COPY_SRC | TU.RENDER_ATTACHMENT,\n mipLevelCount: mips,\n });\n if (bitmap) {\n device.queue.copyExternalImageToTexture({ source: bitmap }, { texture: tex, premultipliedAlpha: false }, { width: w, height: h });\n generateMipmaps(engine, tex);\n } else {\n device.queue.writeTexture({ texture: tex }, (fallback ?? new U8([255, 255, 255, 255])) as Uint8Array<ArrayBuffer>, { bytesPerRow: 4 }, { width: 1, height: 1 });\n }\n const result: Texture2D = {\n texture: tex,\n view: tex.createView(),\n sampler,\n width: w,\n height: h,\n };\n engine._dlr?.b(result, bitmap, srgb, !!bitmap, fallback);\n return result;\n}\n\n/** Assemble a PbrMaterialProps from parsed glTF material data + already-uploaded\n * textures + per-ext fragment overrides. Fast-path: no wrapTex, no occlusionOnUv2,\n * no occlusionTexture. Slow-path additions live in gltf-pbr-builder-ext.ts. */\nexport function assemblePbrProps(\n mat: GltfMaterialData,\n baseColorTexture: Texture2D,\n ormTexture: Texture2D,\n normalTexture: Texture2D | undefined,\n emissiveTexture: Texture2D | undefined,\n extLayers: Partial<PbrMaterialProps> | undefined\n): PbrMaterialProps {\n const ef = mat._emissiveFactor;\n // emissiveFactor multiplies the emissive texture, so [1,1,1] is a no-op WHEN a texture is\n // present. With no emissive texture, [1,1,1] is a real full-white emissive that must be applied\n // (the glTF default is [0,0,0]) — otherwise the surface renders unlit/dark (Material_03).\n const defaultFactor = (ef[0] === 0 && ef[1] === 0 && ef[2] === 0) || (!!emissiveTexture && ef[0] === 1 && ef[1] === 1 && ef[2] === 1);\n return {\n baseColorTexture,\n normalTexture,\n ormTexture,\n emissiveTexture,\n ...(mat._baseColorImage && !isDefaultBaseColorFactor(mat._baseColorFactor) ? { baseColorFactor: mat._baseColorFactor } : undefined),\n doubleSided: mat._doubleSided,\n occlusionStrength: mat._occlusionImage ? 1.0 : 0,\n ...(mat._normalScale !== 1 ? { normalTextureScale: mat._normalScale } : undefined),\n ...(mat._metallicRoughnessImage ? { metallicFactor: mat._metallicFactor, roughnessFactor: mat._roughnessFactor } : undefined),\n ...(!defaultFactor ? { emissiveColor: [ef[0], ef[1], ef[2]] as [number, number, number] } : undefined),\n enableSpecularAA: true,\n ...(mat._alphaMode === \"BLEND\" ? { alphaBlend: true, alpha: mat._baseColorFactor[3] } : undefined),\n ...(mat._alphaMode === \"MASK\" ? { alpha: mat._baseColorFactor[3], alphaCutOff: mat._alphaCutoff } : undefined),\n ...(mat._rawMatDef?.name ? { name: mat._rawMatDef.name as string } : undefined),\n ...extLayers,\n _buildGroup: getPbrGroupBuilder(),\n _uboVersion: 0,\n } as PbrMaterialProps;\n}\n\nfunction isDefaultBaseColorFactor(f: readonly number[]): boolean {\n return f[0] === 1 && f[1] === 1 && f[2] === 1 && f[3] === 1;\n}\n\n/** Build the always-present default textures (base color + ORM) from a parsed glTF material.\n * Fast-path version: no wrapTex, no occlusion-on-uv2 handling. The slow path lives\n * in gltf-pbr-builder-ext.ts and is lazy-loaded only when needed. */\nexport function buildDefaultPbrTextures(\n engine: EngineContext,\n mat: GltfMaterialData,\n sampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n getCachedTex: (bitmap: ImageBitmap, srgb: boolean) => Texture2D\n): { baseColorTexture: Texture2D; ormTexture: Texture2D; normalTexture: Texture2D | undefined; emissiveTexture: Texture2D | undefined } {\n const baseColorTexture = mat._baseColorImage\n ? getCachedTex(mat._baseColorImage, true)\n : (() => {\n const f = mat._baseColorFactor;\n return uploadTex(\n engine,\n null,\n true,\n sampler,\n generateMipmaps,\n new U8([linearToSrgbByte(f[0]), linearToSrgbByte(f[1]), linearToSrgbByte(f[2]), Math.round(Math.max(0, Math.min(1, f[3])) * 255)])\n );\n })();\n const normalTexture = mat._normalImage ? getCachedTex(mat._normalImage, false) : undefined;\n const emissiveTexture = mat._emissiveImage ? getCachedTex(mat._emissiveImage, true) : undefined;\n\n const single = mat._metallicRoughnessImage ?? mat._occlusionImage;\n let ormTexture: Texture2D;\n if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {\n ormTexture = getCachedTex(single, false);\n } else if (!single) {\n const clamp = (v: number) => Math.round(Math.max(0, Math.min(1, v)) * 255);\n ormTexture = uploadTex(engine, null, false, sampler, generateMipmaps, new U8([255, clamp(mat._roughnessFactor), clamp(mat._metallicFactor), 255]));\n } else {\n ormTexture = getCachedTex(mat._metallicRoughnessImage!, false);\n }\n return { baseColorTexture, ormTexture, normalTexture, emissiveTexture };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gltf-pbr-builder.js","sources":["../../../src/loader-gltf/gltf-pbr-builder.ts"],"sourcesContent":["/** Shared PBR-material assembly + texture upload + ext-layer merging.\n * Used by both the core loader (`load-gltf.ts`) and the variants loader\n * (`gltf-variants.ts`) so they can't drift. */\n\nimport { U8 } from \"../engine/typed-arrays.js\";\nimport { TU } from \"../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { PbrMaterialProps } from \"../material/pbr/pbr-material.js\";\nimport { getPbrGroupBuilder } from \"../material/pbr/pbr-material.js\";\nimport type { GltfMaterialData } from \"./gltf-material.js\";\nimport { mipLevelCount } from \"../texture/mip-count.js\";\nimport { linearToSrgbByte } from \"../math/color.js\";\n\n/** Texture post-processor composed from every active feature's `wrapTexture`\n * hook. Identity when no feature contributes one (common case). Kept simple\n * so the core loader stays feature-agnostic and tree-shakes cleanly. */\nexport type TextureWrapFn = (tex: Texture2D, texInfo: unknown) => Texture2D;\nexport const identityTexWrap: TextureWrapFn = (tex) => tex;\n\nexport type GenerateMipmapsFn = (engine: EngineContext, texture: GPUTexture, face?: number) => void;\n\nexport function uploadTex(\n engine: EngineContext,\n bitmap: ImageBitmap | null,\n srgb: boolean,\n sampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n fallback?: Uint8Array\n): Texture2D {\n const device = engine._device;\n const w = bitmap?.width ?? 1;\n const h = bitmap?.height ?? 1;\n const fmt: GPUTextureFormat = srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n const mips = bitmap ? mipLevelCount(w, h) : 1;\n const tex = device.createTexture({\n size: { width: w, height: h },\n format: fmt,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.COPY_SRC | TU.RENDER_ATTACHMENT,\n mipLevelCount: mips,\n });\n if (bitmap) {\n device.queue.copyExternalImageToTexture({ source: bitmap }, { texture: tex, premultipliedAlpha: false }, { width: w, height: h });\n generateMipmaps(engine, tex);\n } else {\n device.queue.writeTexture({ texture: tex }, (fallback ?? new U8([255, 255, 255, 255])) as Uint8Array<ArrayBuffer>, { bytesPerRow: 4 }, { width: 1, height: 1 });\n }\n const result: Texture2D = {\n texture: tex,\n view: tex.createView(),\n sampler,\n width: w,\n height: h,\n };\n engine._dlr?.b(result, bitmap, srgb, !!bitmap, fallback);\n return result;\n}\n\nexport function uploadBaseColorFactorTexture(engine: EngineContext, factor: readonly number[], sampler: GPUSampler, generateMipmaps: GenerateMipmapsFn): Texture2D {\n return uploadTex(\n engine,\n null,\n true,\n sampler,\n generateMipmaps,\n new U8([linearToSrgbByte(factor[0]!), linearToSrgbByte(factor[1]!), linearToSrgbByte(factor[2]!), Math.round(Math.max(0, Math.min(1, factor[3]!)) * 255)])\n );\n}\n\nexport function uploadOrmFactorTexture(engine: EngineContext, roughness: number, metallic: number, sampler: GPUSampler, generateMipmaps: GenerateMipmapsFn): Texture2D {\n const clamp = (value: number): number => Math.round(Math.max(0, Math.min(1, value)) * 255);\n return uploadTex(engine, null, false, sampler, generateMipmaps, new U8([255, clamp(roughness), clamp(metallic), 255]));\n}\n\n/** Assemble a PbrMaterialProps from parsed glTF material data + already-uploaded\n * textures + per-ext fragment overrides. Fast-path: no wrapTex, no occlusionOnUv2,\n * no occlusionTexture. Slow-path additions live in gltf-pbr-builder-ext.ts. */\nexport function assemblePbrProps(\n mat: GltfMaterialData,\n baseColorTexture: Texture2D,\n ormTexture: Texture2D,\n normalTexture: Texture2D | undefined,\n emissiveTexture: Texture2D | undefined,\n extLayers: Partial<PbrMaterialProps> | undefined\n): PbrMaterialProps {\n const ef = mat._emissiveFactor;\n // emissiveFactor multiplies the emissive texture, so [1,1,1] is a no-op WHEN a texture is\n // present. With no emissive texture, [1,1,1] is a real full-white emissive that must be applied\n // (the glTF default is [0,0,0]) — otherwise the surface renders unlit/dark (Material_03).\n const defaultFactor = (ef[0] === 0 && ef[1] === 0 && ef[2] === 0) || (!!emissiveTexture && ef[0] === 1 && ef[1] === 1 && ef[2] === 1);\n return {\n baseColorTexture,\n normalTexture,\n ormTexture,\n emissiveTexture,\n ...(mat._baseColorImage && !isDefaultBaseColorFactor(mat._baseColorFactor) ? { baseColorFactor: mat._baseColorFactor } : undefined),\n doubleSided: mat._doubleSided,\n occlusionStrength: mat._occlusionImage ? 1.0 : 0,\n ...(mat._normalScale !== 1 ? { normalTextureScale: mat._normalScale } : undefined),\n ...(mat._metallicRoughnessImage ? { metallicFactor: mat._metallicFactor, roughnessFactor: mat._roughnessFactor } : undefined),\n ...(!defaultFactor ? { emissiveColor: [ef[0], ef[1], ef[2]] as [number, number, number] } : undefined),\n enableSpecularAA: true,\n ...(mat._alphaMode === \"BLEND\" ? { alphaBlend: true, alpha: mat._baseColorFactor[3] } : undefined),\n ...(mat._alphaMode === \"MASK\" ? { alpha: mat._baseColorFactor[3], alphaCutOff: mat._alphaCutoff } : undefined),\n ...(mat._rawMatDef?.name ? { name: mat._rawMatDef.name as string } : undefined),\n ...extLayers,\n _buildGroup: getPbrGroupBuilder(),\n _uboVersion: 0,\n } as PbrMaterialProps;\n}\n\nfunction isDefaultBaseColorFactor(f: readonly number[]): boolean {\n return f[0] === 1 && f[1] === 1 && f[2] === 1 && f[3] === 1;\n}\n\n/** Build the always-present default textures (base color + ORM) from a parsed glTF material.\n * Fast-path version: no wrapTex, no occlusion-on-uv2 handling. The slow path lives\n * in gltf-pbr-builder-ext.ts and is lazy-loaded only when needed. */\nexport function buildDefaultPbrTextures(\n engine: EngineContext,\n mat: GltfMaterialData,\n sampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n getCachedTex: (bitmap: ImageBitmap, srgb: boolean) => Texture2D\n): { baseColorTexture: Texture2D; ormTexture: Texture2D; normalTexture: Texture2D | undefined; emissiveTexture: Texture2D | undefined } {\n const baseColorTexture = mat._baseColorImage ? getCachedTex(mat._baseColorImage, true) : uploadBaseColorFactorTexture(engine, mat._baseColorFactor, sampler, generateMipmaps);\n const normalTexture = mat._normalImage ? getCachedTex(mat._normalImage, false) : undefined;\n const emissiveTexture = mat._emissiveImage ? getCachedTex(mat._emissiveImage, true) : undefined;\n\n const single = mat._metallicRoughnessImage ?? mat._occlusionImage;\n let ormTexture: Texture2D;\n if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {\n ormTexture = getCachedTex(single, false);\n } else if (!single) {\n ormTexture = uploadOrmFactorTexture(engine, mat._roughnessFactor, mat._metallicFactor, sampler, generateMipmaps);\n } else {\n ormTexture = getCachedTex(mat._metallicRoughnessImage!, false);\n }\n return { baseColorTexture, ormTexture, normalTexture, emissiveTexture };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { getOrCreateSampler } from '../resource/gpu-pool.js';
|
|
2
|
-
import {
|
|
3
|
-
import { linearToSrgbByte } from '../math/color.js';
|
|
4
|
-
import { uploadTex } from './gltf-pbr-builder.js';
|
|
2
|
+
import { uploadBaseColorFactorTexture, uploadOrmFactorTexture } from './gltf-pbr-builder.js';
|
|
5
3
|
|
|
6
4
|
function gltfTexSamplerDesc(json, texInfo) {
|
|
7
5
|
const s = json.textures?.[texInfo.index]?.sampler != null ? json.samplers?.[json.textures[texInfo.index].sampler] : void 0;
|
|
@@ -41,17 +39,7 @@ function buildSampledPbrTextures(engine, mat, defaultSampler, generateMipmaps, s
|
|
|
41
39
|
const tex = getCachedTex(bitmap, srgb);
|
|
42
40
|
return s === defaultSampler ? tex : { ...tex, sampler: s };
|
|
43
41
|
};
|
|
44
|
-
const baseColorTexture = mat._baseColorImage ? cached(mat._baseColorImage, true, pbr.baseColorTexture) : (
|
|
45
|
-
const f = mat._baseColorFactor;
|
|
46
|
-
return uploadTex(
|
|
47
|
-
engine,
|
|
48
|
-
null,
|
|
49
|
-
true,
|
|
50
|
-
defaultSampler,
|
|
51
|
-
generateMipmaps,
|
|
52
|
-
new U8([linearToSrgbByte(f[0]), linearToSrgbByte(f[1]), linearToSrgbByte(f[2]), Math.round(Math.max(0, Math.min(1, f[3])) * 255)])
|
|
53
|
-
);
|
|
54
|
-
})();
|
|
42
|
+
const baseColorTexture = mat._baseColorImage ? cached(mat._baseColorImage, true, pbr.baseColorTexture) : uploadBaseColorFactorTexture(engine, mat._baseColorFactor, defaultSampler, generateMipmaps);
|
|
55
43
|
const normalTexture = mat._normalImage ? cached(mat._normalImage, false, def.normalTexture) : void 0;
|
|
56
44
|
const emissiveTexture = mat._emissiveImage ? cached(mat._emissiveImage, true, def.emissiveTexture) : void 0;
|
|
57
45
|
const single = mat._metallicRoughnessImage ?? mat._occlusionImage;
|
|
@@ -60,8 +48,7 @@ function buildSampledPbrTextures(engine, mat, defaultSampler, generateMipmaps, s
|
|
|
60
48
|
if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {
|
|
61
49
|
ormTexture = cached(single, false, ormTexInfo);
|
|
62
50
|
} else if (!single) {
|
|
63
|
-
|
|
64
|
-
ormTexture = uploadTex(engine, null, false, defaultSampler, generateMipmaps, new U8([255, clamp(mat._roughnessFactor), clamp(mat._metallicFactor), 255]));
|
|
51
|
+
ormTexture = uploadOrmFactorTexture(engine, mat._roughnessFactor, mat._metallicFactor, defaultSampler, generateMipmaps);
|
|
65
52
|
} else {
|
|
66
53
|
ormTexture = cached(mat._metallicRoughnessImage, false, pbr.metallicRoughnessTexture);
|
|
67
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gltf-sampler-desc.js","sources":["../../../src/loader-gltf/gltf-sampler-desc.ts"],"sourcesContent":["import { getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport { U8 } from \"../engine/typed-arrays.js\";\nimport { linearToSrgbByte } from \"../math/color.js\";\nimport { uploadTex } from \"./gltf-pbr-builder.js\";\nimport type { GenerateMipmapsFn } from \"./gltf-pbr-builder.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { GltfMaterialData } from \"./gltf-material.js\";\n\n/** Map a glTF textureInfo's sampler (wrapS/wrapT/magFilter/minFilter) to a WebGPU sampler\n * descriptor. glTF wrap: 33071 CLAMP_TO_EDGE, 33648 MIRRORED_REPEAT, else REPEAT.\n * glTF filter: 9728 NEAREST else LINEAR; min/mip from the combined min filter enum. */\nfunction gltfTexSamplerDesc(json: any, texInfo: any): GPUSamplerDescriptor {\n const s = json.textures?.[texInfo.index]?.sampler != null ? json.samplers?.[json.textures[texInfo.index].sampler] : undefined;\n const wrap = (m: number | undefined): GPUAddressMode => (m === 33071 ? \"clamp-to-edge\" : m === 33648 ? \"mirror-repeat\" : \"repeat\");\n const minF: number | undefined = s?.minFilter;\n const minNearest = minF === 9728 || minF === 9984 || minF === 9986;\n const mipNearest = minF === 9984 || minF === 9985;\n // glTF non-mipmap min filters (9728 NEAREST, 9729 LINEAR) mean \"sample mip 0 only\".\n // The shared uploaded GPU texture always carries a full mip chain, so clamp the LOD\n // to 0 for these filters (matching BJS `noMipmap`); otherwise a minified texture\n // (e.g. small SDF text in a top-down view) would sample blurred mips and render\n // softer/darker than BJS. Mipmapped filters (9984–9987) leave LOD unclamped.\n const noMip = minF === 9728 || minF === 9729;\n const magLinear = s?.magFilter !== 9728;\n return {\n magFilter: magLinear ? \"linear\" : \"nearest\",\n minFilter: minNearest ? \"nearest\" : \"linear\",\n mipmapFilter: mipNearest ? \"nearest\" : \"linear\",\n addressModeU: wrap(s?.wrapS),\n addressModeV: wrap(s?.wrapT),\n ...(noMip ? { lodMaxClamp: 0 } : undefined),\n // WebGPU forbids anisotropy unless mag/min/mip filters are ALL linear; gate on\n // every filter (incl. mipNearest, e.g. glTF LINEAR_MIPMAP_NEAREST) or createSampler throws.\n // Also disable it for the clamped-mip path (single LOD → anisotropy is meaningless).\n maxAnisotropy: magLinear && !minNearest && !mipNearest && !noMip ? 4 : 1,\n };\n}\n\n/** Build a per-texture sampler resolver honoring each texture's glTF sampler\n * (wrap/filter). Loaded lazily only when an asset declares a non-default sampler;\n * the common case (default repeat/linear) uses one shared sampler and never loads this.\n * `texInfo == null` (factor textures) falls back to `defaultSampler`.\n * @internal */\nexport function makeSamplerFor(engine: EngineContext, json: any, defaultSampler: GPUSampler): (texInfo: any) => GPUSampler {\n return (texInfo: any): GPUSampler => {\n if (texInfo == null) {\n return defaultSampler;\n }\n const desc = gltfTexSamplerDesc(json, texInfo);\n // A non-mipmap sampler (lodMaxClamp 0) is created directly: the shared cache key omits\n // the LOD clamp, so caching it there could alias a full-mip sampler with identical\n // filter/wrap. These are rare (SDF/UI textures), so per-call creation is cheaper than\n // growing the universal sampler key — which would move every non-glTF scene's bundle.\n return desc.lodMaxClamp === 0 ? engine._device.createSampler(desc) : getOrCreateSampler(engine, desc);\n };\n}\n\n/** Sampler-aware variant of buildDefaultPbrTextures. Mirrors the core fast path but wraps\n * each shared GPU texture with the sampler resolved from its glTF textureInfo (wrap/filter),\n * so clamp/mirror/nearest assets render correctly without re-uploading identical images.\n * Lazy-loaded only for non-default-sampler assets — the common path stays byte-identical.\n * @internal */\nexport function buildSampledPbrTextures(\n engine: EngineContext,\n mat: GltfMaterialData,\n defaultSampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n samplerFor: (texInfo: any) => GPUSampler,\n getCachedTex: (bitmap: ImageBitmap, srgb: boolean) => Texture2D\n): { baseColorTexture: Texture2D; ormTexture: Texture2D; normalTexture: Texture2D | undefined; emissiveTexture: Texture2D | undefined } {\n const def = mat._rawMatDef ?? {};\n const pbr = def.pbrMetallicRoughness ?? {};\n const cached = (bitmap: ImageBitmap, srgb: boolean, texInfo: any): Texture2D => {\n const s = samplerFor(texInfo);\n const tex = getCachedTex(bitmap, srgb);\n return s === defaultSampler ? tex : { ...tex, sampler: s };\n };\n\n const baseColorTexture = mat._baseColorImage\n ? cached(mat._baseColorImage, true, pbr.baseColorTexture)\n : (() => {\n const f = mat._baseColorFactor;\n return uploadTex(\n engine,\n null,\n true,\n defaultSampler,\n generateMipmaps,\n new U8([linearToSrgbByte(f[0]), linearToSrgbByte(f[1]), linearToSrgbByte(f[2]), Math.round(Math.max(0, Math.min(1, f[3])) * 255)])\n );\n })();\n const normalTexture = mat._normalImage ? cached(mat._normalImage, false, def.normalTexture) : undefined;\n const emissiveTexture = mat._emissiveImage ? cached(mat._emissiveImage, true, def.emissiveTexture) : undefined;\n\n const single = mat._metallicRoughnessImage ?? mat._occlusionImage;\n const ormTexInfo = mat._metallicRoughnessImage ? pbr.metallicRoughnessTexture : def.occlusionTexture;\n let ormTexture: Texture2D;\n if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {\n ormTexture = cached(single, false, ormTexInfo);\n } else if (!single) {\n const clamp = (v: number) => Math.round(Math.max(0, Math.min(1, v)) * 255);\n ormTexture = uploadTex(engine, null, false, defaultSampler, generateMipmaps, new U8([255, clamp(mat._roughnessFactor), clamp(mat._metallicFactor), 255]));\n } else {\n ormTexture = cached(mat._metallicRoughnessImage!, false, pbr.metallicRoughnessTexture);\n }\n return { baseColorTexture, ormTexture, normalTexture, emissiveTexture };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gltf-sampler-desc.js","sources":["../../../src/loader-gltf/gltf-sampler-desc.ts"],"sourcesContent":["import { getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport { uploadBaseColorFactorTexture, uploadOrmFactorTexture } from \"./gltf-pbr-builder.js\";\nimport type { GenerateMipmapsFn } from \"./gltf-pbr-builder.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { GltfMaterialData } from \"./gltf-material.js\";\n\n/** Map a glTF textureInfo's sampler (wrapS/wrapT/magFilter/minFilter) to a WebGPU sampler\n * descriptor. glTF wrap: 33071 CLAMP_TO_EDGE, 33648 MIRRORED_REPEAT, else REPEAT.\n * glTF filter: 9728 NEAREST else LINEAR; min/mip from the combined min filter enum. */\nfunction gltfTexSamplerDesc(json: any, texInfo: any): GPUSamplerDescriptor {\n const s = json.textures?.[texInfo.index]?.sampler != null ? json.samplers?.[json.textures[texInfo.index].sampler] : undefined;\n const wrap = (m: number | undefined): GPUAddressMode => (m === 33071 ? \"clamp-to-edge\" : m === 33648 ? \"mirror-repeat\" : \"repeat\");\n const minF: number | undefined = s?.minFilter;\n const minNearest = minF === 9728 || minF === 9984 || minF === 9986;\n const mipNearest = minF === 9984 || minF === 9985;\n // glTF non-mipmap min filters (9728 NEAREST, 9729 LINEAR) mean \"sample mip 0 only\".\n // The shared uploaded GPU texture always carries a full mip chain, so clamp the LOD\n // to 0 for these filters (matching BJS `noMipmap`); otherwise a minified texture\n // (e.g. small SDF text in a top-down view) would sample blurred mips and render\n // softer/darker than BJS. Mipmapped filters (9984–9987) leave LOD unclamped.\n const noMip = minF === 9728 || minF === 9729;\n const magLinear = s?.magFilter !== 9728;\n return {\n magFilter: magLinear ? \"linear\" : \"nearest\",\n minFilter: minNearest ? \"nearest\" : \"linear\",\n mipmapFilter: mipNearest ? \"nearest\" : \"linear\",\n addressModeU: wrap(s?.wrapS),\n addressModeV: wrap(s?.wrapT),\n ...(noMip ? { lodMaxClamp: 0 } : undefined),\n // WebGPU forbids anisotropy unless mag/min/mip filters are ALL linear; gate on\n // every filter (incl. mipNearest, e.g. glTF LINEAR_MIPMAP_NEAREST) or createSampler throws.\n // Also disable it for the clamped-mip path (single LOD → anisotropy is meaningless).\n maxAnisotropy: magLinear && !minNearest && !mipNearest && !noMip ? 4 : 1,\n };\n}\n\n/** Build a per-texture sampler resolver honoring each texture's glTF sampler\n * (wrap/filter). Loaded lazily only when an asset declares a non-default sampler;\n * the common case (default repeat/linear) uses one shared sampler and never loads this.\n * `texInfo == null` (factor textures) falls back to `defaultSampler`.\n * @internal */\nexport function makeSamplerFor(engine: EngineContext, json: any, defaultSampler: GPUSampler): (texInfo: any) => GPUSampler {\n return (texInfo: any): GPUSampler => {\n if (texInfo == null) {\n return defaultSampler;\n }\n const desc = gltfTexSamplerDesc(json, texInfo);\n // A non-mipmap sampler (lodMaxClamp 0) is created directly: the shared cache key omits\n // the LOD clamp, so caching it there could alias a full-mip sampler with identical\n // filter/wrap. These are rare (SDF/UI textures), so per-call creation is cheaper than\n // growing the universal sampler key — which would move every non-glTF scene's bundle.\n return desc.lodMaxClamp === 0 ? engine._device.createSampler(desc) : getOrCreateSampler(engine, desc);\n };\n}\n\n/** Sampler-aware variant of buildDefaultPbrTextures. Mirrors the core fast path but wraps\n * each shared GPU texture with the sampler resolved from its glTF textureInfo (wrap/filter),\n * so clamp/mirror/nearest assets render correctly without re-uploading identical images.\n * Lazy-loaded only for non-default-sampler assets — the common path stays byte-identical.\n * @internal */\nexport function buildSampledPbrTextures(\n engine: EngineContext,\n mat: GltfMaterialData,\n defaultSampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n samplerFor: (texInfo: any) => GPUSampler,\n getCachedTex: (bitmap: ImageBitmap, srgb: boolean) => Texture2D\n): { baseColorTexture: Texture2D; ormTexture: Texture2D; normalTexture: Texture2D | undefined; emissiveTexture: Texture2D | undefined } {\n const def = mat._rawMatDef ?? {};\n const pbr = def.pbrMetallicRoughness ?? {};\n const cached = (bitmap: ImageBitmap, srgb: boolean, texInfo: any): Texture2D => {\n const s = samplerFor(texInfo);\n const tex = getCachedTex(bitmap, srgb);\n return s === defaultSampler ? tex : { ...tex, sampler: s };\n };\n\n const baseColorTexture = mat._baseColorImage\n ? cached(mat._baseColorImage, true, pbr.baseColorTexture)\n : uploadBaseColorFactorTexture(engine, mat._baseColorFactor, defaultSampler, generateMipmaps);\n const normalTexture = mat._normalImage ? cached(mat._normalImage, false, def.normalTexture) : undefined;\n const emissiveTexture = mat._emissiveImage ? cached(mat._emissiveImage, true, def.emissiveTexture) : undefined;\n\n const single = mat._metallicRoughnessImage ?? mat._occlusionImage;\n const ormTexInfo = mat._metallicRoughnessImage ? pbr.metallicRoughnessTexture : def.occlusionTexture;\n let ormTexture: Texture2D;\n if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {\n ormTexture = cached(single, false, ormTexInfo);\n } else if (!single) {\n ormTexture = uploadOrmFactorTexture(engine, mat._roughnessFactor, mat._metallicFactor, defaultSampler, generateMipmaps);\n } else {\n ormTexture = cached(mat._metallicRoughnessImage!, false, pbr.metallicRoughnessTexture);\n }\n return { baseColorTexture, ormTexture, normalTexture, emissiveTexture };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -43,9 +43,6 @@ fn nme_computeAo(depthTex: texture_2d<f32>, depthSamp: sampler, fragCoord: vec4<
|
|
|
43
43
|
return clamp(1.0 - occlusion / 16.0, 0.0, 1.0);
|
|
44
44
|
}
|
|
45
45
|
`;
|
|
46
|
-
function sanitize(name) {
|
|
47
|
-
return name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
48
|
-
}
|
|
49
46
|
function num(value, fallback) {
|
|
50
47
|
return typeof value === "number" ? `${value}` : `${fallback}`;
|
|
51
48
|
}
|
|
@@ -58,7 +55,7 @@ const emitter = {
|
|
|
58
55
|
throw new Error(`NodeMaterial: AmbientOcclusionBlock "${block.name}" requires an ImageSourceBlock source`);
|
|
59
56
|
}
|
|
60
57
|
const producer = ctx.graph.blocks.get(source.blockId);
|
|
61
|
-
const bindingName = sanitize(producer?.name || `ao${block.id}`);
|
|
58
|
+
const bindingName = ctx.sanitize(producer?.name || `ao${block.id}`);
|
|
62
59
|
if (!state.textures.find((t) => t.name === bindingName)) {
|
|
63
60
|
state.textures.push({ name: bindingName, kind: "texture2d", texture: null });
|
|
64
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ambient-occlusion-block.js","sources":["../../../../../src/material/node/blocks/ambient-occlusion-block.ts"],"sourcesContent":["import type { BlockEmitter, NodeExpr } from \"../node-types.js\";\n\nconst HELPER_KEY = \"nme_ambientOcclusion\";\nconst HELPER_WGSL = `\nfn nme_aoNormalFromDepth(depthTex: texture_2d<f32>, depthSamp: sampler, depth: f32, coords: vec2<f32>, radius: f32) -> vec3<f32> {\n let offset1 = vec2<f32>(0.0, radius);\n let offset2 = vec2<f32>(radius, 0.0);\n let depth1 = textureSampleLevel(depthTex, depthSamp, coords + offset1, 0.0).r;\n let depth2 = textureSampleLevel(depthTex, depthSamp, coords + offset2, 0.0).r;\n let p1 = vec3<f32>(offset1, depth1 - depth);\n let p2 = vec3<f32>(offset2, depth2 - depth);\n var normal = cross(p1, p2);\n normal.z = -normal.z;\n return normalize(normal);\n}\n\nfn nme_aoRandom(uv: vec2<f32>) -> vec3<f32> {\n let x = fract(sin(dot(uv, vec2<f32>(12.9898, 78.233))) * 43758.5453);\n let y = fract(sin(dot(uv, vec2<f32>(39.3468, 11.135))) * 24634.6345);\n let z = fract(sin(dot(uv, vec2<f32>(73.156, 52.235))) * 12414.2347);\n return normalize(vec3<f32>(x, y, z));\n}\n\nfn nme_computeAo(depthTex: texture_2d<f32>, depthSamp: sampler, fragCoord: vec4<f32>, screenSize: vec2<f32>, radius: f32, area: f32, fallOff: f32) -> f32 {\n let uv = fragCoord.xy / screenSize;\n let random = nme_aoRandom(uv * 4.0);\n let depth = textureSampleLevel(depthTex, depthSamp, uv, 0.0).r;\n let position = vec3<f32>(uv, depth);\n let normal = nme_aoNormalFromDepth(depthTex, depthSamp, depth, uv, radius);\n let radiusDepth = radius / depth;\n let sampleSphere = array<vec3<f32>, 16>(\n vec3<f32>(0.5381, 0.1856, -0.4319), vec3<f32>(0.1379, 0.2486, 0.4430), vec3<f32>(0.3371, 0.5679, -0.0057), vec3<f32>(-0.6999, -0.0451, -0.0019),\n vec3<f32>(0.0689, -0.1598, -0.8547), vec3<f32>(0.0560, 0.0069, -0.1843), vec3<f32>(-0.0146, 0.1402, 0.0762), vec3<f32>(0.0100, -0.1924, -0.0344),\n vec3<f32>(-0.3577, -0.5301, -0.4358), vec3<f32>(-0.3169, 0.1063, 0.0158), vec3<f32>(0.0103, -0.5869, 0.0046), vec3<f32>(-0.0897, -0.4940, 0.3287),\n vec3<f32>(0.7119, -0.0154, -0.0918), vec3<f32>(-0.0533, 0.0596, -0.5411), vec3<f32>(0.0352, -0.0631, 0.5460), vec3<f32>(-0.4776, 0.2847, -0.0271)\n );\n var occlusion = 0.0;\n for (var i = 0; i < 16; i = i + 1) {\n let ray = radiusDepth * reflect(sampleSphere[i], random);\n let hemiRay = position + sign(dot(ray, normal)) * ray;\n let occlusionDepth = textureSample(depthTex, depthSamp, clamp(hemiRay.xy, vec2<f32>(0.001), vec2<f32>(0.999))).r;\n let difference = depth - occlusionDepth;\n occlusion += step(fallOff, difference) * (1.0 - smoothstep(fallOff, area, difference));\n }\n return clamp(1.0 - occlusion / 16.0, 0.0, 1.0);\n}\n`;\n\nfunction
|
|
1
|
+
{"version":3,"file":"ambient-occlusion-block.js","sources":["../../../../../src/material/node/blocks/ambient-occlusion-block.ts"],"sourcesContent":["import type { BlockEmitter, NodeExpr } from \"../node-types.js\";\n\nconst HELPER_KEY = \"nme_ambientOcclusion\";\nconst HELPER_WGSL = `\nfn nme_aoNormalFromDepth(depthTex: texture_2d<f32>, depthSamp: sampler, depth: f32, coords: vec2<f32>, radius: f32) -> vec3<f32> {\n let offset1 = vec2<f32>(0.0, radius);\n let offset2 = vec2<f32>(radius, 0.0);\n let depth1 = textureSampleLevel(depthTex, depthSamp, coords + offset1, 0.0).r;\n let depth2 = textureSampleLevel(depthTex, depthSamp, coords + offset2, 0.0).r;\n let p1 = vec3<f32>(offset1, depth1 - depth);\n let p2 = vec3<f32>(offset2, depth2 - depth);\n var normal = cross(p1, p2);\n normal.z = -normal.z;\n return normalize(normal);\n}\n\nfn nme_aoRandom(uv: vec2<f32>) -> vec3<f32> {\n let x = fract(sin(dot(uv, vec2<f32>(12.9898, 78.233))) * 43758.5453);\n let y = fract(sin(dot(uv, vec2<f32>(39.3468, 11.135))) * 24634.6345);\n let z = fract(sin(dot(uv, vec2<f32>(73.156, 52.235))) * 12414.2347);\n return normalize(vec3<f32>(x, y, z));\n}\n\nfn nme_computeAo(depthTex: texture_2d<f32>, depthSamp: sampler, fragCoord: vec4<f32>, screenSize: vec2<f32>, radius: f32, area: f32, fallOff: f32) -> f32 {\n let uv = fragCoord.xy / screenSize;\n let random = nme_aoRandom(uv * 4.0);\n let depth = textureSampleLevel(depthTex, depthSamp, uv, 0.0).r;\n let position = vec3<f32>(uv, depth);\n let normal = nme_aoNormalFromDepth(depthTex, depthSamp, depth, uv, radius);\n let radiusDepth = radius / depth;\n let sampleSphere = array<vec3<f32>, 16>(\n vec3<f32>(0.5381, 0.1856, -0.4319), vec3<f32>(0.1379, 0.2486, 0.4430), vec3<f32>(0.3371, 0.5679, -0.0057), vec3<f32>(-0.6999, -0.0451, -0.0019),\n vec3<f32>(0.0689, -0.1598, -0.8547), vec3<f32>(0.0560, 0.0069, -0.1843), vec3<f32>(-0.0146, 0.1402, 0.0762), vec3<f32>(0.0100, -0.1924, -0.0344),\n vec3<f32>(-0.3577, -0.5301, -0.4358), vec3<f32>(-0.3169, 0.1063, 0.0158), vec3<f32>(0.0103, -0.5869, 0.0046), vec3<f32>(-0.0897, -0.4940, 0.3287),\n vec3<f32>(0.7119, -0.0154, -0.0918), vec3<f32>(-0.0533, 0.0596, -0.5411), vec3<f32>(0.0352, -0.0631, 0.5460), vec3<f32>(-0.4776, 0.2847, -0.0271)\n );\n var occlusion = 0.0;\n for (var i = 0; i < 16; i = i + 1) {\n let ray = radiusDepth * reflect(sampleSphere[i], random);\n let hemiRay = position + sign(dot(ray, normal)) * ray;\n let occlusionDepth = textureSample(depthTex, depthSamp, clamp(hemiRay.xy, vec2<f32>(0.001), vec2<f32>(0.999))).r;\n let difference = depth - occlusionDepth;\n occlusion += step(fallOff, difference) * (1.0 - smoothstep(fallOff, area, difference));\n }\n return clamp(1.0 - occlusion / 16.0, 0.0, 1.0);\n}\n`;\n\nfunction num(value: unknown, fallback: number): string {\n return typeof value === \"number\" ? `${value}` : `${fallback}`;\n}\n\nexport const emitter: BlockEmitter = {\n className: \"AmbientOcclusionBlock\",\n stage: \"fragment\",\n emit(block, _outputName, stage, state, ctx): NodeExpr {\n const source = block.inputs.get(\"source\")?.source;\n if (!source) {\n throw new Error(`NodeMaterial: AmbientOcclusionBlock \"${block.name}\" requires an ImageSourceBlock source`);\n }\n const producer = ctx.graph.blocks.get(source.blockId);\n const bindingName = ctx.sanitize(producer?.name || `ao${block.id}`);\n if (!state.textures.find((t) => t.name === bindingName)) {\n state.textures.push({ name: bindingName, kind: \"texture2d\", texture: null });\n }\n state.fragment.helpers.set(HELPER_KEY, HELPER_WGSL);\n const screenSize = ctx.cast(ctx.resolve(block, \"screenSize\", stage, state), \"vec2f\").expr;\n return {\n expr: `nme_computeAo(nodeTex_${bindingName}, nodeSamp_${bindingName}, _NME_FRAG_COORD_, ${screenSize}, ${num(block.serialized.radius, 0.0001)}, ${num(block.serialized.area, 0.0075)}, ${num(block.serialized.fallOff, 0.000001)})`,\n type: \"f32\",\n };\n },\n};\n"],"names":[],"mappings":"AAEA,MAAM,UAAA,GAAa,sBAAA;AACnB,MAAM,WAAA,GAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA6CpB,SAAS,GAAA,CAAI,OAAgB,QAAA,EAA0B;AACnD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,GAAG,KAAK,CAAA,CAAA,GAAK,GAAG,QAAQ,CAAA,CAAA;AAC/D;AAEO,MAAM,OAAA,GAAwB;AAAA,EACjC,SAAA,EAAW,uBAAA;AAAA,EACX,KAAA,EAAO,UAAA;AAAA,EACP,IAAA,CAAK,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,OAAO,GAAA,EAAe;AAClD,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA,EAAG,MAAA;AAC3C,IAAA,IAAI,CAAC,MAAA,EAAQ;AACT,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,KAAA,CAAM,IAAI,CAAA,qCAAA,CAAuC,CAAA;AAAA,IAC7G;AACA,IAAA,MAAM,WAAW,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,OAAO,OAAO,CAAA;AACpD,IAAA,MAAM,WAAA,GAAc,IAAI,QAAA,CAAS,QAAA,EAAU,QAAQ,CAAA,EAAA,EAAK,KAAA,CAAM,EAAE,CAAA,CAAE,CAAA;AAClE,IAAA,IAAI,CAAC,MAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,WAAW,CAAA,EAAG;AACrD,MAAA,KAAA,CAAM,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,aAAa,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,IAAA,EAAM,CAAA;AAAA,IAC/E;AACA,IAAA,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,WAAW,CAAA;AAClD,IAAA,MAAM,UAAA,GAAa,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,KAAK,CAAA,EAAG,OAAO,CAAA,CAAE,IAAA;AACrF,IAAA,OAAO;AAAA,MACH,IAAA,EAAM,CAAA,sBAAA,EAAyB,WAAW,CAAA,WAAA,EAAc,WAAW,CAAA,oBAAA,EAAuB,UAAU,CAAA,EAAA,EAAK,GAAA,CAAI,KAAA,CAAM,UAAA,CAAW,MAAA,EAAQ,IAAM,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,KAAA,CAAM,UAAA,CAAW,IAAA,EAAM,KAAM,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,KAAA,CAAM,UAAA,CAAW,OAAA,EAAS,IAAQ,CAAC,CAAA,CAAA,CAAA;AAAA,MAChO,IAAA,EAAM;AAAA,KACV;AAAA,EACJ;AACJ;;;;"}
|
|
@@ -6,16 +6,13 @@ const OUTPUT = {
|
|
|
6
6
|
b: { swizzle: ".z", type: "f32" },
|
|
7
7
|
a: { swizzle: ".w", type: "f32" }
|
|
8
8
|
};
|
|
9
|
-
function sanitize(name) {
|
|
10
|
-
return name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
11
|
-
}
|
|
12
9
|
function bindingName(block, inputName, ctx, fallback) {
|
|
13
10
|
const input = block.inputs.get(inputName);
|
|
14
11
|
if (input?.source) {
|
|
15
12
|
const producer = ctx.graph.blocks.get(input.source.blockId);
|
|
16
|
-
return sanitize(producer?.name || fallback);
|
|
13
|
+
return ctx.sanitize(producer?.name || fallback);
|
|
17
14
|
}
|
|
18
|
-
return sanitize(fallback);
|
|
15
|
+
return ctx.sanitize(fallback);
|
|
19
16
|
}
|
|
20
17
|
function ensureBinding(state, name) {
|
|
21
18
|
if (!state.textures.find((t) => t.name === name)) {
|
|
@@ -48,7 +45,7 @@ function emitBiPlanarSample(block, stage, state, ctx) {
|
|
|
48
45
|
if (memo) {
|
|
49
46
|
return memo;
|
|
50
47
|
}
|
|
51
|
-
const baseName = sanitize(block.name || `biPlanar${block.id}`);
|
|
48
|
+
const baseName = ctx.sanitize(block.name || `biPlanar${block.id}`);
|
|
52
49
|
const texX = bindingName(block, "source", ctx, baseName);
|
|
53
50
|
const texY = bindingName(block, "sourceY", ctx, texX);
|
|
54
51
|
ensureBinding(state, texX);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"biplanar-block.js","sources":["../../../../../src/material/node/blocks/biplanar-block.ts"],"sourcesContent":["/** BiPlanarBlock — two-axis variant of triplanar texture projection.\n *\n * Uses the Babylon.js/Iñigo Quilez biplanar method: choose major/median axes\n * from abs(normal), sample those projections with explicit position\n * derivatives, and blend with the shaped two-component weights.\n */\n\nimport type { BlockEmitter, NodeBlock, NodeBuildState, NodeEmitContext, NodeExpr, NodeValueType, Stage } from \"../node-types.js\";\n\nconst OUTPUT: Record<string, { swizzle: string; type: NodeValueType }> = {\n rgba: { swizzle: \"\", type: \"vec4f\" },\n rgb: { swizzle: \".xyz\", type: \"vec3f\" },\n r: { swizzle: \".x\", type: \"f32\" },\n g: { swizzle: \".y\", type: \"f32\" },\n b: { swizzle: \".z\", type: \"f32\" },\n a: { swizzle: \".w\", type: \"f32\" },\n};\n\nfunction sanitize(name: string): string {\n return name.replace(/[^A-Za-z0-9_]/g, \"_\");\n}\n\nfunction bindingName(block: NodeBlock, inputName: string, ctx: NodeEmitContext, fallback: string): string {\n const input = block.inputs.get(inputName);\n if (input?.source) {\n const producer = ctx.graph.blocks.get(input.source.blockId);\n return sanitize(producer?.name || fallback);\n }\n return sanitize(fallback);\n}\n\nfunction ensureBinding(state: NodeBuildState, name: string): void {\n if (!state.textures.find((t) => t.name === name)) {\n state.textures.push({ name, kind: \"texture2d\", texture: null });\n }\n}\n\nfunction applyColorSpace(expr: string, outputName: string, convertToLinear: boolean, convertToGamma: boolean): string {\n if (!convertToLinear && !convertToGamma) {\n return expr;\n }\n const power = convertToLinear ? \"2.2\" : \"0.45454545\";\n if (outputName === \"rgba\") {\n return `vec4<f32>(pow(max(${expr}.xyz, vec3<f32>(0.0)), vec3<f32>(${power})), ${expr}.w)`;\n }\n if (outputName === \"rgb\") {\n return `pow(max(${expr}.xyz, vec3<f32>(0.0)), vec3<f32>(${power}))`;\n }\n if (outputName === \"r\" || outputName === \"g\" || outputName === \"b\") {\n return `pow(max(${expr}${OUTPUT[outputName]!.swizzle}, 0.0), ${power})`;\n }\n return expr;\n}\n\nfunction emitBiPlanarSample(block: NodeBlock, stage: Stage, state: NodeBuildState, ctx: NodeEmitContext): NodeExpr {\n if (stage !== \"fragment\") {\n throw new Error(\"BiPlanarBlock: texture projection is supported only in the fragment stage\");\n }\n\n const stageState = state.fragment;\n const memoKey = `_biplanar_${block.id}_sample`;\n const memo = stageState.memo.get(memoKey);\n if (memo) {\n return memo;\n }\n\n const baseName = sanitize(block.name || `biPlanar${block.id}`);\n const texX = bindingName(block, \"source\", ctx, baseName);\n const texY = bindingName(block, \"sourceY\", ctx, texX);\n ensureBinding(state, texX);\n ensureBinding(state, texY);\n\n const position = ctx.cast(ctx.resolve(block, \"position\", stage, state), \"vec3f\");\n const normal = ctx.cast(ctx.resolve(block, \"normal\", stage, state), \"vec3f\");\n const sharpness = block.inputs.get(\"sharpness\")?.source ? ctx.cast(ctx.resolve(block, \"sharpness\", stage, state), \"f32\").expr : \"1.0\";\n\n const temp = ctx.temp(state, \"bi\");\n const p = `_p${temp}`;\n const dx = `_dx${temp}`;\n const dy = `_dy${temp}`;\n const n = `_n${temp}`;\n const ma = `_ma${temp}`;\n const mi = `_mi${temp}`;\n const me = `_me${temp}`;\n const x = `_x${temp}`;\n const y = `_y${temp}`;\n const w = `_w${temp}`;\n const sample = `_sample${temp}`;\n\n stageState.body.push(`let ${p} = ${position.expr};`);\n stageState.body.push(`let ${dx} = dpdx(${p});`);\n stageState.body.push(`let ${dy} = dpdy(${p});`);\n stageState.body.push(`let ${n} = abs(${normal.expr});`);\n stageState.body.push(`var ${ma}: vec3<i32>;`);\n stageState.body.push(\n `if (${n}.x > ${n}.y && ${n}.x > ${n}.z) { ${ma} = vec3<i32>(0, 1, 2); } else if (${n}.y > ${n}.z) { ${ma} = vec3<i32>(1, 2, 0); } else { ${ma} = vec3<i32>(2, 0, 1); }`\n );\n stageState.body.push(`var ${mi}: vec3<i32>;`);\n stageState.body.push(\n `if (${n}.x < ${n}.y && ${n}.x < ${n}.z) { ${mi} = vec3<i32>(0, 1, 2); } else if (${n}.y < ${n}.z) { ${mi} = vec3<i32>(1, 2, 0); } else { ${mi} = vec3<i32>(2, 0, 1); }`\n );\n stageState.body.push(`let ${me} = vec3<i32>(3, 3, 3) - ${mi} - ${ma};`);\n stageState.body.push(\n `let ${x} = textureSampleGrad(nodeTex_${texX}, nodeSamp_${texX}, vec2<f32>(${p}[${ma}.y], ${p}[${ma}.z]), vec2<f32>(${dx}[${ma}.y], ${dx}[${ma}.z]), vec2<f32>(${dy}[${ma}.y], ${dy}[${ma}.z]));`\n );\n stageState.body.push(\n `let ${y} = textureSampleGrad(nodeTex_${texY}, nodeSamp_${texY}, vec2<f32>(${p}[${me}.y], ${p}[${me}.z]), vec2<f32>(${dx}[${me}.y], ${dx}[${me}.z]), vec2<f32>(${dy}[${me}.y], ${dy}[${me}.z]));`\n );\n stageState.body.push(`var ${w} = vec2<f32>(${n}[${ma}.x], ${n}[${me}.x]);`);\n stageState.body.push(`${w} = clamp((${w} - vec2<f32>(0.5773)) / vec2<f32>(1.0 - 0.5773), vec2<f32>(0.0), vec2<f32>(1.0));`);\n stageState.body.push(`${w} = pow(${w}, vec2<f32>(${sharpness} / 8.0));`);\n stageState.body.push(`let ${sample} = (${x} * ${w}.x + ${y} * ${w}.y) / (${w}.x + ${w}.y);`);\n\n const result = { expr: sample, type: \"vec4f\" } as const;\n stageState.memo.set(memoKey, result);\n return result;\n}\n\nexport const emitter: BlockEmitter = {\n className: \"BiPlanarBlock\",\n emit(block, outputName, stage, state, ctx) {\n if (outputName === \"level\") {\n return { expr: \"1.0\", type: \"f32\" };\n }\n const sample = emitBiPlanarSample(block, stage, state, ctx);\n const out = OUTPUT[outputName] ?? OUTPUT.rgba!;\n const serialized = block.serialized as { convertToLinearSpace?: boolean; convertToGammaSpace?: boolean };\n const converted = applyColorSpace(sample.expr, outputName, serialized.convertToLinearSpace === true, serialized.convertToGammaSpace === true);\n return { expr: converted === sample.expr ? `${sample.expr}${out.swizzle}` : converted, type: out.type };\n },\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"biplanar-block.js","sources":["../../../../../src/material/node/blocks/biplanar-block.ts"],"sourcesContent":["/** BiPlanarBlock — two-axis variant of triplanar texture projection.\n *\n * Uses the Babylon.js/Iñigo Quilez biplanar method: choose major/median axes\n * from abs(normal), sample those projections with explicit position\n * derivatives, and blend with the shaped two-component weights.\n */\n\nimport type { BlockEmitter, NodeBlock, NodeBuildState, NodeEmitContext, NodeExpr, NodeValueType, Stage } from \"../node-types.js\";\n\nconst OUTPUT: Record<string, { swizzle: string; type: NodeValueType }> = {\n rgba: { swizzle: \"\", type: \"vec4f\" },\n rgb: { swizzle: \".xyz\", type: \"vec3f\" },\n r: { swizzle: \".x\", type: \"f32\" },\n g: { swizzle: \".y\", type: \"f32\" },\n b: { swizzle: \".z\", type: \"f32\" },\n a: { swizzle: \".w\", type: \"f32\" },\n};\n\nfunction bindingName(block: NodeBlock, inputName: string, ctx: NodeEmitContext, fallback: string): string {\n const input = block.inputs.get(inputName);\n if (input?.source) {\n const producer = ctx.graph.blocks.get(input.source.blockId);\n return ctx.sanitize(producer?.name || fallback);\n }\n return ctx.sanitize(fallback);\n}\n\nfunction ensureBinding(state: NodeBuildState, name: string): void {\n if (!state.textures.find((t) => t.name === name)) {\n state.textures.push({ name, kind: \"texture2d\", texture: null });\n }\n}\n\nfunction applyColorSpace(expr: string, outputName: string, convertToLinear: boolean, convertToGamma: boolean): string {\n if (!convertToLinear && !convertToGamma) {\n return expr;\n }\n const power = convertToLinear ? \"2.2\" : \"0.45454545\";\n if (outputName === \"rgba\") {\n return `vec4<f32>(pow(max(${expr}.xyz, vec3<f32>(0.0)), vec3<f32>(${power})), ${expr}.w)`;\n }\n if (outputName === \"rgb\") {\n return `pow(max(${expr}.xyz, vec3<f32>(0.0)), vec3<f32>(${power}))`;\n }\n if (outputName === \"r\" || outputName === \"g\" || outputName === \"b\") {\n return `pow(max(${expr}${OUTPUT[outputName]!.swizzle}, 0.0), ${power})`;\n }\n return expr;\n}\n\nfunction emitBiPlanarSample(block: NodeBlock, stage: Stage, state: NodeBuildState, ctx: NodeEmitContext): NodeExpr {\n if (stage !== \"fragment\") {\n throw new Error(\"BiPlanarBlock: texture projection is supported only in the fragment stage\");\n }\n\n const stageState = state.fragment;\n const memoKey = `_biplanar_${block.id}_sample`;\n const memo = stageState.memo.get(memoKey);\n if (memo) {\n return memo;\n }\n\n const baseName = ctx.sanitize(block.name || `biPlanar${block.id}`);\n const texX = bindingName(block, \"source\", ctx, baseName);\n const texY = bindingName(block, \"sourceY\", ctx, texX);\n ensureBinding(state, texX);\n ensureBinding(state, texY);\n\n const position = ctx.cast(ctx.resolve(block, \"position\", stage, state), \"vec3f\");\n const normal = ctx.cast(ctx.resolve(block, \"normal\", stage, state), \"vec3f\");\n const sharpness = block.inputs.get(\"sharpness\")?.source ? ctx.cast(ctx.resolve(block, \"sharpness\", stage, state), \"f32\").expr : \"1.0\";\n\n const temp = ctx.temp(state, \"bi\");\n const p = `_p${temp}`;\n const dx = `_dx${temp}`;\n const dy = `_dy${temp}`;\n const n = `_n${temp}`;\n const ma = `_ma${temp}`;\n const mi = `_mi${temp}`;\n const me = `_me${temp}`;\n const x = `_x${temp}`;\n const y = `_y${temp}`;\n const w = `_w${temp}`;\n const sample = `_sample${temp}`;\n\n stageState.body.push(`let ${p} = ${position.expr};`);\n stageState.body.push(`let ${dx} = dpdx(${p});`);\n stageState.body.push(`let ${dy} = dpdy(${p});`);\n stageState.body.push(`let ${n} = abs(${normal.expr});`);\n stageState.body.push(`var ${ma}: vec3<i32>;`);\n stageState.body.push(\n `if (${n}.x > ${n}.y && ${n}.x > ${n}.z) { ${ma} = vec3<i32>(0, 1, 2); } else if (${n}.y > ${n}.z) { ${ma} = vec3<i32>(1, 2, 0); } else { ${ma} = vec3<i32>(2, 0, 1); }`\n );\n stageState.body.push(`var ${mi}: vec3<i32>;`);\n stageState.body.push(\n `if (${n}.x < ${n}.y && ${n}.x < ${n}.z) { ${mi} = vec3<i32>(0, 1, 2); } else if (${n}.y < ${n}.z) { ${mi} = vec3<i32>(1, 2, 0); } else { ${mi} = vec3<i32>(2, 0, 1); }`\n );\n stageState.body.push(`let ${me} = vec3<i32>(3, 3, 3) - ${mi} - ${ma};`);\n stageState.body.push(\n `let ${x} = textureSampleGrad(nodeTex_${texX}, nodeSamp_${texX}, vec2<f32>(${p}[${ma}.y], ${p}[${ma}.z]), vec2<f32>(${dx}[${ma}.y], ${dx}[${ma}.z]), vec2<f32>(${dy}[${ma}.y], ${dy}[${ma}.z]));`\n );\n stageState.body.push(\n `let ${y} = textureSampleGrad(nodeTex_${texY}, nodeSamp_${texY}, vec2<f32>(${p}[${me}.y], ${p}[${me}.z]), vec2<f32>(${dx}[${me}.y], ${dx}[${me}.z]), vec2<f32>(${dy}[${me}.y], ${dy}[${me}.z]));`\n );\n stageState.body.push(`var ${w} = vec2<f32>(${n}[${ma}.x], ${n}[${me}.x]);`);\n stageState.body.push(`${w} = clamp((${w} - vec2<f32>(0.5773)) / vec2<f32>(1.0 - 0.5773), vec2<f32>(0.0), vec2<f32>(1.0));`);\n stageState.body.push(`${w} = pow(${w}, vec2<f32>(${sharpness} / 8.0));`);\n stageState.body.push(`let ${sample} = (${x} * ${w}.x + ${y} * ${w}.y) / (${w}.x + ${w}.y);`);\n\n const result = { expr: sample, type: \"vec4f\" } as const;\n stageState.memo.set(memoKey, result);\n return result;\n}\n\nexport const emitter: BlockEmitter = {\n className: \"BiPlanarBlock\",\n emit(block, outputName, stage, state, ctx) {\n if (outputName === \"level\") {\n return { expr: \"1.0\", type: \"f32\" };\n }\n const sample = emitBiPlanarSample(block, stage, state, ctx);\n const out = OUTPUT[outputName] ?? OUTPUT.rgba!;\n const serialized = block.serialized as { convertToLinearSpace?: boolean; convertToGammaSpace?: boolean };\n const converted = applyColorSpace(sample.expr, outputName, serialized.convertToLinearSpace === true, serialized.convertToGammaSpace === true);\n return { expr: converted === sample.expr ? `${sample.expr}${out.swizzle}` : converted, type: out.type };\n },\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
const emitter = {
|
|
2
2
|
className: "ImageSourceBlock",
|
|
3
|
-
emit(block, _outputName, _stage, state,
|
|
4
|
-
const bindingName = sanitize(block.name || `img${block.id}`);
|
|
3
|
+
emit(block, _outputName, _stage, state, ctx) {
|
|
4
|
+
const bindingName = ctx.sanitize(block.name || `img${block.id}`);
|
|
5
5
|
if (!state.textures.find((t) => t.name === bindingName)) {
|
|
6
6
|
state.textures.push({ name: bindingName, kind: "texture2d", texture: null });
|
|
7
7
|
}
|
|
8
8
|
return { expr: bindingName, type: "texture2d" };
|
|
9
9
|
}
|
|
10
10
|
};
|
|
11
|
-
function sanitize(name) {
|
|
12
|
-
return name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
13
|
-
}
|
|
14
11
|
|
|
15
12
|
export { emitter };
|
|
16
13
|
//# sourceMappingURL=image-source.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-source.js","sources":["../../../../../src/material/node/blocks/image-source.ts"],"sourcesContent":["/** ImageSourceBlock — holds a texture reference and feeds a TextureBlock's `source` input.\n *\n * The emitter does not emit any WGSL of its own; it just advertises that a\n * texture binding named after this block exists, so the downstream TextureBlock\n * can refer to it. The actual texture upload is handled at material-build time.\n */\n\nimport type { BlockEmitter } from \"../node-types.js\";\n\nexport const emitter: BlockEmitter = {\n className: \"ImageSourceBlock\",\n emit(block, _outputName, _stage, state,
|
|
1
|
+
{"version":3,"file":"image-source.js","sources":["../../../../../src/material/node/blocks/image-source.ts"],"sourcesContent":["/** ImageSourceBlock — holds a texture reference and feeds a TextureBlock's `source` input.\n *\n * The emitter does not emit any WGSL of its own; it just advertises that a\n * texture binding named after this block exists, so the downstream TextureBlock\n * can refer to it. The actual texture upload is handled at material-build time.\n */\n\nimport type { BlockEmitter } from \"../node-types.js\";\n\nexport const emitter: BlockEmitter = {\n className: \"ImageSourceBlock\",\n emit(block, _outputName, _stage, state, ctx) {\n const bindingName = ctx.sanitize(block.name || `img${block.id}`);\n if (!state.textures.find((t) => t.name === bindingName)) {\n state.textures.push({ name: bindingName, kind: \"texture2d\", texture: null });\n }\n // Return a sentinel — the TextureBlock consumes the binding name via this.\n return { expr: bindingName, type: \"texture2d\" };\n },\n};\n"],"names":[],"mappings":"AASO,MAAM,OAAA,GAAwB;AAAA,EACjC,SAAA,EAAW,kBAAA;AAAA,EACX,IAAA,CAAK,KAAA,EAAO,WAAA,EAAa,MAAA,EAAQ,OAAO,GAAA,EAAK;AACzC,IAAA,MAAM,WAAA,GAAc,IAAI,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,GAAA,EAAM,KAAA,CAAM,EAAE,CAAA,CAAE,CAAA;AAC/D,IAAA,IAAI,CAAC,MAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,WAAW,CAAA,EAAG;AACrD,MAAA,KAAA,CAAM,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,aAAa,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,IAAA,EAAM,CAAA;AAAA,IAC/E;AAEA,IAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,WAAA,EAAY;AAAA,EAClD;AACJ;;;;"}
|
|
@@ -1,23 +1,5 @@
|
|
|
1
1
|
import { WGSL } from '../node-types.js';
|
|
2
2
|
|
|
3
|
-
function bjsTypeToNodeType(t) {
|
|
4
|
-
if (t === 1 || t === 2) {
|
|
5
|
-
return "f32";
|
|
6
|
-
}
|
|
7
|
-
if (t === 4) {
|
|
8
|
-
return "vec2f";
|
|
9
|
-
}
|
|
10
|
-
if (t === 8 || t === 32) {
|
|
11
|
-
return "vec3f";
|
|
12
|
-
}
|
|
13
|
-
if (t === 16 || t === 64) {
|
|
14
|
-
return "vec4f";
|
|
15
|
-
}
|
|
16
|
-
if (t === 128) {
|
|
17
|
-
return "mat4f";
|
|
18
|
-
}
|
|
19
|
-
throw new Error(`InputBlock: unsupported BJS connection point type 0x${t.toString(16)}`);
|
|
20
|
-
}
|
|
21
3
|
const ATTRIBUTE_TYPES = {
|
|
22
4
|
position: "vec3f",
|
|
23
5
|
normal: "vec3f",
|
|
@@ -78,21 +60,18 @@ function emitSystemValue(block, stage, state) {
|
|
|
78
60
|
throw new Error(`InputBlock: unsupported systemValue ${sv} on block "${block.name}"`);
|
|
79
61
|
}
|
|
80
62
|
}
|
|
81
|
-
function emitUniform(block, state) {
|
|
63
|
+
function emitUniform(block, state, ctx) {
|
|
82
64
|
const portType = block.serialized["type"] ?? 16;
|
|
83
|
-
const type = bjsTypeToNodeType(portType);
|
|
84
|
-
const fieldName = sanitize(block.name || `input${block.id}`);
|
|
65
|
+
const type = ctx.bjsTypeToNodeType(portType, "InputBlock");
|
|
66
|
+
const fieldName = ctx.sanitize(block.name || `input${block.id}`);
|
|
85
67
|
if (!state.nodeUboFields.find((f) => f._name === fieldName)) {
|
|
86
68
|
state.nodeUboFields.push({ _name: fieldName, _type: WGSL[type] });
|
|
87
69
|
}
|
|
88
70
|
return { expr: `nodeU.${fieldName}`, type };
|
|
89
71
|
}
|
|
90
|
-
function sanitize(name) {
|
|
91
|
-
return name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
92
|
-
}
|
|
93
72
|
const emitter = {
|
|
94
73
|
className: "InputBlock",
|
|
95
|
-
emit(block, _outputName, stage, state,
|
|
74
|
+
emit(block, _outputName, stage, state, ctx) {
|
|
96
75
|
const mode = block.serialized["mode"] ?? block.serialized["_mode"];
|
|
97
76
|
if (mode === 1) {
|
|
98
77
|
return emitAttribute(block, stage, state);
|
|
@@ -101,7 +80,7 @@ const emitter = {
|
|
|
101
80
|
if (typeof sv === "number") {
|
|
102
81
|
return emitSystemValue(block);
|
|
103
82
|
}
|
|
104
|
-
return emitUniform(block, state);
|
|
83
|
+
return emitUniform(block, state, ctx);
|
|
105
84
|
}
|
|
106
85
|
};
|
|
107
86
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-block.js","sources":["../../../../../src/material/node/blocks/input-block.ts"],"sourcesContent":["/** InputBlock emitter.\n *\n * Three modes (BJS NodeMaterialBlockConnectionPointMode):\n * 0 = Uniform — inline value becomes a field in the node UBO.\n * 1 = Attribute — bound to a vertex attribute (position/normal/uv/...).\n * 2 = Varying — interpolated from a system/pre-existing varying.\n *\n * For attributes we declare the vertex attribute (dedup by name) and, if the\n * value is consumed in fragment stage, a varying to carry it across.\n */\n\nimport type { BlockEmitter, NodeBuildState, NodeExpr, NodeValueType, Stage, NodeBlock } from \"../node-types.js\";\nimport { WGSL } from \"../node-types.js\";\n\ntype BjsType = number; // NodeMaterialBlockConnectionPointTypes\n\nfunction bjsTypeToNodeType(t: BjsType): NodeValueType {\n // bitflags: 0x1=Float, 0x4=Vec2, 0x8=Vec3, 0x10=Vec4, 0x20=Color3, 0x40=Color4\n if (t === 0x1 || t === 0x2) {\n return \"f32\";\n }\n if (t === 0x4) {\n return \"vec2f\";\n }\n if (t === 0x8 || t === 0x20) {\n return \"vec3f\";\n }\n if (t === 0x10 || t === 0x40) {\n return \"vec4f\";\n }\n if (t === 0x80) {\n return \"mat4f\";\n }\n throw new Error(`InputBlock: unsupported BJS connection point type 0x${t.toString(16)}`);\n}\n\nfunction wgslLiteral(value: unknown, type: NodeValueType): string {\n if (type === \"f32\") {\n const f = typeof value === \"number\" ? value : 0;\n return formatFloat(f);\n }\n if (Array.isArray(value)) {\n const parts = value.map((v) => formatFloat(typeof v === \"number\" ? v : 0)).join(\", \");\n return `${WGSL[type]}(${parts})`;\n }\n // Fallback to zero.\n if (type === \"vec2f\") {\n return \"vec2<f32>(0.0, 0.0)\";\n }\n if (type === \"vec3f\") {\n return \"vec3<f32>(0.0, 0.0, 0.0)\";\n }\n if (type === \"vec4f\") {\n return \"vec4<f32>(0.0, 0.0, 0.0, 0.0)\";\n }\n return \"0.0\";\n}\n\nfunction formatFloat(n: number): string {\n if (Number.isInteger(n)) {\n return `${n}.0`;\n }\n return `${n}`;\n}\n\n// Known mesh attributes — maps InputBlock.name → WGSL type.\nconst ATTRIBUTE_TYPES: Record<string, NodeValueType> = {\n position: \"vec3f\",\n normal: \"vec3f\",\n tangent: \"vec4f\",\n uv: \"vec2f\",\n uv2: \"vec2f\",\n color: \"vec4f\",\n matricesIndices: \"vec4f\",\n matricesWeights: \"vec4f\",\n matricesIndicesExtra: \"vec4f\",\n matricesWeightsExtra: \"vec4f\",\n};\n\nfunction emitAttribute(block: NodeBlock, stage: Stage, state: NodeBuildState): NodeExpr {\n const attrName = block.name;\n const type = ATTRIBUTE_TYPES[attrName];\n if (!type) {\n throw new Error(`InputBlock: unknown mesh attribute \"${attrName}\"`);\n }\n const wgslType = WGSL[type];\n // Dedup vertex attribute.\n if (!state.vertexAttributes.find((a) => a._name === attrName)) {\n state.vertexAttributes.push({\n _name: attrName,\n _type: wgslType,\n _gpuFormat: type === \"vec2f\" ? \"float32x2\" : type === \"vec3f\" ? \"float32x3\" : \"float32x4\",\n _arrayStride: (type === \"vec2f\" ? 2 : type === \"vec3f\" ? 3 : 4) * 4,\n });\n }\n if (stage === \"vertex\") {\n return { expr: `in.${attrName}`, type };\n }\n // In fragment stage — bridge through a varying (idempotent).\n const vname = `v_attr_${attrName}`;\n if (!state.varyings.find((v) => v._name === vname)) {\n state.varyings.push({ _name: vname, _type: wgslType });\n state.vertex.body.push(`out.${vname} = in.${attrName};`);\n }\n return { expr: `in.${vname}`, type };\n}\n\n// BJS NodeMaterialSystemValues enum (Babylon.js master).\n// We map the commonly used ones to WGSL expressions sourced from scene/mesh UBOs.\n// For matrices not present in Lite's scene UBO (`projection` alone), we fall\n// back to the closest valid expression (or throw — caller decides).\nfunction emitSystemValue(block: NodeBlock, stage: Stage, state: NodeBuildState): NodeExpr {\n const sv = block.serialized[\"systemValue\"] as number | undefined;\n // Only sensible in the vertex stage for matrix types; for CameraPosition/FogColor either stage is fine.\n switch (sv) {\n case 1: // World\n return { expr: \"meshU.world\", type: \"mat4f\" };\n case 2: // View\n return { expr: \"sceneU.view\", type: \"mat4f\" };\n case 3: // Projection\n return { expr: \"sceneU.projection\", type: \"mat4f\" };\n case 4: // ViewProjection\n return { expr: \"sceneU.viewProjection\", type: \"mat4f\" };\n case 5: // WorldView\n return { expr: \"(sceneU.view * meshU.world)\", type: \"mat4f\" };\n case 6: // WorldViewProjection\n return { expr: \"(sceneU.viewProjection * meshU.world)\", type: \"mat4f\" };\n case 7: // CameraPosition\n return { expr: \"sceneU.vEyePosition.xyz\", type: \"vec3f\" };\n case 8: // FogColor\n return { expr: \"sceneU.vFogColor.xyz\", type: \"vec3f\" };\n default:\n throw new Error(`InputBlock: unsupported systemValue ${sv} on block \"${block.name}\"`);\n }\n void stage;\n void state;\n}\n\nfunction emitUniform(block: NodeBlock, state: NodeBuildState): NodeExpr {\n // Determine the WGSL type. BJS serializes the port type under `type`.\n const portType = (block.serialized[\"type\"] as BjsType | undefined) ?? 0x10;\n const type = bjsTypeToNodeType(portType);\n // UBO field name — use block name (must be unique; parser enforces via namedInputs key).\n const fieldName = sanitize(block.name || `input${block.id}`);\n // Dedup.\n if (!state.nodeUboFields.find((f) => f._name === fieldName)) {\n state.nodeUboFields.push({ _name: fieldName, _type: WGSL[type] as any });\n // If this is a literal value (no override yet), it will be written into the\n // UBO at material-build time; for shader generation we just reference the field.\n // We ignore the inline literal here — the UBO write path handles that.\n }\n void wgslLiteral; // reserved for future default-literal constant-fold optimization\n return { expr: `nodeU.${fieldName}`, type };\n}\n\nfunction sanitize(name: string): string {\n return name.replace(/[^A-Za-z0-9_]/g, \"_\");\n}\n\nexport const emitter: BlockEmitter = {\n className: \"InputBlock\",\n emit(block, _outputName, stage, state, _ctx) {\n const mode = (block.serialized[\"mode\"] ?? block.serialized[\"_mode\"]) as number | undefined;\n if (mode === 1) {\n return emitAttribute(block, stage, state);\n }\n // System-value uniforms (World, WVP, CameraPosition, …) come from scene/mesh UBOs\n // rather than the material's node UBO, so they never appear in `nodeUboFields`.\n const sv = block.serialized[\"systemValue\"];\n if (typeof sv === \"number\") {\n return emitSystemValue(block, stage, state);\n }\n // Default to Uniform (mode 0 or unspecified).\n return emitUniform(block, state);\n },\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input-block.js","sources":["../../../../../src/material/node/blocks/input-block.ts"],"sourcesContent":["/** InputBlock emitter.\n *\n * Three modes (BJS NodeMaterialBlockConnectionPointMode):\n * 0 = Uniform — inline value becomes a field in the node UBO.\n * 1 = Attribute — bound to a vertex attribute (position/normal/uv/...).\n * 2 = Varying — interpolated from a system/pre-existing varying.\n *\n * For attributes we declare the vertex attribute (dedup by name) and, if the\n * value is consumed in fragment stage, a varying to carry it across.\n */\n\nimport type { BlockEmitter, NodeBuildState, NodeEmitContext, NodeExpr, NodeValueType, Stage, NodeBlock } from \"../node-types.js\";\nimport { WGSL } from \"../node-types.js\";\n\ntype BjsType = number; // NodeMaterialBlockConnectionPointTypes\n\nfunction wgslLiteral(value: unknown, type: NodeValueType): string {\n if (type === \"f32\") {\n const f = typeof value === \"number\" ? value : 0;\n return formatFloat(f);\n }\n if (Array.isArray(value)) {\n const parts = value.map((v) => formatFloat(typeof v === \"number\" ? v : 0)).join(\", \");\n return `${WGSL[type]}(${parts})`;\n }\n // Fallback to zero.\n if (type === \"vec2f\") {\n return \"vec2<f32>(0.0, 0.0)\";\n }\n if (type === \"vec3f\") {\n return \"vec3<f32>(0.0, 0.0, 0.0)\";\n }\n if (type === \"vec4f\") {\n return \"vec4<f32>(0.0, 0.0, 0.0, 0.0)\";\n }\n return \"0.0\";\n}\n\nfunction formatFloat(n: number): string {\n if (Number.isInteger(n)) {\n return `${n}.0`;\n }\n return `${n}`;\n}\n\n// Known mesh attributes — maps InputBlock.name → WGSL type.\nconst ATTRIBUTE_TYPES: Record<string, NodeValueType> = {\n position: \"vec3f\",\n normal: \"vec3f\",\n tangent: \"vec4f\",\n uv: \"vec2f\",\n uv2: \"vec2f\",\n color: \"vec4f\",\n matricesIndices: \"vec4f\",\n matricesWeights: \"vec4f\",\n matricesIndicesExtra: \"vec4f\",\n matricesWeightsExtra: \"vec4f\",\n};\n\nfunction emitAttribute(block: NodeBlock, stage: Stage, state: NodeBuildState): NodeExpr {\n const attrName = block.name;\n const type = ATTRIBUTE_TYPES[attrName];\n if (!type) {\n throw new Error(`InputBlock: unknown mesh attribute \"${attrName}\"`);\n }\n const wgslType = WGSL[type];\n // Dedup vertex attribute.\n if (!state.vertexAttributes.find((a) => a._name === attrName)) {\n state.vertexAttributes.push({\n _name: attrName,\n _type: wgslType,\n _gpuFormat: type === \"vec2f\" ? \"float32x2\" : type === \"vec3f\" ? \"float32x3\" : \"float32x4\",\n _arrayStride: (type === \"vec2f\" ? 2 : type === \"vec3f\" ? 3 : 4) * 4,\n });\n }\n if (stage === \"vertex\") {\n return { expr: `in.${attrName}`, type };\n }\n // In fragment stage — bridge through a varying (idempotent).\n const vname = `v_attr_${attrName}`;\n if (!state.varyings.find((v) => v._name === vname)) {\n state.varyings.push({ _name: vname, _type: wgslType });\n state.vertex.body.push(`out.${vname} = in.${attrName};`);\n }\n return { expr: `in.${vname}`, type };\n}\n\n// BJS NodeMaterialSystemValues enum (Babylon.js master).\n// We map the commonly used ones to WGSL expressions sourced from scene/mesh UBOs.\n// For matrices not present in Lite's scene UBO (`projection` alone), we fall\n// back to the closest valid expression (or throw — caller decides).\nfunction emitSystemValue(block: NodeBlock, stage: Stage, state: NodeBuildState): NodeExpr {\n const sv = block.serialized[\"systemValue\"] as number | undefined;\n // Only sensible in the vertex stage for matrix types; for CameraPosition/FogColor either stage is fine.\n switch (sv) {\n case 1: // World\n return { expr: \"meshU.world\", type: \"mat4f\" };\n case 2: // View\n return { expr: \"sceneU.view\", type: \"mat4f\" };\n case 3: // Projection\n return { expr: \"sceneU.projection\", type: \"mat4f\" };\n case 4: // ViewProjection\n return { expr: \"sceneU.viewProjection\", type: \"mat4f\" };\n case 5: // WorldView\n return { expr: \"(sceneU.view * meshU.world)\", type: \"mat4f\" };\n case 6: // WorldViewProjection\n return { expr: \"(sceneU.viewProjection * meshU.world)\", type: \"mat4f\" };\n case 7: // CameraPosition\n return { expr: \"sceneU.vEyePosition.xyz\", type: \"vec3f\" };\n case 8: // FogColor\n return { expr: \"sceneU.vFogColor.xyz\", type: \"vec3f\" };\n default:\n throw new Error(`InputBlock: unsupported systemValue ${sv} on block \"${block.name}\"`);\n }\n void stage;\n void state;\n}\n\nfunction emitUniform(block: NodeBlock, state: NodeBuildState, ctx: NodeEmitContext): NodeExpr {\n // Determine the WGSL type. BJS serializes the port type under `type`.\n const portType = (block.serialized[\"type\"] as BjsType | undefined) ?? 0x10;\n const type = ctx.bjsTypeToNodeType(portType, \"InputBlock\");\n // UBO field name — use block name (must be unique; parser enforces via namedInputs key).\n const fieldName = ctx.sanitize(block.name || `input${block.id}`);\n // Dedup.\n if (!state.nodeUboFields.find((f) => f._name === fieldName)) {\n state.nodeUboFields.push({ _name: fieldName, _type: WGSL[type] as any });\n // If this is a literal value (no override yet), it will be written into the\n // UBO at material-build time; for shader generation we just reference the field.\n // We ignore the inline literal here — the UBO write path handles that.\n }\n void wgslLiteral; // reserved for future default-literal constant-fold optimization\n return { expr: `nodeU.${fieldName}`, type };\n}\n\nexport const emitter: BlockEmitter = {\n className: \"InputBlock\",\n emit(block, _outputName, stage, state, ctx) {\n const mode = (block.serialized[\"mode\"] ?? block.serialized[\"_mode\"]) as number | undefined;\n if (mode === 1) {\n return emitAttribute(block, stage, state);\n }\n // System-value uniforms (World, WVP, CameraPosition, …) come from scene/mesh UBOs\n // rather than the material's node UBO, so they never appear in `nodeUboFields`.\n const sv = block.serialized[\"systemValue\"];\n if (typeof sv === \"number\") {\n return emitSystemValue(block, stage, state);\n }\n // Default to Uniform (mode 0 or unspecified).\n return emitUniform(block, state, ctx);\n },\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -137,17 +137,14 @@ let ccNdfdy_AA = dpdy(ccNormalW);
|
|
|
137
137
|
let ccSlopeSquare_AA = max(dot(ccNdfdx_AA, ccNdfdx_AA), dot(ccNdfdy_AA, ccNdfdy_AA));
|
|
138
138
|
ccAA_factor_y = sqrt(ccSlopeSquare_AA) * 0.75; }` : ``}
|
|
139
139
|
let ccAlphaG = ccRough * ccRough + 0.0005 + ccAA_factor_y;` : ``;
|
|
140
|
-
const
|
|
141
|
-
let ccNdotV = abs(dot(ccNormalW, V)) + 0.0000001;${useCcTint ? `
|
|
140
|
+
const ccTintViewSetup = useCcTint ? `
|
|
142
141
|
let ccIorInv = 1.0 / max(ccIor, 1.0001);
|
|
143
142
|
let ccAbsorptionColor = nme_pbr_colorAtDistance(max(ccTintColor, v3(0.0000001)), max(ccTintAtDistance, 0.0000001));
|
|
144
143
|
let ccVRefract = refract(-V, ccNormalW, ccIorInv);
|
|
145
|
-
let ccNdotVRefract = abs(dot(ccNormalW, ccVRefract)) + 0.0000001;` :
|
|
146
|
-
let
|
|
147
|
-
let
|
|
148
|
-
let
|
|
149
|
-
let ccVRefract = refract(-V, ccNormalW, ccIorInv);
|
|
150
|
-
let ccNdotVRefract = abs(dot(ccNormalW, ccVRefract)) + 0.0000001;` : ``}` : `let ccNormalW = N;
|
|
144
|
+
let ccNdotVRefract = abs(dot(ccNormalW, ccVRefract)) + 0.0000001;` : ``;
|
|
145
|
+
const ccNormalSetup = useClearcoat ? useCcBump ? `let ccNormalW = nme_perturbNormal(worldPos, Ng, ccBumpUv, ccBumpColor, 1.0);
|
|
146
|
+
let ccNdotV = abs(dot(ccNormalW, V)) + 0.0000001;${ccTintViewSetup}` : `let ccNormalW = Ng;
|
|
147
|
+
let ccNdotV = abs(dot(ccNormalW, V)) + 0.0000001;${ccTintViewSetup}` : `let ccNormalW = N;
|
|
151
148
|
let ccNdotV: f32 = 0.0;`;
|
|
152
149
|
const shDecls = useSheen ? `let shIntensityRaw = clamp(shIntensityIn, 0.0, 1.0);
|
|
153
150
|
${useShAlbedoScaling ? `let shIntensity = shIntensityRaw;` : `let reflectanceF0 = max(colorF0.r, max(colorF0.g, colorF0.b));
|