@meimu/mutracer 0.2.0 → 0.3.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/README.md +3 -0
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +8949 -7915
- package/docs/api.md +42 -21
- package/docs/caustics.md +80 -0
- package/docs/materials.md +5 -4
- package/docs/progressive-rendering.md +50 -9
- package/docs/technical/continuous-spectrum.md +93 -0
- package/docs/updates.md +3 -1
- package/docs/viewer-checklist.md +65 -0
- package/docs/viewer.md +7 -5
- package/lib/Display.js +1 -1
- package/lib/Display.js.map +1 -1
- package/lib/Engine.d.ts +2 -0
- package/lib/Engine.js +47 -12
- package/lib/Engine.js.map +1 -1
- package/lib/Render.d.ts +61 -13
- package/lib/Render.js +169 -19
- package/lib/Render.js.map +1 -1
- package/lib/RenderLoop.d.ts +7 -3
- package/lib/RenderLoop.js +68 -44
- package/lib/RenderLoop.js.map +1 -1
- package/lib/main.d.ts +1 -1
- package/lib/main.js.map +1 -1
- package/lib/oidn.d.ts +1 -1
- package/lib/oidnBundledWeights.cdn.d.ts +2 -2
- package/lib/renderer/GPUTraceQueue.d.ts +2 -1
- package/lib/renderer/GPUTraceQueue.js +3 -1
- package/lib/renderer/GPUTraceQueue.js.map +1 -1
- package/lib/renderer/RenderingPipeline.d.ts +4 -0
- package/lib/renderer/RenderingPipeline.js.map +1 -1
- package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
- package/lib/renderer/WGPUCausticLightPass.js +217 -0
- package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
- package/lib/renderer/WGPUEnvMapDistribution.js +18 -18
- package/lib/renderer/WGPUFullQuadPass.js +3 -3
- package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
- package/lib/renderer/WGPUPhotonMap.js +191 -0
- package/lib/renderer/WGPUPhotonMap.js.map +1 -0
- package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
- package/lib/renderer/WGPURayTraceOutput.js +122 -28
- package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
- package/lib/renderer/WGPURayTracePass.d.ts +48 -17
- package/lib/renderer/WGPURayTracePass.js +538 -340
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.js +83 -47
- package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
- package/lib/renderer/WebGLFullQuadPass.js +4 -0
- package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
- package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
- package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
- package/lib/renderer/WebGLRayTracePass.d.ts +6 -1
- package/lib/renderer/WebGLRayTracePass.js +43 -6
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/WebGLRenderingPipeline.js +10 -14
- package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLSkyBaker.js +60 -60
- package/lib/renderer/accumulationTarget.d.ts +2 -1
- package/lib/renderer/accumulationTarget.js.map +1 -1
- package/lib/renderer/causticDiagnostics.d.ts +31 -0
- package/lib/renderer/causticDiagnostics.js +5 -0
- package/lib/renderer/causticDiagnostics.js.map +1 -0
- package/lib/renderer/causticEmission.d.ts +10 -0
- package/lib/renderer/causticEmission.js +40 -0
- package/lib/renderer/causticEmission.js.map +1 -0
- package/lib/renderer/causticUniform.d.ts +12 -0
- package/lib/renderer/causticUniform.js +22 -0
- package/lib/renderer/causticUniform.js.map +1 -0
- package/lib/renderer/caustics.d.ts +16 -0
- package/lib/renderer/caustics.js +93 -0
- package/lib/renderer/caustics.js.map +1 -0
- package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
- package/lib/renderer/glsl/aovReflectance.glsl.js +53 -53
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
- package/lib/renderer/glsl/aovTrace.frag.js +33 -33
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -9
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
- package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -73
- package/lib/renderer/glsl/chunks/intersect.glsl.js +426 -428
- package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +156 -153
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +771 -771
- package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
- package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +68 -63
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +94 -76
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +140 -117
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +14 -14
- package/lib/renderer/glsl/chunks/sampling.glsl.js +89 -92
- package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
- package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
- package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
- package/lib/renderer/glsl/depthQuery.frag.js +2 -2
- package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
- package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
- package/lib/renderer/glsl/rayTrace.frag.js +260 -237
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +26 -26
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
- package/lib/renderer/lightSampling.d.ts +3 -2
- package/lib/renderer/lightSampling.js +14 -8
- package/lib/renderer/lightSampling.js.map +1 -1
- package/lib/renderer/progressiveScheduler.js +4 -3
- package/lib/renderer/progressiveScheduler.js.map +1 -1
- package/lib/renderer/renderPipeline.d.ts +1 -0
- package/lib/renderer/renderPipeline.js.map +1 -1
- package/lib/renderer/researchTransport.d.ts +31 -0
- package/lib/renderer/researchTransport.js +5 -0
- package/lib/renderer/researchTransport.js.map +1 -0
- package/lib/renderer/sceneLayoutSchema.d.ts +1 -0
- package/lib/renderer/sceneLayoutSchema.js +2 -2
- package/lib/renderer/sceneLayoutSchema.js.map +1 -1
- package/lib/renderer/scratchSampling.js +6 -6
- package/lib/renderer/spectrum.d.ts +21 -0
- package/lib/renderer/spectrum.js +154 -0
- package/lib/renderer/spectrum.js.map +1 -0
- package/lib/renderer/webglLightSampling.d.ts +39 -0
- package/lib/renderer/webglLightSampling.js +15 -0
- package/lib/renderer/webglLightSampling.js.map +1 -0
- package/lib/renderer/wgpuBindlessSource.js +3 -3
- package/lib/renderer/wgpuShaderSource.d.ts +7 -0
- package/lib/renderer/wgpuShaderSource.js +2 -0
- package/lib/renderer/wgpuShaderSource.js.map +1 -1
- package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
- package/lib/renderer/wgsl/aovReflectance.wgsl.js +55 -55
- package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
- package/lib/renderer/wgsl/aovResolve.wgsl.js +2 -2
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js +1 -1
- package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
- package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
- package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
- package/lib/renderer/wgsl/causticLight.compute.js +537 -0
- package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js +37 -37
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +598 -592
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +14 -14
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +75 -73
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +794 -794
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
- package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +2 -1
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +35 -25
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +142 -138
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +204 -187
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +11 -11
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js +89 -93
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
- package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
- package/lib/renderer/wgsl/compose.frag.wgsl.js +98 -98
- package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
- package/lib/renderer/wgsl/depthQuery.wgsl.js +2 -2
- package/lib/renderer/wgsl/jnlm.compute.js +74 -74
- package/lib/renderer/wgsl/offlineAdaptive.compute.js +25 -25
- package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
- package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
- package/lib/renderer/wgsl/photonMap.compute.js +352 -0
- package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
- package/lib/renderer/wgsl/proceduralSky.compute.js +64 -64
- package/lib/renderer/wgsl/rayTrace.compute.d.ts +9 -1
- package/lib/renderer/wgsl/rayTrace.compute.js +448 -522
- package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
- package/lib/scene/MaterialState.d.ts +2 -2
- package/lib/scene/MaterialState.js +2 -2
- package/lib/scene/MaterialState.js.map +1 -1
- package/lib/settings/render.d.ts +11 -0
- package/lib/settings/render.js +1 -0
- package/lib/settings/render.js.map +1 -1
- package/lib/util/fromTHREE.js +2 -2
- package/lib/util/fromTHREE.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/llms.txt +2 -1
- package/package.json +3 -3
|
@@ -5,7 +5,7 @@ import { mapAlphaUsageConstants } from '../../materialConstants.js';
|
|
|
5
5
|
// (https://github.com/hoverinc/ray-tracing-renderer).
|
|
6
6
|
// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.
|
|
7
7
|
import { materialAlphaModeConstants } from '../../materialConstants.js';
|
|
8
|
-
export function createMaterialBufferWgsl({ hasAnisotropyDirections = true, hasCoatNormals = false, hasSceneAlpha = true, hasTransmission = true, hasMetalness = true } = {}) {
|
|
8
|
+
export function createMaterialBufferWgsl({ hasAnisotropyDirections = true, hasCoatNormals = false, hasSceneAlpha = true, hasTransmission = true, caustics = false, hasMetalness = true } = {}) {
|
|
9
9
|
const alphaModeAssignment = hasSceneAlpha
|
|
10
10
|
? '(*ma).alphaMode = i32(matData.alphaMode);'
|
|
11
11
|
: '';
|
|
@@ -20,7 +20,7 @@ else if ((*ma).alphaMode == ${materialAlphaModeConstants.mask}) {
|
|
|
20
20
|
: '(*ma).alpha = 1.0;';
|
|
21
21
|
return /* wgsl */ `
|
|
22
22
|
|
|
23
|
-
${hasAnisotropyDirections ? /* wgsl */ `fn
|
|
23
|
+
${hasAnisotropyDirections ? /* wgsl */ `fn fb(roughness: f32, strength: f32) -> vec2f {
|
|
24
24
|
if (strength == 0.0) { return vec2f(roughness, 0.0); }
|
|
25
25
|
let u = roughness * roughness;
|
|
26
26
|
let a = u + (1.0 - u) * strength * strength;
|
|
@@ -29,55 +29,55 @@ return vec2f(pow((a*a + u*u) * 0.5, 0.25), clamp(1.0 - u/a, 0.0, 1.0));
|
|
|
29
29
|
}
|
|
30
30
|
` : /* wgsl */ ``}
|
|
31
31
|
|
|
32
|
-
fn
|
|
32
|
+
fn mq(c: vec3f) -> vec3f {
|
|
33
33
|
return mix(pow(c * 0.9478672986 + 0.0521327014, vec3f(2.4)), c * 0.0773993808, vec3f(c < vec3f(0.04045)));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
fn decodeMapColor(idx: i32, c: vec3f) -> vec3f {
|
|
37
37
|
if (mapInfo[idx + NUM_MAPS * 2].y > 0.5) { return c; }
|
|
38
|
-
return
|
|
38
|
+
return mq(c);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
fn
|
|
41
|
+
fn af(val: i32) -> vec2f {
|
|
42
42
|
return vec2f(f32(val >> 8), f32(val & 0xff) / 255.0);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
fn
|
|
45
|
+
fn jv(idx: i32) -> vec2f {
|
|
46
46
|
return mapInfo[idx].xy;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
fn
|
|
49
|
+
fn lE(idx: i32) -> i32 {
|
|
50
50
|
return i32(floor(mapInfo[idx].z));
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
fn
|
|
53
|
+
fn jV(idx: i32) -> vec2f {
|
|
54
54
|
return vec2f(fract(mapInfo[idx].z), mapInfo[idx].w);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
fn
|
|
57
|
+
fn fS(value: f32, mode: f32) -> f32 {
|
|
58
58
|
if (mode < 0.5) { return fract(value); }
|
|
59
59
|
if (mode < 1.5) { return clamp(value, 0.0, 1.0); }
|
|
60
60
|
return 1.0 - abs(1.0 - (value - 2.0 * floor(value * 0.5)));
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
fn
|
|
63
|
+
fn kF(idx: i32, uv: vec2f) -> vec2f {
|
|
64
64
|
let transform = mapInfo[idx + NUM_MAPS];
|
|
65
65
|
let modes = mapInfo[idx + NUM_MAPS * 2].zw;
|
|
66
66
|
let value = uv * transform.xy + transform.zw;
|
|
67
|
-
return vec2f(
|
|
67
|
+
return vec2f(fS(value.x, modes.x), fS(value.y, modes.y));
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
fn
|
|
71
|
-
let
|
|
72
|
-
let
|
|
73
|
-
let
|
|
74
|
-
let
|
|
75
|
-
let
|
|
76
|
-
let
|
|
70
|
+
fn tK(idx: i32, uv: vec2f) -> vec2f {
|
|
71
|
+
let rJ = kF(idx, uv);
|
|
72
|
+
let jn = 1.0 / vec2f(textureDimensions(map).xy);
|
|
73
|
+
let dX = jV(idx);
|
|
74
|
+
let kx = jv(idx) + jn;
|
|
75
|
+
let po = dX - 0.5 * jn;
|
|
76
|
+
let lS = dX + kx - jn;
|
|
77
77
|
return clamp(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
po + rJ * kx,
|
|
79
|
+
dX,
|
|
80
|
+
lS
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -86,28 +86,28 @@ return select(uv, uv1, mapInfo[idx + NUM_MAPS * 2].x > 0.5);
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
fn sampleMap(idx: i32, uv: vec2f) -> vec4f {
|
|
89
|
-
let size = vec2i(round(
|
|
90
|
-
let
|
|
89
|
+
let size = vec2i(round(jv(idx) * vec2f(textureDimensions(map).xy) + vec2f(1.0)));
|
|
90
|
+
let cR = kF(idx, uv) * vec2f(size) - vec2f(0.5);
|
|
91
91
|
let modes = mapInfo[idx + NUM_MAPS * 2].zw;
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
if ((size.x > 1 && modes.x < 0.5 && (
|
|
95
|
-
(size.y > 1 && modes.y < 0.5 && (
|
|
96
|
-
let base = vec2i(floor(
|
|
97
|
-
let weight = fract(
|
|
98
|
-
let origin = vec2i(round(
|
|
94
|
+
if ((size.x > 1 && modes.x < 0.5 && (cR.x < 0.0 || cR.x > f32(size.x - 1))) ||
|
|
95
|
+
(size.y > 1 && modes.y < 0.5 && (cR.y < 0.0 || cR.y > f32(size.y - 1)))) {
|
|
96
|
+
let base = vec2i(floor(cR));
|
|
97
|
+
let weight = fract(cR);
|
|
98
|
+
let origin = vec2i(round(jV(idx) * vec2f(textureDimensions(map).xy) - vec2f(0.5)));
|
|
99
99
|
return mix(
|
|
100
|
-
mix(
|
|
101
|
-
mix(
|
|
100
|
+
mix(eN(idx, base, size, origin, modes), eN(idx, base + vec2i(1, 0), size, origin, modes), weight.x),
|
|
101
|
+
mix(eN(idx, base + vec2i(0, 1), size, origin, modes), eN(idx, base + vec2i(1, 1), size, origin, modes), weight.x), weight.y);
|
|
102
102
|
}
|
|
103
|
-
return textureSampleLevel(map, mapSampler,
|
|
103
|
+
return textureSampleLevel(map, mapSampler, tK(idx, uv), lE(idx), 0.0);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
fn
|
|
107
|
-
var p = clamp(
|
|
108
|
-
if (modes.x < 0.5) { p.x = ((
|
|
109
|
-
if (modes.y < 0.5) { p.y = ((
|
|
110
|
-
return textureLoad(map, origin + p,
|
|
106
|
+
fn eN(idx: i32, jq: vec2i, size: vec2i, origin: vec2i, modes: vec2f) -> vec4f {
|
|
107
|
+
var p = clamp(jq, vec2i(0), size - vec2i(1));
|
|
108
|
+
if (modes.x < 0.5) { p.x = ((jq.x % size.x) + size.x) % size.x; }
|
|
109
|
+
if (modes.y < 0.5) { p.y = ((jq.y % size.y) + size.y) % size.y; }
|
|
110
|
+
return textureLoad(map, origin + p, lE(idx), 0);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
|
|
@@ -135,21 +135,21 @@ return emission;
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
fn
|
|
138
|
+
fn aL(roughness: f32, anisotropy: f32) -> vec2f {
|
|
139
139
|
let alpha = roughness * roughness;
|
|
140
|
-
let
|
|
141
|
-
if (anisotropy == 0.0) { return vec2f(max(
|
|
142
|
-
let
|
|
143
|
-
let tp = alpha * sqrt(2.0 / (1.0 +
|
|
144
|
-
return max(vec2f(
|
|
140
|
+
let pZ = ROUGHNESS_MIN * ROUGHNESS_MIN;
|
|
141
|
+
if (anisotropy == 0.0) { return vec2f(max(pZ, alpha)); }
|
|
142
|
+
let cY = 1.0 - anisotropy;
|
|
143
|
+
let tp = alpha * sqrt(2.0 / (1.0 + cY * cY));
|
|
144
|
+
return max(vec2f(pZ), vec2f(tp, cY * tp));
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
fn
|
|
147
|
+
fn kV(instanceIndex: i32) -> vec3f {
|
|
148
148
|
if (instanceIndex < 0) { return vec3f(1.0); }
|
|
149
149
|
return instancesBuffer[instanceIndex * ${INSTANCE_VEC4_STRIDE} + 9].xyz;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
fn
|
|
152
|
+
fn getMaterial(
|
|
153
153
|
ma: ptr<function, OpenPbrResolvedMaterial>,
|
|
154
154
|
materialIndex: i32,
|
|
155
155
|
uv: vec2f,
|
|
@@ -230,11 +230,11 @@ if (USE_METALLIC_ROUGHNESS_MAPS) {
|
|
|
230
230
|
|
|
231
231
|
let mrtMapIndex = i32(matData.mrtMapIndex);
|
|
232
232
|
if (mrtMapIndex >= 0) {
|
|
233
|
-
let
|
|
233
|
+
let fO = sampleMap(
|
|
234
234
|
mrtMapIndex, getMapUvSet(mrtMapIndex, uv, uv1)
|
|
235
235
|
);
|
|
236
|
-
(*ma).baseMetalness *=
|
|
237
|
-
(*ma).specularRoughness *=
|
|
236
|
+
(*ma).baseMetalness *= fO.b;
|
|
237
|
+
(*ma).specularRoughness *= fO.g;
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
|
|
@@ -267,16 +267,16 @@ ${hasAnisotropyDirections ? /* wgsl */ `
|
|
|
267
267
|
(*ma).coatAnisotropyRotation = matData.coatAnisotropyRotation;
|
|
268
268
|
if (USE_ANISOTROPY_MAPS && matData.anisotropyMapIndex >= 0.0) {
|
|
269
269
|
let index = i32(matData.anisotropyMapIndex);
|
|
270
|
-
let
|
|
271
|
-
(*ma).specularAnisotropy *=
|
|
272
|
-
let direction =
|
|
270
|
+
let cR = sampleMap(index, getMapUvSet(index, uv, uv1));
|
|
271
|
+
(*ma).specularAnisotropy *= cR.b;
|
|
272
|
+
let direction = cR.rg * 2.0 - 1.0;
|
|
273
273
|
if (dot(direction, direction) > 1e-4) { (*ma).anisotropyDirection = normalize(direction); }
|
|
274
274
|
(*ma).anisotropyDirectionEnabled = true;
|
|
275
275
|
}
|
|
276
276
|
if (matData.specularAnisotropyModel > 0.5 && (*ma).specularAnisotropy > 0.0) {
|
|
277
|
-
let
|
|
278
|
-
(*ma).specularRoughness =
|
|
279
|
-
(*ma).specularAnisotropy =
|
|
277
|
+
let tX = fb(clamp((*ma).specularRoughness, 0.0, 1.0), (*ma).specularAnisotropy);
|
|
278
|
+
(*ma).specularRoughness = tX.x;
|
|
279
|
+
(*ma).specularAnisotropy = tX.y;
|
|
280
280
|
}
|
|
281
281
|
if ((*ma).anisotropyDirectionEnabled) {
|
|
282
282
|
let theta = matData.specularAnisotropyRotation;
|
|
@@ -288,57 +288,59 @@ let d = (*ma).anisotropyDirection;
|
|
|
288
288
|
|
|
289
289
|
|
|
290
290
|
if ((*ma).coatWeight > 0.0 && (*ma).coatRoughness > 0.0) {
|
|
291
|
-
let
|
|
292
|
-
let
|
|
291
|
+
let hJ = (*ma).specularRoughness * (*ma).specularRoughness;
|
|
292
|
+
let hK = (*ma).coatRoughness * (*ma).coatRoughness;
|
|
293
293
|
(*ma).specularRoughness = mix((*ma).specularRoughness,
|
|
294
|
-
pow(min(1.0,
|
|
294
|
+
pow(min(1.0, hJ * hJ + 2.0 * hK * hK), 0.25), (*ma).coatWeight);
|
|
295
295
|
}
|
|
296
296
|
${hasTransmission ? '' : /* wgsl */ `(*ma).transmissionWeight = 0.0;`}
|
|
297
297
|
${hasMetalness ? '' : /* wgsl */ `(*ma).baseMetalness = 0.0;`}
|
|
298
|
-
let color =
|
|
298
|
+
let color = kV(instanceIndex) * vertexColor;
|
|
299
299
|
(*ma).baseColor *= color;
|
|
300
300
|
if ((*ma).materialType == UNLIT) { (*ma).emission *= color; }
|
|
301
301
|
|
|
302
|
-
(*ma).
|
|
302
|
+
${caustics ? /* wgsl */ ` (*ma).causticRoughness = (*ma).specularRoughness;
|
|
303
|
+
(*ma).causticNormalMapped = matData.normalMapIndex >= 0.0;
|
|
304
|
+
` : ''} (*ma).specularRoughness = clamp((*ma).specularRoughness, ROUGHNESS_MIN, 1.0);
|
|
303
305
|
(*ma).baseMetalness = clamp((*ma).baseMetalness, 0.0, 1.0);
|
|
304
|
-
let specularAlpha =
|
|
306
|
+
let specularAlpha = aL((*ma).specularRoughness, (*ma).specularAnisotropy);
|
|
305
307
|
(*ma).alphaX = specularAlpha.x;
|
|
306
308
|
(*ma).alphaY = specularAlpha.y;
|
|
307
309
|
}
|
|
308
310
|
|
|
309
|
-
fn
|
|
311
|
+
fn oS(materialIndex: i32, uv: vec2f, normal: vec3f, dp1: vec3f, dp2: vec3f, oM: vec2f, oN: vec2f) -> vec3f {
|
|
310
312
|
let matData = materialsBuffer[materialIndex];
|
|
311
313
|
let normalMapIndex = i32(matData.normalMapIndex);
|
|
312
314
|
if (normalMapIndex >= 0) {
|
|
313
315
|
|
|
314
316
|
|
|
315
317
|
|
|
316
|
-
let
|
|
317
|
-
let
|
|
318
|
-
var dpdu =
|
|
319
|
-
var
|
|
320
|
-
let
|
|
321
|
-
if (
|
|
322
|
-
let
|
|
323
|
-
dpdu *=
|
|
324
|
-
|
|
318
|
+
let rX = cross(dp2, normal);
|
|
319
|
+
let rW = cross(normal, dp1);
|
|
320
|
+
var dpdu = rX * oM.x + rW * oN.x;
|
|
321
|
+
var tI = rX * oM.y + rW * oN.y;
|
|
322
|
+
let dT = max(dot(dpdu, dpdu), dot(tI, tI));
|
|
323
|
+
if (dT > 1e-12) {
|
|
324
|
+
let tQ = inverseSqrt(dT);
|
|
325
|
+
dpdu *= tQ;
|
|
326
|
+
tI *= tQ;
|
|
325
327
|
}
|
|
326
328
|
else {
|
|
327
329
|
|
|
328
330
|
|
|
329
|
-
let
|
|
331
|
+
let ob = select(
|
|
330
332
|
vec3f(0.0, 1.0, 0.0),
|
|
331
333
|
vec3f(0.0, 0.0, 1.0),
|
|
332
334
|
abs(normal.z) < 0.999
|
|
333
335
|
);
|
|
334
|
-
dpdu = normalize(cross(
|
|
335
|
-
|
|
336
|
+
dpdu = normalize(cross(ob, normal));
|
|
337
|
+
tI = cross(normal, dpdu);
|
|
336
338
|
}
|
|
337
339
|
|
|
338
340
|
var n = 2.0 * sampleMap(normalMapIndex, uv).rgb - 1.0;
|
|
339
341
|
n = normalize(vec3(n.xy * matData.normalMapScale, n.z));
|
|
340
342
|
|
|
341
|
-
let tbn = mat3x3(dpdu,
|
|
343
|
+
let tbn = mat3x3(dpdu, tI, normal);
|
|
342
344
|
|
|
343
345
|
return normalize(tbn * n);
|
|
344
346
|
} else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialBuffer.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/materialBuffer.wgsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,qDAAqD;AACrD,sDAAsD;AACtD,kFAAkF;AAElF,OAAO,EACL,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,UAAU,wBAAwB,CAAC,EACvC,uBAAuB,GAAG,IAAI,EAC9B,cAAc,GAAG,KAAK,EACtB,aAAa,GAAG,IAAI,EACpB,eAAe,GAAG,IAAI,EACtB,YAAY,GAAG,IAAI,KAOjB,EAAE;IACJ,MAAM,mBAAmB,GAAG,aAAa;QACvC,CAAC,CAAC,2CAA2C;QAC7C,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,mBAAmB,GAAG,aAAa;QACvC,CAAC,CAAC,UAAU,CAAC;yBACU,0BAA0B,CAAC,MAAM;;;8BAG5B,0BAA0B,CAAC,IAAI;;EAE3D;QACA,CAAC,CAAC,oBAAoB,CAAC;IAEzB,OAAO,UAAU,CAAC;;EAElB,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;CAOtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yCAuH0B,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B3D,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAkCc,sBAAsB,CAAC,YAAY;;;oCAG9B,sBAAsB,CAAC,KAAK;;;;;;EAMlE,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC;;EAEvC,mBAAmB;;EAEnB,mBAAmB,CAAC,iBAAiB,EAAE,MAAM,CAAC;;;;;;;;;;;;;;EAc9C,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC;;EAE3C,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC;;EAE3C,qBAAqB,CAAC,MAAM,CAAC;;EAE7B,mBAAmB,CAAC,eAAe,EAAE,MAAM,CAAC;;EAE9C,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;CAG7B,CAAC,CAAC,CAAC,EAAE;;EAEF,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC;;EAE/C,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC;;EAE3C,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC;;EAE/C,mBAAmB,CAAC,mBAAmB,EAAE,MAAM,CAAC;;EAEhD,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC;;EAEjD,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;;;;;;;EASb,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,iCAAiC;EACnE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmD9D,CAAC;AACF,CAAC;AAED,MAAM,kBAAkB,GAAG,wBAAwB,EAAE,CAAC;AAEtD,eAAe,kBAAkB,CAAC","sourcesContent":["import { simpleTextureSample, thinFilmTextureSample } from '../../materialTextureSlots.js';\nimport { INSTANCE_VEC4_STRIDE } from '../../bvhAccel.js';\nimport { mapAlphaUsageConstants } from '../../materialConstants.js';\n// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport {\n materialAlphaModeConstants\n} from '../../materialConstants.js';\n\nexport function createMaterialBufferWgsl({\n hasAnisotropyDirections = true,\n hasCoatNormals = false,\n hasSceneAlpha = true,\n hasTransmission = true,\n hasMetalness = true\n}: {\n hasSceneAlpha?: boolean;\n hasAnisotropyDirections?: boolean;\n hasCoatNormals?: boolean;\n hasTransmission?: boolean;\n hasMetalness?: boolean;\n} = {}) {\n const alphaModeAssignment = hasSceneAlpha\n ? '(*ma).alphaMode = i32(matData.alphaMode);'\n : '';\n const alphaModeResolution = hasSceneAlpha\n ? /* wgsl */ `\n if ((*ma).alphaMode == ${materialAlphaModeConstants.opaque}) {\n (*ma).alpha = 1.0;\n }\n else if ((*ma).alphaMode == ${materialAlphaModeConstants.mask}) {\n (*ma).alpha = select(0.0, 1.0, (*ma).alpha >= matData.alphaCutoff);\n }`\n : '(*ma).alpha = 1.0;';\n\n return /* wgsl */ `\n\n${hasAnisotropyDirections ? /* wgsl */ `fn gltf_anisotropy_to_openpbr(roughness: f32, strength: f32) -> vec2f {\n if (strength == 0.0) { return vec2f(roughness, 0.0); }\n let u = roughness * roughness;\n let a = u + (1.0 - u) * strength * strength;\n if (a == 0.0) { return vec2f(0.0); }\n return vec2f(pow((a*a + u*u) * 0.5, 0.25), clamp(1.0 - u/a, 0.0, 1.0));\n}\n` : /* wgsl */ ``}\n\nfn sRGBToLinear(c: vec3f) -> vec3f {\n return mix(pow(c * 0.9478672986 + 0.0521327014, vec3f(2.4)), c * 0.0773993808, vec3f(c < vec3f(0.04045)));\n}\n\nfn decodeMapColor(idx: i32, c: vec3f) -> vec3f {\n if (mapInfo[idx + NUM_MAPS * 2].y > 0.5) { return c; }\n return sRGBToLinear(c);\n}\n\nfn unpackMaterialIndex(val: i32) -> vec2f {\n return vec2f(f32(val >> 8), f32(val & 0xff) / 255.0);\n}\n\nfn getMapSize(idx: i32) -> vec2f {\n return mapInfo[idx].xy;\n}\n\nfn getMapLayer(idx: i32) -> i32 {\n return i32(floor(mapInfo[idx].z));\n}\n\nfn getMapOffset(idx: i32) -> vec2f {\n return vec2f(fract(mapInfo[idx].z), mapInfo[idx].w);\n}\n\nfn wrapMapCoordinate(value: f32, mode: f32) -> f32 {\n if (mode < 0.5) { return fract(value); }\n if (mode < 1.5) { return clamp(value, 0.0, 1.0); }\n return 1.0 - abs(1.0 - (value - 2.0 * floor(value * 0.5)));\n}\n\nfn wrappedMapUv(idx: i32, uv: vec2f) -> vec2f {\n let transform = mapInfo[idx + NUM_MAPS];\n let modes = mapInfo[idx + NUM_MAPS * 2].zw;\n let value = uv * transform.xy + transform.zw;\n return vec2f(wrapMapCoordinate(value.x, modes.x), wrapMapCoordinate(value.y, modes.y));\n}\n\nfn getMapUV(idx: i32, uv: vec2f) -> vec2f {\n let repeatedUv = wrappedMapUv(idx, uv);\n let atlasTexel = 1.0 / vec2f(textureDimensions(map).xy);\n let firstTexelCenter = getMapOffset(idx);\n let sourceExtent = getMapSize(idx) + atlasTexel;\n let sourceOrigin = firstTexelCenter - 0.5 * atlasTexel;\n let lastTexelCenter = firstTexelCenter + sourceExtent - atlasTexel;\n return clamp(\n sourceOrigin + repeatedUv * sourceExtent,\n firstTexelCenter,\n lastTexelCenter\n );\n}\n\nfn getMapUvSet(idx: i32, uv: vec2f, uv1: vec2f) -> vec2f {\n return select(uv, uv1, mapInfo[idx + NUM_MAPS * 2].x > 0.5);\n}\n\nfn sampleMap(idx: i32, uv: vec2f) -> vec4f {\n let size = vec2i(round(getMapSize(idx) * vec2f(textureDimensions(map).xy) + vec2f(1.0)));\n let texel = wrappedMapUv(idx, uv) * vec2f(size) - vec2f(0.5);\n let modes = mapInfo[idx + NUM_MAPS * 2].zw;\n // Repeat filtering must cross the logical image boundary, never another\n // atlas placement. Interior/clamped/mirrored footprints use hardware filtering.\n if ((size.x > 1 && modes.x < 0.5 && (texel.x < 0.0 || texel.x > f32(size.x - 1))) ||\n (size.y > 1 && modes.y < 0.5 && (texel.y < 0.0 || texel.y > f32(size.y - 1)))) {\n let base = vec2i(floor(texel));\n let weight = fract(texel);\n let origin = vec2i(round(getMapOffset(idx) * vec2f(textureDimensions(map).xy) - vec2f(0.5)));\n return mix(\n mix(loadMapTexel(idx, base, size, origin, modes), loadMapTexel(idx, base + vec2i(1, 0), size, origin, modes), weight.x),\n mix(loadMapTexel(idx, base + vec2i(0, 1), size, origin, modes), loadMapTexel(idx, base + vec2i(1, 1), size, origin, modes), weight.x), weight.y);\n }\n return textureSampleLevel(map, mapSampler, getMapUV(idx, uv), getMapLayer(idx), 0.0);\n}\n\nfn loadMapTexel(idx: i32, coordinate: vec2i, size: vec2i, origin: vec2i, modes: vec2f) -> vec4f {\n var p = clamp(coordinate, vec2i(0), size - vec2i(1));\n if (modes.x < 0.5) { p.x = ((coordinate.x % size.x) + size.x) % size.x; }\n if (modes.y < 0.5) { p.y = ((coordinate.y % size.y) + size.y) % size.y; }\n return textureLoad(map, origin + p, getMapLayer(idx), 0);\n}\n\n\nfn getMaterialEmission(materialIndex: i32, uv: vec2f, uv1: vec2f) -> vec3f {\n let matData = materialsBuffer[materialIndex];\n var emission = matData.emission;\n if (USE_EMISSIVE_MAPS) {\n let emissiveMapIndex = i32(matData.emissiveMapIndex);\n if (emissiveMapIndex >= 0) {\n emission *= decodeMapColor(emissiveMapIndex, sampleMap(\n emissiveMapIndex, getMapUvSet(emissiveMapIndex, uv, uv1)\n ).rgb);\n }\n }\n if (USE_COAT_WEIGHT_MAPS && matData.matType == 0.0) {\n let coatWeightMapIndex = i32(matData.coatWeightMapIndex);\n if (coatWeightMapIndex >= 0) {\n let coatWeight = clamp(matData.coatWeight, 0.0, 1.0) * sampleMap(\n coatWeightMapIndex, getMapUvSet(coatWeightMapIndex, uv, uv1)\n ).r;\n emission *= mix(vec3f(1.0), sqrt(max(matData.coatColor, vec3f(0.0))), coatWeight);\n }\n }\n return emission;\n}\n\n// OpenPBR 1.1.1: RMS-preserving GGX anisotropy, shared by base and coat.\nfn openpbr_roughness_to_alpha(roughness: f32, anisotropy: f32) -> vec2f {\n let alpha = roughness * roughness;\n let alphaMin = ROUGHNESS_MIN * ROUGHNESS_MIN;\n if (anisotropy == 0.0) { return vec2f(max(alphaMin, alpha)); }\n let complement = 1.0 - anisotropy;\n let alphaT = alpha * sqrt(2.0 / (1.0 + complement * complement));\n return max(vec2f(alphaMin), vec2f(alphaT, complement * alphaT));\n}\n\nfn getInstanceColor(instanceIndex: i32) -> vec3f {\n if (instanceIndex < 0) { return vec3f(1.0); }\n return instancesBuffer[instanceIndex * ${INSTANCE_VEC4_STRIDE} + 9].xyz;\n}\n\nfn getMaterial(\n ma: ptr<function, OpenPbrResolvedMaterial>,\n materialIndex: i32,\n uv: vec2f,\n uv1: vec2f,\n instanceIndex: i32,\n vertexColor: vec3f\n) {\n let matData = materialsBuffer[materialIndex];\n\n (*ma).baseColor = matData.color;\n (*ma).materialType = i32(matData.matType);\n (*ma).specularRoughness = matData.roughness;\n (*ma).baseMetalness = matData.metallic;\n (*ma).specularAnisotropy = clamp(matData.anisotropy, 0.0, 1.0);\n (*ma).emission = getMaterialEmission(materialIndex, uv, uv1);\n (*ma).inside = false;\n (*ma).specularIor = matData.ior;\n (*ma).transmissionWeight = matData.transmission;\n (*ma).thinWalled = matData.thin > 0.5;\n (*ma).bevel = matData.bevel;\n (*ma).transmissionDispersionScale = matData.dispersion;\n (*ma).dispersionAbbeNumber = max(matData.dispersionAbbeNumber, 1e-6);\n (*ma).mediumExtinction = max(matData.mediumExtinction, vec3f(0.0));\n (*ma).mediumScattering = max(matData.mediumScattering, vec3f(0.0));\n (*ma).mediumAnisotropy = clamp(matData.mediumAnisotropy, -1.0, 1.0);\n (*ma).mediumType = select(0, 1, max(max((*ma).mediumExtinction.x, (*ma).mediumExtinction.y), (*ma).mediumExtinction.z) > 0.0);\n (*ma).alpha = matData.alpha;\n ${alphaModeAssignment}\n\n (*ma).thinFilmThickness = matData.thinFilmThickness * 1000.0;\n (*ma).thinFilmIor = matData.thinFilmIor;\n (*ma).thinFilmWeight = select(0.0, clamp(matData.thinFilmWeight, 0.0, 1.0), HAS_THIN_FILM);\n (*ma).baseWeight = clamp(matData.baseWeight, 0.0, 1.0);\n (*ma).diffuseRoughness = clamp(matData.baseDiffuseRoughness, 0.0, 1.0);\n (*ma).specularWeight = max(matData.specularWeight, 0.0);\n (*ma).specularColor = max(matData.specularColor, vec3f(0.0));\n (*ma).subsurfaceWeight = select(0.0, clamp(matData.subsurfaceWeight, 0.0, 1.0), HAS_SUBSURFACE);\n (*ma).subsurfaceColor = max(matData.subsurfaceColor, vec3f(0.0));\n (*ma).transmissionColor = max(matData.transmissionColor, vec3f(0.0));\n (*ma).fuzzWeight = select(0.0, clamp(matData.fuzzWeight, 0.0, 1.0), HAS_FUZZ);\n (*ma).fuzzColor = max(matData.fuzzColor, vec3f(0.0));\n (*ma).fuzzRoughness = clamp(matData.fuzzRoughness, 0.0, 1.0);\n (*ma).coatWeight = select(0.0, clamp(matData.coatWeight, 0.0, 1.0), HAS_COAT);\n (*ma).coatColor = max(matData.coatColor, vec3f(0.0));\n (*ma).coatRoughness = clamp(matData.coatRoughness, ROUGHNESS_MIN, 1.0);\n (*ma).coatAnisotropy = clamp(matData.coatAnisotropy, 0.0, 1.0);\n (*ma).coatIor = max(matData.coatIor, 1.0);\n (*ma).coatDarkening = clamp(matData.coatDarkening, 0.0, 1.0);\n\n if (USE_DIFFUSE_MAPS) {\n let diffuseMapIndex = i32(matData.diffuseMapIndex);\n if (diffuseMapIndex >= 0) {\n // TODO textureSample is not supported in compute shader.\n let diffuse = sampleMap(\n diffuseMapIndex, getMapUvSet(diffuseMapIndex, uv, uv1)\n );\n // Material factors from THREE / glTF are already linear. Only color\n // textures need decoding from their stored sRGB values.\n (*ma).baseColor *= decodeMapColor(diffuseMapIndex, diffuse.rgb);\n\n // Map alpha to transmission\n if (matData.mapAlphaUsage == ${mapAlphaUsageConstants.transmission}) {\n (*ma).transmissionWeight = 1.0 - diffuse.a;\n }\n else if (matData.mapAlphaUsage == ${mapAlphaUsageConstants.alpha}) {\n (*ma).alpha *= diffuse.a;\n }\n }\n }\n\n ${simpleTextureSample('alphaMap', 'wgsl')}\n\n ${alphaModeResolution}\n\n ${simpleTextureSample('transmissionMap', 'wgsl')}\n\n if (USE_METALLIC_ROUGHNESS_MAPS) {\n // Metallic roughness transmission map index\n let mrtMapIndex = i32(matData.mrtMapIndex);\n if (mrtMapIndex >= 0) {\n let metallicRoughness = sampleMap(\n mrtMapIndex, getMapUvSet(mrtMapIndex, uv, uv1)\n );\n (*ma).baseMetalness *= metallicRoughness.b;\n (*ma).specularRoughness *= metallicRoughness.g;\n }\n }\n\n ${simpleTextureSample('roughnessMap', 'wgsl')}\n\n ${simpleTextureSample('metalnessMap', 'wgsl')}\n\n ${thinFilmTextureSample('wgsl')}\n\n ${simpleTextureSample('coatWeightMap', 'wgsl')}\n\n${hasCoatNormals ? /* wgsl */ `\n // Independent coat shading also applies when the coat has no normal map.\n (*ma).coatNormalEnabled = (*ma).coatWeight > 0.0 && (matData.normalMapIndex >= 0.0 || matData.coatNormalMapIndex >= 0.0);\n` : ''}\n\n ${simpleTextureSample('coatRoughnessMap', 'wgsl')}\n\n ${simpleTextureSample('fuzzColorMap', 'wgsl')}\n\n ${simpleTextureSample('fuzzRoughnessMap', 'wgsl')}\n\n ${simpleTextureSample('specularWeightMap', 'wgsl')}\n\n ${simpleTextureSample('specularColorMap', 'wgsl')}\n\n${hasAnisotropyDirections ? /* wgsl */ `\n (*ma).anisotropyDirection = vec2f(1.0, 0.0);\n (*ma).anisotropyDirectionEnabled = matData.specularAnisotropyRotation != 0.0;\n (*ma).coatAnisotropyRotation = matData.coatAnisotropyRotation;\n if (USE_ANISOTROPY_MAPS && matData.anisotropyMapIndex >= 0.0) {\n let index = i32(matData.anisotropyMapIndex);\n let texel = sampleMap(index, getMapUvSet(index, uv, uv1));\n (*ma).specularAnisotropy *= texel.b;\n let direction = texel.rg * 2.0 - 1.0;\n if (dot(direction, direction) > 1e-4) { (*ma).anisotropyDirection = normalize(direction); }\n (*ma).anisotropyDirectionEnabled = true;\n }\n if (matData.specularAnisotropyModel > 0.5 && (*ma).specularAnisotropy > 0.0) {\n let native = gltf_anisotropy_to_openpbr(clamp((*ma).specularRoughness, 0.0, 1.0), (*ma).specularAnisotropy);\n (*ma).specularRoughness = native.x;\n (*ma).specularAnisotropy = native.y;\n }\n if ((*ma).anisotropyDirectionEnabled) {\n let theta = matData.specularAnisotropyRotation;\n let d = (*ma).anisotropyDirection;\n (*ma).anisotropyDirection = vec2f(cos(theta)*d.x - sin(theta)*d.y, sin(theta)*d.x + cos(theta)*d.y);\n }\n\n` : /* wgsl */ ``}\n // OpenPBR 1.1.1: coat refraction broadens all base microfacet lobes.\n // Keep the zero-coat / smooth-coat paths byte-identical.\n if ((*ma).coatWeight > 0.0 && (*ma).coatRoughness > 0.0) {\n let baseRoughness2 = (*ma).specularRoughness * (*ma).specularRoughness;\n let coatRoughness2 = (*ma).coatRoughness * (*ma).coatRoughness;\n (*ma).specularRoughness = mix((*ma).specularRoughness,\n pow(min(1.0, baseRoughness2 * baseRoughness2 + 2.0 * coatRoughness2 * coatRoughness2), 0.25), (*ma).coatWeight);\n }\n ${hasTransmission ? '' : /* wgsl */ `(*ma).transmissionWeight = 0.0;`}\n ${hasMetalness ? '' : /* wgsl */ `(*ma).baseMetalness = 0.0;`}\n let color = getInstanceColor(instanceIndex) * vertexColor;\n (*ma).baseColor *= color;\n if ((*ma).materialType == UNLIT) { (*ma).emission *= color; }\n\n (*ma).specularRoughness = clamp((*ma).specularRoughness, ROUGHNESS_MIN, 1.0);\n (*ma).baseMetalness = clamp((*ma).baseMetalness, 0.0, 1.0);\n let specularAlpha = openpbr_roughness_to_alpha((*ma).specularRoughness, (*ma).specularAnisotropy);\n (*ma).alphaX = specularAlpha.x;\n (*ma).alphaY = specularAlpha.y;\n}\n\nfn getMatNormal(materialIndex: i32, uv: vec2f, normal: vec3f, dp1: vec3f, dp2: vec3f, duv1: vec2f, duv2: vec2f) -> vec3f {\n let matData = materialsBuffer[materialIndex];\n let normalMapIndex = i32(matData.normalMapIndex);\n if (normalMapIndex >= 0) {\n // http://www.thetenthplanet.de/archives/1180\n // TODO use tangent attribute\n // Compute co-tangent and co-bitangent vectors\n let dp2perp = cross(dp2, normal);\n let dp1perp = cross(normal, dp1);\n var dpdu = dp2perp * duv1.x + dp1perp * duv2.x;\n var dpdv = dp2perp * duv1.y + dp1perp * duv2.y;\n let gradientLengthSquared = max(dot(dpdu, dpdu), dot(dpdv, dpdv));\n if (gradientLengthSquared > 1e-12) {\n let invmax = inverseSqrt(gradientLengthSquared);\n dpdu *= invmax;\n dpdv *= invmax;\n }\n else {\n // Generated/triplanar UVs have no per-vertex UV derivatives. Build a\n // stable fallback basis instead of normalizing two zero vectors.\n let referenceAxis = select(\n vec3f(0.0, 1.0, 0.0),\n vec3f(0.0, 0.0, 1.0),\n abs(normal.z) < 0.999\n );\n dpdu = normalize(cross(referenceAxis, normal));\n dpdv = cross(normal, dpdu);\n }\n\n var n = 2.0 * sampleMap(normalMapIndex, uv).rgb - 1.0;\n n = normalize(vec3(n.xy * matData.normalMapScale, n.z));\n\n let tbn = mat3x3(dpdu, dpdv, normal);\n\n return normalize(tbn * n);\n } else {\n return normal;\n }\n}\n`;\n}\n\nconst materialBufferWgsl = createMaterialBufferWgsl();\n\nexport default materialBufferWgsl;\n"]}
|
|
1
|
+
{"version":3,"file":"materialBuffer.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/materialBuffer.wgsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,qDAAqD;AACrD,sDAAsD;AACtD,kFAAkF;AAElF,OAAO,EACL,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,UAAU,wBAAwB,CAAC,EACvC,uBAAuB,GAAG,IAAI,EAC9B,cAAc,GAAG,KAAK,EACtB,aAAa,GAAG,IAAI,EACpB,eAAe,GAAG,IAAI,EAAE,QAAQ,GAAG,KAAK,EACxC,YAAY,GAAG,IAAI,KAOjB,EAAE;IACJ,MAAM,mBAAmB,GAAG,aAAa;QACvC,CAAC,CAAC,2CAA2C;QAC7C,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,mBAAmB,GAAG,aAAa;QACvC,CAAC,CAAC,UAAU,CAAC;yBACU,0BAA0B,CAAC,MAAM;;;8BAG5B,0BAA0B,CAAC,IAAI;;EAE3D;QACA,CAAC,CAAC,oBAAoB,CAAC;IAEzB,OAAO,UAAU,CAAC;;EAElB,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;CAOtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yCAuH0B,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B3D,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAkCc,sBAAsB,CAAC,YAAY;;;oCAG9B,sBAAsB,CAAC,KAAK;;;;;;EAMlE,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC;;EAEvC,mBAAmB;;EAEnB,mBAAmB,CAAC,iBAAiB,EAAE,MAAM,CAAC;;;;;;;;;;;;;;EAc9C,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC;;EAE3C,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC;;EAE3C,qBAAqB,CAAC,MAAM,CAAC;;EAE7B,mBAAmB,CAAC,eAAe,EAAE,MAAM,CAAC;;EAE9C,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;CAG7B,CAAC,CAAC,CAAC,EAAE;;EAEF,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC;;EAE/C,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC;;EAE3C,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC;;EAE/C,mBAAmB,CAAC,mBAAmB,EAAE,MAAM,CAAC;;EAEhD,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC;;EAEjD,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;;;;;;;EASb,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,iCAAiC;EACnE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,4BAA4B;;;;;EAK7D,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;;CAEvB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CL,CAAC;AACF,CAAC;AAED,MAAM,kBAAkB,GAAG,wBAAwB,EAAE,CAAC;AAEtD,eAAe,kBAAkB,CAAC","sourcesContent":["import { simpleTextureSample, thinFilmTextureSample } from '../../materialTextureSlots.js';\nimport { INSTANCE_VEC4_STRIDE } from '../../bvhAccel.js';\nimport { mapAlphaUsageConstants } from '../../materialConstants.js';\n// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport {\n materialAlphaModeConstants\n} from '../../materialConstants.js';\n\nexport function createMaterialBufferWgsl({\n hasAnisotropyDirections = true,\n hasCoatNormals = false,\n hasSceneAlpha = true,\n hasTransmission = true, caustics = false,\n hasMetalness = true\n}: {\n hasSceneAlpha?: boolean;\n hasAnisotropyDirections?: boolean;\n hasCoatNormals?: boolean;\n hasTransmission?: boolean; caustics?: boolean;\n hasMetalness?: boolean;\n} = {}) {\n const alphaModeAssignment = hasSceneAlpha\n ? '(*ma).alphaMode = i32(matData.alphaMode);'\n : '';\n const alphaModeResolution = hasSceneAlpha\n ? /* wgsl */ `\n if ((*ma).alphaMode == ${materialAlphaModeConstants.opaque}) {\n (*ma).alpha = 1.0;\n }\n else if ((*ma).alphaMode == ${materialAlphaModeConstants.mask}) {\n (*ma).alpha = select(0.0, 1.0, (*ma).alpha >= matData.alphaCutoff);\n }`\n : '(*ma).alpha = 1.0;';\n\n return /* wgsl */ `\n\n${hasAnisotropyDirections ? /* wgsl */ `fn gltf_anisotropy_to_openpbr(roughness: f32, strength: f32) -> vec2f {\n if (strength == 0.0) { return vec2f(roughness, 0.0); }\n let u = roughness * roughness;\n let a = u + (1.0 - u) * strength * strength;\n if (a == 0.0) { return vec2f(0.0); }\n return vec2f(pow((a*a + u*u) * 0.5, 0.25), clamp(1.0 - u/a, 0.0, 1.0));\n}\n` : /* wgsl */ ``}\n\nfn sRGBToLinear(c: vec3f) -> vec3f {\n return mix(pow(c * 0.9478672986 + 0.0521327014, vec3f(2.4)), c * 0.0773993808, vec3f(c < vec3f(0.04045)));\n}\n\nfn decodeMapColor(idx: i32, c: vec3f) -> vec3f {\n if (mapInfo[idx + NUM_MAPS * 2].y > 0.5) { return c; }\n return sRGBToLinear(c);\n}\n\nfn unpackMaterialIndex(val: i32) -> vec2f {\n return vec2f(f32(val >> 8), f32(val & 0xff) / 255.0);\n}\n\nfn getMapSize(idx: i32) -> vec2f {\n return mapInfo[idx].xy;\n}\n\nfn getMapLayer(idx: i32) -> i32 {\n return i32(floor(mapInfo[idx].z));\n}\n\nfn getMapOffset(idx: i32) -> vec2f {\n return vec2f(fract(mapInfo[idx].z), mapInfo[idx].w);\n}\n\nfn wrapMapCoordinate(value: f32, mode: f32) -> f32 {\n if (mode < 0.5) { return fract(value); }\n if (mode < 1.5) { return clamp(value, 0.0, 1.0); }\n return 1.0 - abs(1.0 - (value - 2.0 * floor(value * 0.5)));\n}\n\nfn wrappedMapUv(idx: i32, uv: vec2f) -> vec2f {\n let transform = mapInfo[idx + NUM_MAPS];\n let modes = mapInfo[idx + NUM_MAPS * 2].zw;\n let value = uv * transform.xy + transform.zw;\n return vec2f(wrapMapCoordinate(value.x, modes.x), wrapMapCoordinate(value.y, modes.y));\n}\n\nfn getMapUV(idx: i32, uv: vec2f) -> vec2f {\n let repeatedUv = wrappedMapUv(idx, uv);\n let atlasTexel = 1.0 / vec2f(textureDimensions(map).xy);\n let firstTexelCenter = getMapOffset(idx);\n let sourceExtent = getMapSize(idx) + atlasTexel;\n let sourceOrigin = firstTexelCenter - 0.5 * atlasTexel;\n let lastTexelCenter = firstTexelCenter + sourceExtent - atlasTexel;\n return clamp(\n sourceOrigin + repeatedUv * sourceExtent,\n firstTexelCenter,\n lastTexelCenter\n );\n}\n\nfn getMapUvSet(idx: i32, uv: vec2f, uv1: vec2f) -> vec2f {\n return select(uv, uv1, mapInfo[idx + NUM_MAPS * 2].x > 0.5);\n}\n\nfn sampleMap(idx: i32, uv: vec2f) -> vec4f {\n let size = vec2i(round(getMapSize(idx) * vec2f(textureDimensions(map).xy) + vec2f(1.0)));\n let texel = wrappedMapUv(idx, uv) * vec2f(size) - vec2f(0.5);\n let modes = mapInfo[idx + NUM_MAPS * 2].zw;\n // Repeat filtering must cross the logical image boundary, never another\n // atlas placement. Interior/clamped/mirrored footprints use hardware filtering.\n if ((size.x > 1 && modes.x < 0.5 && (texel.x < 0.0 || texel.x > f32(size.x - 1))) ||\n (size.y > 1 && modes.y < 0.5 && (texel.y < 0.0 || texel.y > f32(size.y - 1)))) {\n let base = vec2i(floor(texel));\n let weight = fract(texel);\n let origin = vec2i(round(getMapOffset(idx) * vec2f(textureDimensions(map).xy) - vec2f(0.5)));\n return mix(\n mix(loadMapTexel(idx, base, size, origin, modes), loadMapTexel(idx, base + vec2i(1, 0), size, origin, modes), weight.x),\n mix(loadMapTexel(idx, base + vec2i(0, 1), size, origin, modes), loadMapTexel(idx, base + vec2i(1, 1), size, origin, modes), weight.x), weight.y);\n }\n return textureSampleLevel(map, mapSampler, getMapUV(idx, uv), getMapLayer(idx), 0.0);\n}\n\nfn loadMapTexel(idx: i32, coordinate: vec2i, size: vec2i, origin: vec2i, modes: vec2f) -> vec4f {\n var p = clamp(coordinate, vec2i(0), size - vec2i(1));\n if (modes.x < 0.5) { p.x = ((coordinate.x % size.x) + size.x) % size.x; }\n if (modes.y < 0.5) { p.y = ((coordinate.y % size.y) + size.y) % size.y; }\n return textureLoad(map, origin + p, getMapLayer(idx), 0);\n}\n\n\nfn getMaterialEmission(materialIndex: i32, uv: vec2f, uv1: vec2f) -> vec3f {\n let matData = materialsBuffer[materialIndex];\n var emission = matData.emission;\n if (USE_EMISSIVE_MAPS) {\n let emissiveMapIndex = i32(matData.emissiveMapIndex);\n if (emissiveMapIndex >= 0) {\n emission *= decodeMapColor(emissiveMapIndex, sampleMap(\n emissiveMapIndex, getMapUvSet(emissiveMapIndex, uv, uv1)\n ).rgb);\n }\n }\n if (USE_COAT_WEIGHT_MAPS && matData.matType == 0.0) {\n let coatWeightMapIndex = i32(matData.coatWeightMapIndex);\n if (coatWeightMapIndex >= 0) {\n let coatWeight = clamp(matData.coatWeight, 0.0, 1.0) * sampleMap(\n coatWeightMapIndex, getMapUvSet(coatWeightMapIndex, uv, uv1)\n ).r;\n emission *= mix(vec3f(1.0), sqrt(max(matData.coatColor, vec3f(0.0))), coatWeight);\n }\n }\n return emission;\n}\n\n// OpenPBR 1.1.1: RMS-preserving GGX anisotropy, shared by base and coat.\nfn openpbr_roughness_to_alpha(roughness: f32, anisotropy: f32) -> vec2f {\n let alpha = roughness * roughness;\n let alphaMin = ROUGHNESS_MIN * ROUGHNESS_MIN;\n if (anisotropy == 0.0) { return vec2f(max(alphaMin, alpha)); }\n let complement = 1.0 - anisotropy;\n let alphaT = alpha * sqrt(2.0 / (1.0 + complement * complement));\n return max(vec2f(alphaMin), vec2f(alphaT, complement * alphaT));\n}\n\nfn getInstanceColor(instanceIndex: i32) -> vec3f {\n if (instanceIndex < 0) { return vec3f(1.0); }\n return instancesBuffer[instanceIndex * ${INSTANCE_VEC4_STRIDE} + 9].xyz;\n}\n\nfn getMaterial(\n ma: ptr<function, OpenPbrResolvedMaterial>,\n materialIndex: i32,\n uv: vec2f,\n uv1: vec2f,\n instanceIndex: i32,\n vertexColor: vec3f\n) {\n let matData = materialsBuffer[materialIndex];\n\n (*ma).baseColor = matData.color;\n (*ma).materialType = i32(matData.matType);\n (*ma).specularRoughness = matData.roughness;\n (*ma).baseMetalness = matData.metallic;\n (*ma).specularAnisotropy = clamp(matData.anisotropy, 0.0, 1.0);\n (*ma).emission = getMaterialEmission(materialIndex, uv, uv1);\n (*ma).inside = false;\n (*ma).specularIor = matData.ior;\n (*ma).transmissionWeight = matData.transmission;\n (*ma).thinWalled = matData.thin > 0.5;\n (*ma).bevel = matData.bevel;\n (*ma).transmissionDispersionScale = matData.dispersion;\n (*ma).dispersionAbbeNumber = max(matData.dispersionAbbeNumber, 1e-6);\n (*ma).mediumExtinction = max(matData.mediumExtinction, vec3f(0.0));\n (*ma).mediumScattering = max(matData.mediumScattering, vec3f(0.0));\n (*ma).mediumAnisotropy = clamp(matData.mediumAnisotropy, -1.0, 1.0);\n (*ma).mediumType = select(0, 1, max(max((*ma).mediumExtinction.x, (*ma).mediumExtinction.y), (*ma).mediumExtinction.z) > 0.0);\n (*ma).alpha = matData.alpha;\n ${alphaModeAssignment}\n\n (*ma).thinFilmThickness = matData.thinFilmThickness * 1000.0;\n (*ma).thinFilmIor = matData.thinFilmIor;\n (*ma).thinFilmWeight = select(0.0, clamp(matData.thinFilmWeight, 0.0, 1.0), HAS_THIN_FILM);\n (*ma).baseWeight = clamp(matData.baseWeight, 0.0, 1.0);\n (*ma).diffuseRoughness = clamp(matData.baseDiffuseRoughness, 0.0, 1.0);\n (*ma).specularWeight = max(matData.specularWeight, 0.0);\n (*ma).specularColor = max(matData.specularColor, vec3f(0.0));\n (*ma).subsurfaceWeight = select(0.0, clamp(matData.subsurfaceWeight, 0.0, 1.0), HAS_SUBSURFACE);\n (*ma).subsurfaceColor = max(matData.subsurfaceColor, vec3f(0.0));\n (*ma).transmissionColor = max(matData.transmissionColor, vec3f(0.0));\n (*ma).fuzzWeight = select(0.0, clamp(matData.fuzzWeight, 0.0, 1.0), HAS_FUZZ);\n (*ma).fuzzColor = max(matData.fuzzColor, vec3f(0.0));\n (*ma).fuzzRoughness = clamp(matData.fuzzRoughness, 0.0, 1.0);\n (*ma).coatWeight = select(0.0, clamp(matData.coatWeight, 0.0, 1.0), HAS_COAT);\n (*ma).coatColor = max(matData.coatColor, vec3f(0.0));\n (*ma).coatRoughness = clamp(matData.coatRoughness, ROUGHNESS_MIN, 1.0);\n (*ma).coatAnisotropy = clamp(matData.coatAnisotropy, 0.0, 1.0);\n (*ma).coatIor = max(matData.coatIor, 1.0);\n (*ma).coatDarkening = clamp(matData.coatDarkening, 0.0, 1.0);\n\n if (USE_DIFFUSE_MAPS) {\n let diffuseMapIndex = i32(matData.diffuseMapIndex);\n if (diffuseMapIndex >= 0) {\n // TODO textureSample is not supported in compute shader.\n let diffuse = sampleMap(\n diffuseMapIndex, getMapUvSet(diffuseMapIndex, uv, uv1)\n );\n // Material factors from THREE / glTF are already linear. Only color\n // textures need decoding from their stored sRGB values.\n (*ma).baseColor *= decodeMapColor(diffuseMapIndex, diffuse.rgb);\n\n // Map alpha to transmission\n if (matData.mapAlphaUsage == ${mapAlphaUsageConstants.transmission}) {\n (*ma).transmissionWeight = 1.0 - diffuse.a;\n }\n else if (matData.mapAlphaUsage == ${mapAlphaUsageConstants.alpha}) {\n (*ma).alpha *= diffuse.a;\n }\n }\n }\n\n ${simpleTextureSample('alphaMap', 'wgsl')}\n\n ${alphaModeResolution}\n\n ${simpleTextureSample('transmissionMap', 'wgsl')}\n\n if (USE_METALLIC_ROUGHNESS_MAPS) {\n // Metallic roughness transmission map index\n let mrtMapIndex = i32(matData.mrtMapIndex);\n if (mrtMapIndex >= 0) {\n let metallicRoughness = sampleMap(\n mrtMapIndex, getMapUvSet(mrtMapIndex, uv, uv1)\n );\n (*ma).baseMetalness *= metallicRoughness.b;\n (*ma).specularRoughness *= metallicRoughness.g;\n }\n }\n\n ${simpleTextureSample('roughnessMap', 'wgsl')}\n\n ${simpleTextureSample('metalnessMap', 'wgsl')}\n\n ${thinFilmTextureSample('wgsl')}\n\n ${simpleTextureSample('coatWeightMap', 'wgsl')}\n\n${hasCoatNormals ? /* wgsl */ `\n // Independent coat shading also applies when the coat has no normal map.\n (*ma).coatNormalEnabled = (*ma).coatWeight > 0.0 && (matData.normalMapIndex >= 0.0 || matData.coatNormalMapIndex >= 0.0);\n` : ''}\n\n ${simpleTextureSample('coatRoughnessMap', 'wgsl')}\n\n ${simpleTextureSample('fuzzColorMap', 'wgsl')}\n\n ${simpleTextureSample('fuzzRoughnessMap', 'wgsl')}\n\n ${simpleTextureSample('specularWeightMap', 'wgsl')}\n\n ${simpleTextureSample('specularColorMap', 'wgsl')}\n\n${hasAnisotropyDirections ? /* wgsl */ `\n (*ma).anisotropyDirection = vec2f(1.0, 0.0);\n (*ma).anisotropyDirectionEnabled = matData.specularAnisotropyRotation != 0.0;\n (*ma).coatAnisotropyRotation = matData.coatAnisotropyRotation;\n if (USE_ANISOTROPY_MAPS && matData.anisotropyMapIndex >= 0.0) {\n let index = i32(matData.anisotropyMapIndex);\n let texel = sampleMap(index, getMapUvSet(index, uv, uv1));\n (*ma).specularAnisotropy *= texel.b;\n let direction = texel.rg * 2.0 - 1.0;\n if (dot(direction, direction) > 1e-4) { (*ma).anisotropyDirection = normalize(direction); }\n (*ma).anisotropyDirectionEnabled = true;\n }\n if (matData.specularAnisotropyModel > 0.5 && (*ma).specularAnisotropy > 0.0) {\n let native = gltf_anisotropy_to_openpbr(clamp((*ma).specularRoughness, 0.0, 1.0), (*ma).specularAnisotropy);\n (*ma).specularRoughness = native.x;\n (*ma).specularAnisotropy = native.y;\n }\n if ((*ma).anisotropyDirectionEnabled) {\n let theta = matData.specularAnisotropyRotation;\n let d = (*ma).anisotropyDirection;\n (*ma).anisotropyDirection = vec2f(cos(theta)*d.x - sin(theta)*d.y, sin(theta)*d.x + cos(theta)*d.y);\n }\n\n` : /* wgsl */ ``}\n // OpenPBR 1.1.1: coat refraction broadens all base microfacet lobes.\n // Keep the zero-coat / smooth-coat paths byte-identical.\n if ((*ma).coatWeight > 0.0 && (*ma).coatRoughness > 0.0) {\n let baseRoughness2 = (*ma).specularRoughness * (*ma).specularRoughness;\n let coatRoughness2 = (*ma).coatRoughness * (*ma).coatRoughness;\n (*ma).specularRoughness = mix((*ma).specularRoughness,\n pow(min(1.0, baseRoughness2 * baseRoughness2 + 2.0 * coatRoughness2 * coatRoughness2), 0.25), (*ma).coatWeight);\n }\n ${hasTransmission ? '' : /* wgsl */ `(*ma).transmissionWeight = 0.0;`}\n ${hasMetalness ? '' : /* wgsl */ `(*ma).baseMetalness = 0.0;`}\n let color = getInstanceColor(instanceIndex) * vertexColor;\n (*ma).baseColor *= color;\n if ((*ma).materialType == UNLIT) { (*ma).emission *= color; }\n\n${caustics ? /* wgsl */ ` (*ma).causticRoughness = (*ma).specularRoughness;\n (*ma).causticNormalMapped = matData.normalMapIndex >= 0.0;\n` : ''} (*ma).specularRoughness = clamp((*ma).specularRoughness, ROUGHNESS_MIN, 1.0);\n (*ma).baseMetalness = clamp((*ma).baseMetalness, 0.0, 1.0);\n let specularAlpha = openpbr_roughness_to_alpha((*ma).specularRoughness, (*ma).specularAnisotropy);\n (*ma).alphaX = specularAlpha.x;\n (*ma).alphaY = specularAlpha.y;\n}\n\nfn getMatNormal(materialIndex: i32, uv: vec2f, normal: vec3f, dp1: vec3f, dp2: vec3f, duv1: vec2f, duv2: vec2f) -> vec3f {\n let matData = materialsBuffer[materialIndex];\n let normalMapIndex = i32(matData.normalMapIndex);\n if (normalMapIndex >= 0) {\n // http://www.thetenthplanet.de/archives/1180\n // TODO use tangent attribute\n // Compute co-tangent and co-bitangent vectors\n let dp2perp = cross(dp2, normal);\n let dp1perp = cross(normal, dp1);\n var dpdu = dp2perp * duv1.x + dp1perp * duv2.x;\n var dpdv = dp2perp * duv1.y + dp1perp * duv2.y;\n let gradientLengthSquared = max(dot(dpdu, dpdu), dot(dpdv, dpdv));\n if (gradientLengthSquared > 1e-12) {\n let invmax = inverseSqrt(gradientLengthSquared);\n dpdu *= invmax;\n dpdv *= invmax;\n }\n else {\n // Generated/triplanar UVs have no per-vertex UV derivatives. Build a\n // stable fallback basis instead of normalizing two zero vectors.\n let referenceAxis = select(\n vec3f(0.0, 1.0, 0.0),\n vec3f(0.0, 0.0, 1.0),\n abs(normal.z) < 0.999\n );\n dpdu = normalize(cross(referenceAxis, normal));\n dpdv = cross(normal, dpdu);\n }\n\n var n = 2.0 * sampleMap(normalMapIndex, uv).rgb - 1.0;\n n = normalize(vec3(n.xy * matData.normalMapScale, n.z));\n\n let tbn = mat3x3(dpdu, dpdv, normal);\n\n return normalize(tbn * n);\n } else {\n return normal;\n }\n}\n`;\n}\n\nconst materialBufferWgsl = createMaterialBufferWgsl();\n\nexport default materialBufferWgsl;\n"]}
|