主题
Custom Shaders
Use this skill when the user asks to add a project-owned shader, apply a custom Technique, precompile selected variants, or recover missing variants from logs. Keep project resources separate from official engine shader caches.
Contract
- SCE shaders originate from Urho3D (Urho) and use an SCE-adapted bgfx compilation pipeline. Reuse Urho rendering concepts and GLSL effect algorithms, but use the current SCE headers, stage/input declarations and binding conventions as the authority. Familiarity with upstream Urho is useful context, not proof that upstream source compiles unchanged.
- Shader source and includes live below
res/Shaders/BLGL/. - Read engine examples and shared headers directly from the downloaded package at
<EditorRoot>/update/<current update domain>/res/_m/shaders/<package version>/shaders/BLGL/. For example, a master installation underE:/WasmSCEusesE:/WasmSCE/update/editor-master.spark.xd.com/res/_m/shaders/<package version>/shaders/BLGL/. Current package files are plain text and can be opened with ordinary file-reading tools. Select the package declared by the installation's resource version record, rather than guessing the highest downloaded directory or hardcoding a version. TheShared shader include cachecompilation log maps the GUI Editor's active source directory to its compiler cache; Headless needs an explicit matching include root. If BLGL is absent or unreadable, update the Editor resources and locate the declared package. - New Editors automatically search the project
res/Shaders/BLGL/first and the currently mounted sharedshaders/BLGL/second, for both explicit precompilation and PIE on-demand compilation. Varying definitions use the same order. There is no need to copy shared headers into every project. Shared paths and contents affect the project cache identity; reload after changes. Older Editors without this support may temporarily need headers copied from the current SCE package. Existing project copies still override shared headers after upgrading. - This pipeline accepts the SCE/bgfx
BLGL/dialect. The package's legacyGLSL/andHLSL/folders target different native Urho backends; they are reference sources rather than drop-in inputs for this pipeline. - A Technique XML selects
vs,ps, orcsnames and pass state; it is not shader source. - The project selection file is
editor/shaders.precompile.json. Each variant is identified bypath + stage + normalized defines + platforms. - Project
res/is already part of the normal project package. The extra step is generating bytecode before packaging; do not rebuild officialshadercacheextra. - Project compilation runs in the DX11 Editor, or in an owned ShaderCompile.exe child of a supporting Headless host. Both target Windows/Editor DX11, Android ESSL, and iOS Metal on Windows; this does not enable on-device compilation. Headless Shader compilation needs no login.
- Quality candidates map directly to
RENDER_QUALITY=0low,1medium,2high, and3full/adaptive. The extra-defines field remains the escape hatch for stage-specific macros such asCLUSTER,CLUSTER_VS,FOGOFWAR,NOT_SUPPORT_SRGB, andGAMMA_IN_SHADERING.
Workflow
- Require an open, ready project. In the GUI use
editor_get_context; in Headless useheadless_get_project_stateand the installed tool schemas. For Headless retain the full matching package including ShaderCompile.exe, provide the installed resource root and explicit shared package through repeatable--shader-include-root. Select that package from the installation resource record, not a guessed latest directory. See the Headless compile example. - When authoring source, first read the source contract and minimal example and the copyable example. Choose the target geometry/render path before adapting it. Put the
.glslsource, includes, and varying.def.scfiles underres/Shaders/BLGL/. Use a unique filename; cache output names are based on the shader basename. - Add or inspect a project Technique XML. Call
shader_validate_techniqueand fix missing source reports before compiling. - Call
shader_list_sourcesandshader_get_plan. Preserve the returned plan shape and useshader_save_planwithexpected_jsonwhen changing an existing plan. Do not silently invent a macro combination. - Call
shader_compile_projectwithoutapplyfirst. Review every returned job. Only after the user requested the write/compile operation, call it withapply: true. - Confirm that
res/Shaders/BLGL/Compiled/was replaced successfully. A failed compile must leave the previous complete output intact. - Start PIE/debug and use Runtime
material.probeorscenegraph.materialsto verify the actual Technique path, pass, shader defines, and render state.
After editing a source or include, stop PIE and reload the project if the next run still shows the old result. The current path is not live hot reload.
Standalone Compiler Integration
- Prefer the Editor window or MCP for project compilation. Editor calls the SCE shaderc library in-process, with include paths resolved through its resource mounts.
- Headless uses the same MCP plan and output semantics through an owned ShaderCompile.exe task process. It requires a DX11-capable Windows environment, keeps project sources ahead of shared includes, and commits only a complete validated batch. Do not invoke the internal task protocol manually or compile concurrently with project lifecycle/build/publish preparation/account switching. A failure or cancellation preserves the prior Compiled output; cleanup_pending requires owned shutdown cleanup before further work.
- A standalone caller of
bgfx::shaderc::CommandCompileShadermust explicitly pass repeated-iarguments for project and shared BLGL roots, plus the resolved--varyingdeffile path; it cannot discover the selected Editor package version itself. Preserve argument boundaries for paths with spaces. - Follow the guide's standalone compiler section for the adapted flags:
-cis processed stage source text,-sis the source path, and-fis the work directory. Upstream shaderc command examples cannot be pasted unchanged. - These are library argument semantics, not flags of the legacy batch modes of ShaderCompile.exe or PrecompileShader.exe. Use shader_compile_project for the Headless project task flow rather than inventing a compiler command or bypassing stage/output handling.
Source Authoring
- Treat the current shared package's
BLGL/*.glslas working engine examples: start withUnlit.glslfor basic texturing/color,LitSolid.glslfor conventional lighting,PBRLitSolid.glslfor PBR, orUnlitMeshParticle.glslfor mesh particles. Read the matching Technique/pass, defines, varying and vertex layout together; built-in conditional branches are not a complete minimal project by themselves. Use the copyable starter for the end-to-end resource and compile-plan setup. - Use
VS()/PS()withCOMPILEVS/COMPILEPSbranches. Put the varying.def.scinclude first, and declare stage$input/$outputconsistently with its semantics. Do not paste a standalonemain()ormainImage()shader unchanged. The compiler supplies stage/platform defines. - Use current shared headers (
Common/common.sh,urho3d_compatibility.sh,uniforms.sh,samplers.sh,transform.sh) as needed. Do not vendor upstream Urho headers to guess missing declarations. - Preserve the geometry path's transforms and inputs:
iModelMatrix,GetWorldPos(...),GetClipPos(...); static mesh, skinned mesh, instancing, Urho2D and fullscreen passes are not interchangeable. The starter covers static Position + UV0 geometry only, not a whitelist of supported custom shader targets. - Match bindings on both sides:
sDiffMapis materialdiffuse(slot 0);cMatDiffColoris material parameterMatDiffColor. Time iscElapsedTimein VS andcElapsedTimePSin PS. Verify declarations and runtime bindings before introducing other uniforms. - Keep coordinate/UV precision throughout declarations, constructors and varyings; handle input sRGB decoding separately from output Gamma as described below.
- Read the starter's GLSL, varying, Technique, material and initial plan together. Merge an existing project's plan, then add complete runtime-requested defines from observations. A successful compile does not establish correct geometry, pass selection or target-device appearance.
Mobile Coordinate And UV Precision
SCE's shader compilation can lower ordinary float / vec2/3/4 to half precision. Do not assume that writing float in the source guarantees 32-bit arithmetic on the target device. In this shader dialect, hvec2/3/4 denotes high precision, not half precision.
- Keep vertex positions, UV calculations, and their precision-sensitive intermediate values in
hvec2/3/4. Check the corresponding inputs and varyings in.def.scand both shader stages; converting an already-rounded low-precision result tohveccannot restore lost detail. - Use
hvec2_init/hvec3_init/hvec4_initwhen constructing these vectors. AvecNconstructor can introduce low precision before assignment to anhvecNvariable. - Retain lower precision for values such as colors where the effect tolerates it. Do not promote every shader variable as the default fix.
The platforms do not enforce low precision identically:
| Target | Relevant precision behavior |
|---|---|
| iOS Metal | Low-precision translation produces explicit half types; 16-bit rounding can become visible. |
| Android ESSL | Low-precision intent commonly becomes mediump, a minimum precision requirement; the driver may execute at higher precision. |
| Windows DX11 | half/min16float does not guarantee 16-bit execution; hardware and drivers may use higher precision. |
A slowly changing position can round to the same value across several frames and then jump; UV rounding can cause texture shimmer. This can look like animation frame skipping even when animation updates and FPS are normal. A successful DX11 Editor preview or one Android device does not establish iOS or all-device correctness.
For mobile-only jitter, compare the default Technique with the custom Technique on the same object and device, inspect position/UV precision, then recompile the affected platform variants and verify that the device uses the new project bytecode. When explaining why Android or PC looks normal, distinguish the known compiler rules from the actual shader output and device behavior; do not assume every Android GPU promotes mediump to 32 bits. If changing precision does not resolve it, continue checking animation timing and rendering rather than treating precision as a confirmed cause.
Recover Missing Variants From Logs
Call shader_scan_missing_variants with the newest relevant Editor/client log paths. It extracts:
Compile Shader, vsDefines=..., psDefines=...Success Compile: Shader[...] Type[...] Defines[...]Failed Compile: Shader[...] Type[...] Defines[...]No Compile Result ...Could not find resource shaders/blgl/...
Treat shader, stage, defines, missing, and evidence as observations, not guesses. A pair record without a shader name must be correlated with shader_validate_technique, material data, or Runtime material.probe before it is added to the plan. Normalize defines only by the tool's returned value; do not remove feature macros because they look uncommon.
When missing_resources is returned, first determine whether the path belongs to the shared Shader resource package. Do not copy a shared include into a project merely to silence the log.
Recommended loop:
text
shader_scan_missing_variants
-> correlate shader/stage with Technique or material
-> shader_save_plan
-> shader_compile_project (dry-run)
-> shader_compile_project { apply: true }
-> PIE + material.probeHardware And Software sRGB Variants
NOT_SUPPORT_SRGB selects software sRGB-to-linear decoding in the pixel shader when hardware sampling does not provide it for the color texture. Standard shaders use GammaToLinearSpace() on the sampled color in this branch. It compensates for missing hardware decoding; it does not disable color-space handling or change coordinate precision.
- Current clients detect linear texture support and hardware sRGB sampling separately for each device and texture format. Android ASTC 5x5/6x6 can use hardware sRGB; do not assume that Android or ASTC requires
NOT_SUPPORT_SRGB. A texture declared sRGB uses hardware decoding when its format supports it, and the corresponding shader should not decode that sample again. - Mobile settings use ASTC 5x5 sRGB capability as the default software-resolve decision for passes that opt into it. Scene particles instead use the bound diffuse texture's declared color space and actual format support. Other custom passes must be checked against their actual runtime defines; the engine does not automatically supply software decoding for every shader or texture slot.
- Search native startup logs for INFO-level
[TextureCapabilities] format=... linear=... srgb=....srgb=1reports hardware sRGB support for that format, whilelinear=1only reports linear texture availability. The retained linear ASTC 5x5/6x6 compatibility fallback does not force sRGB support.[TextureProbe]reports ASTC probe failures andkeepLinearAstc; correlate these with the capability results. Textures_rgbalone is its declared color space, not proof of hardware decoding or of the requested shader variant. - Check software variants when a device reports a missing pixel shader while the DX11 Editor preview works. Preserve the full observed pixel defines, including quality and other feature macros. For a shader used across devices, keep the ordinary hardware-sRGB variant and the software variant when runtime paths require both; one device reporting
srgb=1does not justify deleting software variants needed by other devices, formats, or older clients. Add observed combinations through the scan/plan/compile workflow, repackage the project output, and verify the target client loads it. Do not force the macro into the Technique, add it to every platform or vertex stage without evidence, or remove it from a failed lookup to select a different variant. - A custom shader must implement the decoding branch; adding a compile define alone cannot supply missing conversion code. Decode only sRGB color samples that need it, preserve alpha, and keep linear data textures such as normals and masks out of this conversion. Avoid decoding again when hardware has already converted the sample.
GAMMA_IN_SHADERINGhandles linear-to-Gamma output and is independent of input decoding. A runtime combination may need both macros. Preserve that combination when observed; do not substitute one macro for the other or remove either merely to make the cache lookup succeed.
Applying A Custom Technique
Use a project-unique logical path, for example Editor/Techniques/MyEffect.xml, and assign that path through the material API or material resource. Do not shadow an EngineRes/ or official Editor/ Technique while diagnosing a project shader. If the object is invisible, check the requested RenderPath pass and material state before changing GLSL. material.probe is the runtime authority; XML inspection alone cannot prove that the client loaded the intended Technique.
Safety Boundaries
- Do not compile or overwrite
Compiledfrom a failed or partial job. - Do not treat a saved platform checkbox as proof that bytecode exists.
- Do not expand all possible defines into a Cartesian product; compile combinations observed in materials, Techniques, code, or logs.
- Use a full GUI Editor or supporting Headless host with the target project ready; independent
TriggerMcpHostdoes not provide project Shader tools. Prefer the user's already-open target-project GUI Editor unless the user explicitly requests isolation. With no open GUI, reuse a Headless session or start one for independent precompilation. Inspect capabilities and schemas, retain the matching full package and explicitly configure installed shared includes as described above; Shader precompilation does not require login.