lecodes-cli 0.19.2 → 0.20.1
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 +1 -0
- package/dist/index.js +1324 -658
- package/package.json +9 -9
- package/runtime/materials/decal-relief.mat +178 -0
- package/runtime/materials/decal.mat +172 -0
- package/runtime/materials/lightmap-baked-lite.mat +175 -0
- package/runtime/materials/lightmap-baked.mat +176 -0
- package/runtime/materials/lightmap.mat +181 -0
- package/runtime/materials/lit.mat +43 -0
- package/runtime/materials/particles-quad.mat +171 -0
- package/runtime/materials/particles.mat +121 -0
- package/runtime/materials/shadow.mat +21 -0
- package/runtime/materials/terrain.mat +134 -0
- package/runtime/materials/unlit-transparent.mat +42 -0
- package/runtime/materials/unlit.mat +44 -0
- package/runtime/materials/video.mat +31 -0
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/assets/Roboto-Variable-DHm9jpd-.woff2 +0 -0
- package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/runtime/web/assets/basis-C64VHDVD.js +1 -0
- package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
- package/runtime/web/assets/createViewerLite-C_bkKXLg.js +852 -0
- package/runtime/web/assets/draco-BiISTFcR.js +118 -0
- package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/runtime/web/assets/index-BTB5KV9x.js +2 -0
- package/runtime/web/assets/mapViewImpl-B2JcES8l.js +810 -0
- package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +8 -0
- package/runtime/web/assets/neutral_ibl128-D-lzdkLN.ktx +0 -0
- package/runtime/web/assets/worker-Caf-yYEI.js +2 -0
- package/runtime/web/embed.html +32 -0
- package/runtime/web/embed.js +171 -0
- package/src/cmgenTool.ts +17 -9
- package/src/commands/app.ts +6 -1
- package/src/commands/appDesktop.ts +27 -4
- package/src/commands/appShared.ts +145 -3
- package/src/commands/appTemplates.ts +28 -4
- package/src/commands/assets.ts +3 -7
- package/src/commands/design.ts +9 -26
- package/src/commands/desktop.ts +9 -1
- package/src/commands/dev.ts +64 -0
- package/src/commands/projectTemplates.ts +17 -4
- package/src/commands/render.ts +9 -11
- package/src/commands/scene.ts +2 -6
- package/src/commands/shaders.ts +17 -1
- package/src/commands/shadersNew.ts +133 -0
- package/src/commands/test.ts +2 -1
- package/src/commands/thumbs.ts +3 -6
- package/src/commands/update.ts +42 -21
- package/src/desktopRenderer.ts +32 -2
- package/src/desktopScript.ts +1 -1
- package/src/dev/androidDev.ts +154 -0
- package/src/dev/devServer.ts +53 -6
- package/src/dev/webRunner.ts +22 -0
- package/src/index.ts +24 -4
- package/src/matcTool.ts +31 -19
- package/src/peerInstall.ts +160 -0
- package/src/peers.ts +48 -14
- package/src/projectEnv.ts +4 -0
- package/src/releases.ts +16 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Default particle material — one universal point-sprite shader for every particle system
|
|
2
|
+
// (SDK: Material.particles(), the default when `new Particles({...})` gets no material).
|
|
3
|
+
//
|
|
4
|
+
// Per-particle inputs come from the particles.cpp vertex stream:
|
|
5
|
+
// COLOR — tint (the color/dynamicColor curves), multiplied into the texture
|
|
6
|
+
// CUSTOM0 — x: size (world units, diameter), y: rotation (radians),
|
|
7
|
+
// z: opacity, w: flipbook frame index
|
|
8
|
+
// Per-system looks are uniforms (all default 0; Material.particles() primes them):
|
|
9
|
+
// sheetSize — (cols, rows) of the flipbook sheet the texture is cut into. The shader trusts
|
|
10
|
+
// both components ≥ 1 (no divide-by-zero guard here) — the SDK clamps; (1,1) =
|
|
11
|
+
// single image. A raw material instance MUST prime this before drawing.
|
|
12
|
+
// emissive — extra brightness multiplier for a glow look (0 = off)
|
|
13
|
+
// additive — 0 = alpha compositing (smoke), 1 = additive (fire/sparks); fractional blends mix.
|
|
14
|
+
// Works inside `blending: fade` because Filament blends premultiplied
|
|
15
|
+
// (ONE, ONE_MINUS_SRC_ALPHA): we premultiply rgb ourselves and scale down the
|
|
16
|
+
// written alpha, so dst attenuation fades out as `additive` rises.
|
|
17
|
+
// softness — radial falloff so an untextured particle is a soft round dot, not a square
|
|
18
|
+
// (baseColorMap is host-primed to 1×1 white; the SDK sets softness=0 with a map)
|
|
19
|
+
//
|
|
20
|
+
// Sizing: perspScale (viewportHeightPx / (2·tan(fov/2))) is auto-published by the engine in
|
|
21
|
+
// material-global slot 3 (scene.cpp updateShaderGlobalParams), so gl_PointSize = size·scale/depth
|
|
22
|
+
// gives a true world-space diameter. Object vertex domain: particles ride the emitter's transform.
|
|
23
|
+
|
|
24
|
+
material {
|
|
25
|
+
name : particles,
|
|
26
|
+
shadingModel : unlit,
|
|
27
|
+
parameters : [
|
|
28
|
+
{ type : sampler2d, name : baseColorMap },
|
|
29
|
+
{ type : float2, name : sheetSize, precision : high },
|
|
30
|
+
{ type : float, name : emissive },
|
|
31
|
+
{ type : float, name : additive },
|
|
32
|
+
{ type : float, name : softness },
|
|
33
|
+
{ type : float, name : depthFade }
|
|
34
|
+
],
|
|
35
|
+
// `custom` carries (size, rotation, opacity, FRAME) and the frame index feeds the atlas uv, so
|
|
36
|
+
// this varying must stay full precision — see the highp note in the fragment stage.
|
|
37
|
+
variables : [
|
|
38
|
+
{ name : custom, precision : high }
|
|
39
|
+
],
|
|
40
|
+
blending : fade,
|
|
41
|
+
culling : none,
|
|
42
|
+
requires: [ color, custom0 ]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
vertex {
|
|
46
|
+
void materialVertex(inout MaterialVertexInputs material) {
|
|
47
|
+
float4 viewPos = getViewFromWorldMatrix() * material.worldPosition;
|
|
48
|
+
float z = max(-viewPos.z, 1e-3);
|
|
49
|
+
gl_PointSize = getCustom0().x * getMaterialGlobal3().x / z;
|
|
50
|
+
material.custom = getCustom0();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fragment {
|
|
55
|
+
void material(inout MaterialInputs material) {
|
|
56
|
+
prepareMaterial(material);
|
|
57
|
+
|
|
58
|
+
// EVERYTHING on the atlas-uv path is explicitly `highp`. matc's `-p mobile` profile lowers
|
|
59
|
+
// unqualified floats to `mediump`, which Apple GPUs really do execute as fp16 (desktop GL
|
|
60
|
+
// and desktop browsers quietly run mediump at fp32, which is why this only showed on iOS).
|
|
61
|
+
// In fp16, `cell + uv` for the last column lands in [7,8) where the ULP is 0.0039; divided
|
|
62
|
+
// by 8 that is ~1 whole texel of a 2048px sheet, so the sprite visibly stair-steps — and it
|
|
63
|
+
// degrades with the cell index (column 7 quantizes ~8x coarser than column 0).
|
|
64
|
+
highp float2 uv = gl_PointCoord.xy;
|
|
65
|
+
|
|
66
|
+
highp float rot = variable_custom.y;
|
|
67
|
+
if (rot != 0.0) {
|
|
68
|
+
highp float co = cos(rot);
|
|
69
|
+
highp float si = sin(rot);
|
|
70
|
+
highp float2 p = uv - float2(0.5, 0.5);
|
|
71
|
+
uv = float2(co * p.x - si * p.y, si * p.x + co * p.y) + float2(0.5, 0.5);
|
|
72
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
|
73
|
+
discard;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
highp float2 sheet = materialParams.sheetSize;
|
|
78
|
+
highp float frame = floor(variable_custom.w);
|
|
79
|
+
// integer cell math — float `floor(frame / sheet.x)` lands one row early at every row start
|
|
80
|
+
// on the GPU (6 * (1/6) floors to 0); see particles-quad.mat
|
|
81
|
+
int sx = int(sheet.x + 0.5);
|
|
82
|
+
int fi = int(frame + 0.5);
|
|
83
|
+
int total_i = sx * int(sheet.y + 0.5);
|
|
84
|
+
fi = fi - (fi / total_i) * total_i;
|
|
85
|
+
highp float2 cell = float2(float(fi - (fi / sx) * sx), float(fi / sx));
|
|
86
|
+
highp float2 tuv = (cell + uv) / sheet;
|
|
87
|
+
|
|
88
|
+
float4 tex = texture(materialParams_baseColorMap, tuv);
|
|
89
|
+
float4 tint = getColor();
|
|
90
|
+
|
|
91
|
+
// soft round falloff from the (unrotated) sprite center
|
|
92
|
+
float radial = 1.0 - smoothstep(0.0, 0.5, length(gl_PointCoord.xy - float2(0.5, 0.5)));
|
|
93
|
+
float shape = mix(1.0, radial, saturate(materialParams.softness));
|
|
94
|
+
|
|
95
|
+
float alpha = tex.a * tint.a * variable_custom.z * shape;
|
|
96
|
+
|
|
97
|
+
// Soft particles (depthFade > 0, metres): fade the sprite out where it cuts into the scene
|
|
98
|
+
// geometry behind it. sampler0_structure is Filament's depth ("structure") buffer — bound
|
|
99
|
+
// to the colour pass by patch 0017 while creator-gl sees a drawn system with depthFade > 0
|
|
100
|
+
// (otherwise it is a 1x1 dummy, and this branch is off). The fragment is reprojected to
|
|
101
|
+
// render-target uv the way Filament's own SSR does (surface_light_indirect.fs), and both
|
|
102
|
+
// depths are linearized with the SSR linearizeDepth formula (reversed-Z, far at infinity).
|
|
103
|
+
// (not in the depth/shadow/picking variants: their per-view layout has no structure sampler)
|
|
104
|
+
#if !defined(VARIANT_DEPTH)
|
|
105
|
+
if (materialParams.depthFade > 0.0) {
|
|
106
|
+
highp vec3 wp = getWorldPosition();
|
|
107
|
+
highp vec4 clip = getClipFromWorldMatrix() * vec4(wp, 1.0);
|
|
108
|
+
highp vec2 suv = clip.xy * (0.5 / clip.w) + 0.5;
|
|
109
|
+
highp float sceneDepth = textureLod(sampler0_structure, uvToRenderTargetUV(suv), 0.0).r;
|
|
110
|
+
highp mat4 p = getViewFromClipMatrix();
|
|
111
|
+
highp float sceneZ = (sceneDepth * p[2].z + p[3].z) / max(sceneDepth * p[2].w + p[3].w, 1.0 / 16777216.0);
|
|
112
|
+
highp float fragZ = (getViewFromWorldMatrix() * vec4(wp, 1.0)).z;
|
|
113
|
+
// both are view-space z (negative ahead): fragZ - sceneZ = how far the scene is behind
|
|
114
|
+
alpha *= saturate((fragZ - sceneZ) / materialParams.depthFade);
|
|
115
|
+
}
|
|
116
|
+
#endif
|
|
117
|
+
float3 rgb = tex.rgb * tint.rgb * (1.0 + materialParams.emissive);
|
|
118
|
+
|
|
119
|
+
material.baseColor = float4(rgb * alpha, alpha * (1.0 - saturate(materialParams.additive)));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
material {
|
|
2
|
+
name : "Invisible shadow plane",
|
|
3
|
+
shadingModel : unlit,
|
|
4
|
+
shadowMultiplier : true,
|
|
5
|
+
blending : transparent,
|
|
6
|
+
parameters : [
|
|
7
|
+
// Color and opacity of the projected shadow (RGBA)
|
|
8
|
+
{
|
|
9
|
+
type : float4,
|
|
10
|
+
name : color
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
fragment {
|
|
16
|
+
void material(inout MaterialInputs material) {
|
|
17
|
+
prepareMaterial(material);
|
|
18
|
+
// baseColor defines the color and opacity of the final shadow
|
|
19
|
+
material.baseColor = materialParams.color;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// terrain — the splat-map ground material (docs/terrain-plan.md §1.5). Up to four PBR layers
|
|
2
|
+
// (albedo + optional normal map, per-layer tiling / roughness) blended by a control map's RGBA
|
|
3
|
+
// weights (one texel per height sample); a layer may sample triplanar (rock on cliffs). UV0 is the
|
|
4
|
+
// terrain's local XZ in metres (creator-gl/src/terrain.cpp writes it), so `tiling` reads as metres
|
|
5
|
+
// per repeat and the control map is addressed as (uv / cellSize + 0.5) / gridSize.
|
|
6
|
+
//
|
|
7
|
+
// Sampler budget: feature level 1 (every host, WebGL included) allows 9 samplers per material, so the
|
|
8
|
+
// normal maps come PACKED two per texture — normals01 = (layer 0 XY in RG, layer 1 XY in BA),
|
|
9
|
+
// normals23 likewise; Z is reconstructed. `lecodes assets` packs them; an unset pack (the shared
|
|
10
|
+
// 1x1 white) decodes to a flat normal, and normalScale 0 skips the read.
|
|
11
|
+
//
|
|
12
|
+
// Baked lighting: lightmap.mat's atlas block (R = sun visibility, G = AO on UV1 = the terrain's ONE
|
|
13
|
+
// atlas rect; the light volume for movers is not needed — a terrain never moves), so a baked level
|
|
14
|
+
// applies the atlas to this material directly, no swap. Every sampler defaults to the shared 1x1
|
|
15
|
+
// white (applyIdentityDefaults): an unset layer is white, an unset lightmap is "fully lit".
|
|
16
|
+
material {
|
|
17
|
+
name : terrain,
|
|
18
|
+
shadingModel : lit,
|
|
19
|
+
flipUV : false,
|
|
20
|
+
requires : [ uv0, uv1 ],
|
|
21
|
+
postLightingBlending : multiply,
|
|
22
|
+
parameters : [
|
|
23
|
+
{ type : sampler2d, name : control },
|
|
24
|
+
{ type : sampler2d, name : albedo0 },
|
|
25
|
+
{ type : sampler2d, name : albedo1 },
|
|
26
|
+
{ type : sampler2d, name : albedo2 },
|
|
27
|
+
{ type : sampler2d, name : albedo3 },
|
|
28
|
+
{ type : sampler2d, name : normals01 },
|
|
29
|
+
{ type : sampler2d, name : normals23 },
|
|
30
|
+
// metres per texture repeat, per layer
|
|
31
|
+
{ type : float4, name : tiling },
|
|
32
|
+
{ type : float4, name : roughness },
|
|
33
|
+
// normal-map strength per layer; 0 = the layer has no normal map
|
|
34
|
+
{ type : float4, name : normalScale },
|
|
35
|
+
// 1 = sample that layer triplanar in world space (its normal map is then skipped)
|
|
36
|
+
{ type : float4, name : triplanar },
|
|
37
|
+
// samples along X and Z
|
|
38
|
+
{ type : float2, name : gridSize },
|
|
39
|
+
{ type : float, name : cellSize },
|
|
40
|
+
{ type : float3, name : tint },
|
|
41
|
+
{ type : sampler2d, name : lightmap },
|
|
42
|
+
// the point lights' baked irradiance, sRGB(E / lightScale), same rect; lightScale 0 = none (the 9th sampler)
|
|
43
|
+
{ type : sampler2d, name : lightmapLight },
|
|
44
|
+
{ type : float, name : lightScale },
|
|
45
|
+
// the light store's curve: texel = sRGB(pow(E / lightScale, 1 / lightGamma)); 0/1 = linear (v2 bakes), 2 = the square-root store
|
|
46
|
+
{ type : float, name : lightGamma },
|
|
47
|
+
{ type : float4, name : lightmapST },
|
|
48
|
+
{ type : float, name : ambientScale },
|
|
49
|
+
{ type : float, name : sunStrength },
|
|
50
|
+
// how much of the baked ambient occlusion applies (1 = all)
|
|
51
|
+
{ type : float, name : bakedAo }
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fragment {
|
|
56
|
+
vec4 triplanarSample(sampler2D tex, vec3 p, vec3 bw, float s) {
|
|
57
|
+
return texture(tex, p.zy / s) * bw.x + texture(tex, p.xz / s) * bw.y + texture(tex, p.xy / s) * bw.z;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// `slot` 0 = this layer's normal XY sits in the pack's RG, 1 = in its BA
|
|
61
|
+
void splatLayer(sampler2D alb, sampler2D pack, float slot, float tiling, float nscale, float tri, float w,
|
|
62
|
+
vec2 uv, vec3 wp, vec3 bw, inout vec3 albedo, inout vec3 nrm) {
|
|
63
|
+
if (w <= 0.0) return;
|
|
64
|
+
float s = max(tiling, 1e-3);
|
|
65
|
+
if (tri > 0.5) {
|
|
66
|
+
albedo += triplanarSample(alb, wp, bw, s).rgb * w;
|
|
67
|
+
nrm += vec3(0.0, 0.0, 1.0) * w;
|
|
68
|
+
} else {
|
|
69
|
+
vec2 luv = uv / s;
|
|
70
|
+
albedo += texture(alb, luv).rgb * w;
|
|
71
|
+
if (nscale > 0.0) {
|
|
72
|
+
vec4 p = texture(pack, luv);
|
|
73
|
+
vec2 xy = (slot > 0.5 ? p.ba : p.rg) * 2.0 - 1.0;
|
|
74
|
+
xy *= nscale;
|
|
75
|
+
float z = sqrt(max(1.0 - dot(xy, xy), 0.0));
|
|
76
|
+
nrm += vec3(xy, z) * w;
|
|
77
|
+
} else {
|
|
78
|
+
nrm += vec3(0.0, 0.0, 1.0) * w;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void material(inout MaterialInputs material) {
|
|
84
|
+
vec2 uv = getUV0();
|
|
85
|
+
vec2 cuv = (uv / max(materialParams.cellSize, 1e-4) + 0.5) / max(materialParams.gridSize, vec2(1.0));
|
|
86
|
+
vec4 w = texture(materialParams_control, cuv);
|
|
87
|
+
float ws = w.r + w.g + w.b + w.a;
|
|
88
|
+
w = ws > 1e-4 ? w / ws : vec4(1.0, 0.0, 0.0, 0.0);
|
|
89
|
+
|
|
90
|
+
vec3 wp = getUserWorldPosition();
|
|
91
|
+
vec3 gn = getWorldGeometricNormalVector();
|
|
92
|
+
vec3 bw = abs(gn);
|
|
93
|
+
bw = bw / max(bw.x + bw.y + bw.z, 1e-4);
|
|
94
|
+
|
|
95
|
+
vec3 albedo = vec3(0.0);
|
|
96
|
+
vec3 nrm = vec3(0.0);
|
|
97
|
+
splatLayer(materialParams_albedo0, materialParams_normals01, 0.0, materialParams.tiling.x, materialParams.normalScale.x, materialParams.triplanar.x, w.r, uv, wp, bw, albedo, nrm);
|
|
98
|
+
splatLayer(materialParams_albedo1, materialParams_normals01, 1.0, materialParams.tiling.y, materialParams.normalScale.y, materialParams.triplanar.y, w.g, uv, wp, bw, albedo, nrm);
|
|
99
|
+
splatLayer(materialParams_albedo2, materialParams_normals23, 0.0, materialParams.tiling.z, materialParams.normalScale.z, materialParams.triplanar.z, w.b, uv, wp, bw, albedo, nrm);
|
|
100
|
+
splatLayer(materialParams_albedo3, materialParams_normals23, 1.0, materialParams.tiling.w, materialParams.normalScale.w, materialParams.triplanar.w, w.a, uv, wp, bw, albedo, nrm);
|
|
101
|
+
material.normal = normalize(nrm);
|
|
102
|
+
prepareMaterial(material);
|
|
103
|
+
|
|
104
|
+
material.baseColor = vec4(albedo * materialParams.tint, 1.0);
|
|
105
|
+
material.roughness = dot(materialParams.roughness, w);
|
|
106
|
+
material.metallic = 0.0;
|
|
107
|
+
|
|
108
|
+
// ---- baked lighting (lightmap.mat's atlas block) ----
|
|
109
|
+
vec3 n = gn;
|
|
110
|
+
vec2 luv = getUV1() * materialParams.lightmapST.xy + materialParams.lightmapST.zw;
|
|
111
|
+
vec2 lm = texture(materialParams_lightmap, luv).rg;
|
|
112
|
+
lm.g = mix(1.0, lm.g, materialParams.bakedAo);
|
|
113
|
+
material.ambientOcclusion = lm.g;
|
|
114
|
+
// the point lights' baked diffuse (lightmap.mat's emissive path; the terrain has no glTF emissive)
|
|
115
|
+
float lg = materialParams.lightGamma > 0.0 ? materialParams.lightGamma : 1.0;
|
|
116
|
+
vec3 baked = pow(texture(materialParams_lightmapLight, luv).rgb, vec3(lg)) * materialParams.lightScale;
|
|
117
|
+
material.emissive = vec4(material.baseColor.rgb * baked * (getExposure() / PI), 0.0);
|
|
118
|
+
|
|
119
|
+
float vis = mix(1.0, lm.r, materialParams.sunStrength);
|
|
120
|
+
vec3 sh = frameUniforms.iblSH[0].xyz
|
|
121
|
+
+ frameUniforms.iblSH[1].xyz * n.y + frameUniforms.iblSH[2].xyz * n.z + frameUniforms.iblSH[3].xyz * n.x
|
|
122
|
+
+ frameUniforms.iblSH[4].xyz * (n.y * n.x) + frameUniforms.iblSH[5].xyz * (n.y * n.z)
|
|
123
|
+
+ frameUniforms.iblSH[6].xyz * (3.0 * n.z * n.z - 1.0) + frameUniforms.iblSH[7].xyz * (n.z * n.x)
|
|
124
|
+
+ frameUniforms.iblSH[8].xyz * (n.x * n.x - n.y * n.y);
|
|
125
|
+
vec3 luma = vec3(0.2126, 0.7152, 0.0722);
|
|
126
|
+
float amb = max(dot(max(sh, 0.0), luma), 0.0) * frameUniforms.iblLuminance * materialParams.ambientScale * lm.g;
|
|
127
|
+
float nol = max(dot(n, frameUniforms.lightDirection), 0.0);
|
|
128
|
+
float sun = dot(frameUniforms.lightColorIntensity.rgb, luma) * frameUniforms.lightColorIntensity.w * nol / PI;
|
|
129
|
+
// the baked lamps ride the emissive slot the multiply scales too: same share on both sides
|
|
130
|
+
float lamp = dot(baked, luma) * (getExposure() / PI);
|
|
131
|
+
float k = (amb + sun * vis + lamp) / max(amb + sun + lamp, 1e-6);
|
|
132
|
+
material.postLightingColor = vec4(k, k, k, 1.0);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Unlit, ALPHA-BLENDED: the twin of unlit.mat for `Material.unlit({ transparent: true })`.
|
|
2
|
+
//
|
|
3
|
+
// Two differences from unlit.mat, and both are why this is a separate source rather than the same
|
|
4
|
+
// shader compiled twice — blending is baked in by matc (a MaterialInstance cannot change it):
|
|
5
|
+
//
|
|
6
|
+
// 1. baseColor is a float4, so the colour carries its own alpha (`color: "#ffffff80"`). The opaque
|
|
7
|
+
// material keeps a float3, where an alpha would be a lie.
|
|
8
|
+
// 2. the result is PREMULTIPLIED here. Filament's `blending : transparent` expects premultiplied
|
|
9
|
+
// source, and neither input is: creator-gl sends the colour as RgbaType::PREMULTIPLIED_sRGB,
|
|
10
|
+
// which only converts sRGB→linear and does NOT multiply (Color.h), and a decoded PNG is
|
|
11
|
+
// straight alpha too. So multiply once, at the end. (The pre-2026-08 unlit blended without
|
|
12
|
+
// this step, which is what made half-transparent textures read too bright at the edges.)
|
|
13
|
+
//
|
|
14
|
+
// Keep the colour × map maths in step with unlit.mat.
|
|
15
|
+
|
|
16
|
+
material {
|
|
17
|
+
name : unlit_transparent,
|
|
18
|
+
shadingModel : unlit,
|
|
19
|
+
parameters : [
|
|
20
|
+
// baseColor multiplies baseColorMap (both white-primed by the host — see lit.mat), alpha included
|
|
21
|
+
{
|
|
22
|
+
type : float4,
|
|
23
|
+
name : baseColor
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type : sampler2d,
|
|
27
|
+
name : baseColorMap
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
blending : transparent,
|
|
31
|
+
requires: [
|
|
32
|
+
uv0
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fragment {
|
|
37
|
+
void material(inout MaterialInputs material) {
|
|
38
|
+
prepareMaterial(material);
|
|
39
|
+
vec4 base = texture(materialParams_baseColorMap, getUV0()) * materialParams.baseColor;
|
|
40
|
+
material.baseColor = vec4(base.rgb * base.a, base.a);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Unlit (flat) material: baseColor × baseColorMap, OPAQUE.
|
|
2
|
+
//
|
|
3
|
+
// Opaque is the default for the same reason lit.mat is: a blended draw writes no depth, is sorted
|
|
4
|
+
// back-to-front by centre, and Filament drops it from the shadow pass (RenderPass.cpp's
|
|
5
|
+
// filterTranslucentObjects) — so a "flat colour" cube used to occlude nothing and cast no shadow.
|
|
6
|
+
// Alpha is meaningless here: baseColor is a float3 and the map's alpha channel is ignored.
|
|
7
|
+
//
|
|
8
|
+
// The blended twin is unlit-transparent.mat (float4 baseColor, premultiplied). It is a SEPARATE
|
|
9
|
+
// source, not a variant: blending has to be baked in at compile time (a MaterialInstance can't
|
|
10
|
+
// change it), and the two shaders differ in the colour type and the premultiply anyway. Keep an
|
|
11
|
+
// edit to the colour/map maths in step across both — they are ten lines each, side by side.
|
|
12
|
+
//
|
|
13
|
+
// baseColorMap is a plain sampler2d on EVERY target. Apple used to compile its own variant with a
|
|
14
|
+
// samplerExternal map (plus a `useBaseColorMap` bool to branch on), which made Material.unlit refuse
|
|
15
|
+
// an ordinary texture there — filament rejects a SAMPLER_2D bound to an external parameter. Camera
|
|
16
|
+
// passthrough has its own camera.mat / camera_obj.mat, so that split is gone: one source, one
|
|
17
|
+
// behaviour, and the flag with it (nothing in the SDK has emitted `useBaseColorMap` for a while).
|
|
18
|
+
|
|
19
|
+
material {
|
|
20
|
+
name : unlit,
|
|
21
|
+
shadingModel : unlit,
|
|
22
|
+
parameters : [
|
|
23
|
+
// baseColor multiplies baseColorMap (white-primed by the host) — see lit.mat
|
|
24
|
+
{
|
|
25
|
+
type : float3,
|
|
26
|
+
name : baseColor
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type : sampler2d,
|
|
30
|
+
name : baseColorMap
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
requires: [
|
|
34
|
+
uv0
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fragment {
|
|
39
|
+
void material(inout MaterialInputs material) {
|
|
40
|
+
prepareMaterial(material);
|
|
41
|
+
material.baseColor = texture(materialParams_baseColorMap, getUV0());
|
|
42
|
+
material.baseColor.rgb *= materialParams.baseColor;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Video material — samples the frame a media player hands the engine as a texture.
|
|
2
|
+
//
|
|
3
|
+
// The sampler is EXTERNAL because that is what the platforms which actually play video give us:
|
|
4
|
+
// Android a SurfaceTexture (GL_TEXTURE_EXTERNAL_OES), Apple an AVPlayerItemVideoOutput texture.
|
|
5
|
+
// Desktop OpenGL has no external samplers and uploads frames as ordinary RGBA8 instead — it has no
|
|
6
|
+
// video decode yet (parity `gl-media-texture`: desktop = todo), so the desktop build compiles this
|
|
7
|
+
// material only to keep one source per target; whoever wires video up there decides then whether
|
|
8
|
+
// the desktop blob needs its own sampler2d variant.
|
|
9
|
+
|
|
10
|
+
material {
|
|
11
|
+
name : video,
|
|
12
|
+
shadingModel : unlit,
|
|
13
|
+
parameters : [
|
|
14
|
+
{
|
|
15
|
+
type : samplerExternal,
|
|
16
|
+
name : baseColorMap
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
requires: [
|
|
20
|
+
uv0
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fragment {
|
|
25
|
+
void material(inout MaterialInputs material) {
|
|
26
|
+
prepareMaterial(material);
|
|
27
|
+
// inverseTonemapSRGB round-trips the View's tonemapper, so the decoded frame displays with
|
|
28
|
+
// its true colors instead of washed-out/over-bright.
|
|
29
|
+
material.baseColor.rgb = inverseTonemapSRGB(texture(materialParams_baseColorMap, getUV0()).rgb);
|
|
30
|
+
}
|
|
31
|
+
}
|