Skip to content

refactor: migrate all shaders from raw GLSL to ShaderLab format#347

Open
zhuxudong wants to merge 14 commits intogalacean:dev/2.0from
zhuxudong:refactor/glsl-to-shaderlab
Open

refactor: migrate all shaders from raw GLSL to ShaderLab format#347
zhuxudong wants to merge 14 commits intogalacean:dev/2.0from
zhuxudong:refactor/glsl-to-shaderlab

Conversation

@zhuxudong
Copy link
Copy Markdown
Member

@zhuxudong zhuxudong commented Apr 20, 2026

Summary

  • Convert all 17 shader files from raw GLSL (Shader.create(name, vs, fs)) to ShaderLab format (Shader.create(shaderLabSource))
  • Replace attribute/varying/uniform with struct Attributes/Varyings and bare declarations
  • Replace #include <xxx> angle-bracket macros with explicit calculateBlendShape() / getSkinMatrix() calls
  • Replace old include paths with engine ShaderLibrary paths ("Common/Common.glsl", "Skin/Skin.glsl", etc.)
  • Fix Shader.find("pbr")Shader.find("PBR") and PBR pass index passes[0]passes[2]
  • Fix advanced-shader (Eye/SSS/Hair) include paths
  • Consolidate separate .glsl files into .ts ShaderLab strings
  • Delete 12 stale files (.glsl, global.d.ts, vertex.ts, fragment.ts)
  • Keep render states in TS material code, not in shader declarations
  • BakePBRMaterial: rewrite using #include "PBR/ForwardPassPBR.glsl" with lightmap extension

Dependencies

Test plan

  • PlainColor/Icon/Grid/Wireframe/TBN 材质渲染正常
  • Outline 高亮、FrameBuffer Picker 拾取正常
  • Line/Dash 线条渲染正常
  • Water/Waterfall/WaterRipple 水面效果正常
  • PlanarShadow 平面阴影正常
  • SkeletonViewer 骨骼可视化正常
  • BakePBR lightmap 渲染正常
  • BoxSelection 框选正常

---

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added digital human shader materials: Eye, Hair, and Subsurface Scattering (SSS)
* Added Grid shader for visual assistance
* Enhanced water effect shaders with advanced rendering capabilities

* **Improvements**
* Modernized build system with optimized shader asset handling
* Improved build reliability through dependency-aware compilation ordering
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Convert all shader code to ShaderLab syntax:
- Wrap in Shader/SubShader/Pass structure
- Replace attribute/varying/uniform with struct Attributes/Varyings
- Replace #include <xxx> macros with explicit vertex transform code
- Replace old #include paths with engine ShaderLibrary paths
- Change Shader.create(name, vs, fs) to Shader.create(shaderLabSource)
- Consolidate separate .glsl files into .ts ShaderLab strings
- Fix advanced-shader include paths for future extension use
- Keep render states in TS material code (not in shader)

Deleted: 10 .glsl files, 4 global.d.ts, bake-pbr vertex/fragment.ts
BakePBRMaterial skipped (TODO: full PBR pipeline migration)
…igration

- Restore global.d.ts for *.shader and *.wasm module declarations
- Add ts-ignore for ShaderPass single-arg constructor (engine not yet published)
- Update AssetType.Texture2D to AssetType.Texture to match engine API
…ions

- PlanarShadowShaderFactory: fix lowercase "pbr" to "PBR"
- PlainColorMaterial, FramebufferPicker, BoxSelectionSSMaterial:
  add explicit struct Varyings declaration
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Shader sources are migrated from inline GLSL embedded in TypeScript files to external .gsp shader assets. A new shader precompilation pipeline using @galacean/engine-shader-compiler is introduced, with build scripts updated across multiple packages and Rollup configured to use the new compiler plugin instead of string/glslify plugins.

Changes

Cohort / File(s) Summary
Root Build System
package.json, rollup.config.mjs
Added precompile npm script, new dev dependency @galacean/engine-shader-compiler, removed rollup-plugin-glslify and rollup-plugin-string. Rollup config now uses shaderCompiler() plugin, implements topological package sort by dependencies, and supports optional ./sources subpath exports.
Material Shader Refactoring
packages/custom-material/src/bake-pbr/*, packages/custom-material/src/*/...Material.ts, packages/custom-material/src/water/*, packages/custom-material/src/grid/GridMaterial.ts, packages/custom-material/src/plain-color/PlainColorMaterial.ts, packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts
Removed inline vertex/fragment shader definitions; materials now import shader sources from external .gsp assets and use conditional Shader.find() || Shader.create() pattern.
Control/Gizmo/Framebuffer Shader Migration
packages/controls/src/box-selection/BoxSelectionSSMaterial.ts, packages/gizmo/src/icon/IconMaterial.ts, packages/framebuffer-picker/src/FramebufferPicker.ts, packages/outline/src/OutlineManager.ts
Replaced inline GLSL with external shader module imports; updated shader registration to idempotent lookup-or-create pattern.
Geometry Sketch Material Updates
packages/geometry-sketch/src/material/TBNMaterial.ts, packages/geometry-sketch/src/material/WireframeMaterial.ts, packages/geometry-sketch/src/material/GeometryShader.ts
Migrated shader sources to external modules; removed exported geometry texture definitions and replaced inline shader construction with lookup-based initialization.
Lines & Skeleton Viewer Shaders
packages/lines/src/line/material/dashShader.ts, packages/lines/src/line/material/lineShader.ts, packages/skeleton-viewer/src/SkeletonViewer.ts
Converted inline shader definitions to external asset imports; applied conditional registration pattern.
New Shader Asset Files (.gsp)
packages/custom-material/libs/bake-pbr/BakePBR.gsp, packages/custom-material/libs/advanced-shader/eye/Eye.gsp, packages/custom-material/libs/advanced-shader/hair/Hair.gsp, packages/custom-material/libs/advanced-shader/sss/SSS.gsp, packages/custom-material/libs/grid/Grid.gsp, packages/custom-material/libs/plain-color/PlainColor.gsp, packages/custom-material/libs/planar-shadow/PlanarShadow.gsp, packages/custom-material/libs/planar-shadow/PlanarShadowOnly.gsp, packages/custom-material/libs/water/*
Created JSON-defined shader assets with vertex/fragment shader definitions, supporting features like skinning, blendshapes, PBR lighting, shadow mapping, and advanced material effects (clear-coat, anisotropy, iridescence, transmission, SSS).
Additional Shader Assets
packages/controls/libs/box-selection/BoxSelection.gsp, packages/framebuffer-picker/libs/FramebufferPickerColor.gsp, packages/geometry-sketch/libs/material/TBN.gsp, packages/geometry-sketch/libs/material/Wireframe.gsp, packages/gizmo/libs/icon/Icon.gsp, packages/lines/libs/line/material/Dash.gsp, packages/lines/libs/line/material/Line.gsp, packages/outline/libs/OutlinePostprocess.gsp, packages/outline/libs/OutlineReplace.gsp, packages/skeleton-viewer/libs/SkeletonViewer.gsp
New modular shader definitions for controls, effects, visualization, and rendering pipelines with configurable vertex/fragment logic.
Library Index & Type Declarations
packages/*/libs/index.ts, packages/*/libs/global.d.ts, packages/*/src/global.d.ts
Added auto-generated index.ts files re-exporting shader sources; introduced ambient TypeScript module declarations for *.shader and *.gsp imports typed as string and object respectively.
Package Configuration Updates
packages/*/package.json, packages/*/tsconfig.json
Added precompile npm scripts to all affected packages; updated custom-material/package.json with exports field for "." and "./sources" subpaths; added trailing newlines to tsconfig.json files.
Source Consolidation
packages/custom-material/src/sources.ts, packages/custom-material/libs/index.ts
Created new modules to centralize re-exports of shader source imports for downstream consumption and editor tooling.
Icon Asset Resource Loading
packages/gizmo/src/icon/Icon.ts
Changed resource manager loader from AssetType.Texture2D to AssetType.Texture for URL-based texture assignment.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Shaders hopped from files to assets neat,
No more inline strings in the TypeScript seat,
Precompiled pipelines dance with grace,
Build systems now have a faster pace,
Modular, crisp, the new shader space! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'refactor: migrate all shaders from raw GLSL to ShaderLab format' directly and concisely describes the main change: converting shader definitions from raw GLSL to ShaderLab format across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/gizmo/src/icon/Icon.ts (1)

60-71: ⚠️ Potential issue | 🟠 Major

Unhandled rejection and stale-resolver race in async texture load.

Two concerns on the URL branch:

  1. The promise has no .catch, so a failed load becomes an unhandled rejection with no recovery or diagnostic.
  2. If texture is reassigned (e.g., URL → different URL, or URL → Texture2D) before the previous load resolves, the stale resolver will still run and overwrite _material.baseTexture with the obsolete texture. Guard the assignment against this._texture === value at resolve time.
🛡️ Proposed fix
       } else {
-        this.engine.resourceManager.load({ url: value, type: AssetType.Texture }).then((texture: Texture2D) => {
-          this._material.baseTexture = texture;
-        });
+        this.engine.resourceManager
+          .load<Texture2D>({ url: value, type: AssetType.Texture })
+          .then((texture: Texture2D) => {
+            // Ignore stale result if `texture` was reassigned in the meantime.
+            if (this._texture !== value) return;
+            this._material.baseTexture = texture;
+          })
+          .catch((err) => {
+            console.error(`Icon failed to load texture: ${value}`, err);
+          });
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/gizmo/src/icon/Icon.ts` around lines 60 - 71, The texture setter's
async URL branch currently lacks error handling and can be conditionally
overwritten by stale resolves; update the URL branch in the set texture(value:
string | Texture2D) method to (1) capture the expected value (e.g., const
expected = value) before calling engine.resourceManager.load({ url: value, type:
AssetType.Texture }) and in the .then handler only assign
this._material.baseTexture = texture if this._texture === expected, and (2)
attach a .catch to the promise to log or handle load errors (use process/error
logger or throw as appropriate) to avoid unhandled rejections; ensure the same
guard is used if converting to a Texture2D synchronously when value instanceof
Texture2D.
🧹 Nitpick comments (13)
packages/controls/src/box-selection/BoxSelectionSSMaterial.ts (1)

20-24: Consider initializing Varyings before returning from vert.

Line 21 creates Varyings v and returns it (Line 23) without assigning v._placeholder. While the field is not used in the fragment shader, explicitly initializing struct members before return is a defensive programming practice that can prevent portability issues on stricter GLSL backends.

Suggested improvement
       Varyings vert(Attributes attr) {
         Varyings v;
+        v._placeholder = 0.0;
         gl_Position = vec4(attr.POSITION, 1.0);
         return v;
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/controls/src/box-selection/BoxSelectionSSMaterial.ts` around lines
20 - 24, The Varyings struct instance 'v' in the vertex function 'vert' is
returned without initializing its member(s); initialize v._placeholder (or all
Varyings fields) before returning from vert to ensure defined behavior across
GLSL backends—locate the function vert and the local variable v in
BoxSelectionSSMaterial.ts and set v._placeholder (or zero/appropriate default
for each field) prior to the return statement.
packages/geometry-sketch/src/material/TBNMaterial.ts (2)

14-17: Consolidate uniform declarations at the top of the Pass.

material_BaseColor is declared on Line 87 between vert and frag, while the other uniforms (u_lineScale, camera_VPMat, u_worldMatrix, u_worldNormal) are grouped at Lines 14–17. Moving material_BaseColor up with the rest keeps uniform declarations co-located and matches the pattern used elsewhere in the PR.

♻️ Proposed grouping
       float u_lineScale;
       mat4 camera_VPMat;
       mat4 u_worldMatrix;
       mat4 u_worldNormal;
+      vec4 material_BaseColor;
...
-      vec4 material_BaseColor;
-
       void frag(Varyings v) {
         gl_FragColor = material_BaseColor;
       }

Also applies to: 87-87

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/geometry-sketch/src/material/TBNMaterial.ts` around lines 14 - 17,
Uniform declarations are split: move the material_BaseColor uniform declaration
so it is co-located with the other uniforms (u_lineScale, camera_VPMat,
u_worldMatrix, u_worldNormal) at the top of the Pass; locate the
material_BaseColor declaration between vert and frag and cut/paste it up with
those uniforms to keep all uniform declarations together and follow the
project's pattern.

35-37: Nit: Varyings returned uninitialized.

Varyings only contains _placeholder and vert() returns v without assigning it. The frag stage never reads it (it only uses the material_BaseColor uniform), so this is functionally safe, but you could drop the placeholder once your ShaderLab version allows an empty struct, or initialize it (Varyings v; v._placeholder = 0.0;) to silence potential driver warnings.

Also applies to: 84-84

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/geometry-sketch/src/material/TBNMaterial.ts` around lines 35 - 37,
The Varyings struct is left uninitialized because vert() returns a Varyings v
without assigning its _placeholder field; either initialize the struct in vert()
(e.g., set v._placeholder = 0.0 before return) or remove the placeholder field
once empty structs are supported to avoid driver warnings; apply the same fix to
the other Varyings occurrence referenced in this file so all vert() returns
return initialized Varyings instances.
packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts (2)

190-190: Prefer @ts-expect-error over @ts-ignore.

@ts-expect-error will fail the build as soon as the engine publishes the matching ShaderPass single-arg overload, guaranteeing the suppression is cleaned up. @ts-ignore silently lingers forever. Minor, but particularly useful since the comment explicitly says this is a temporary workaround.

-// `@ts-ignore` - ShaderPass single-arg constructor supported in engine but not yet published
+// `@ts-expect-error` - ShaderPass single-arg constructor supported in engine but not yet published
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts` at
line 190, Replace the inline TypeScript suppression at the ShaderPass single-arg
constructor site by changing the comment token from `@ts-ignore` to
`@ts-expect-error` so the build will fail once the engine publishes the matching
overload; update the adjacent explanatory comment (the one referencing
"ShaderPass single-arg constructor supported in engine but not yet published")
if needed to keep context while ensuring the suppression uses `@ts-expect-error`
instead of `@ts-ignore` in PlanarShadowShaderFactory where ShaderPass is
constructed.

21-22: Doc wording nit.

"Replace material Shader and initialization." / "Material to replace and initialization." reads awkwardly. Consider: "Replace the material's shader and initialize its render state." and "The material to configure."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`
around lines 21 - 22, Update the JSDoc wording to be clearer: change "Replace
material Shader and initialization." to "Replace the material's shader and
initialize its render state." and change "Material to replace and
initialization." to "The material to configure."; locate these strings in the
JSDoc for the PlanarShadowShaderFactory (or the function/method that
replaces/configures the material) and update the comment blocks accordingly to
match the suggested phrasing.
packages/custom-material/src/bake-pbr/BakePBRMaterial.ts (1)

41-107: Duplicated PBR main-loop will drift from the engine's ForwardPassPBR.

BakePBRFragment re-implements the whole surface/BSDF/shadow/direct-light/IBL/transmission/fog pipeline that PBR/ForwardPassPBR.glsl already provides, and the #include is effectively only being used to pull in helper functions. Any future engine-side change to the PBR pipeline (new BSDF inputs, additional light types, shadow API tweaks, output-format changes) won't propagate here and will silently diverge — matching the "partial/TODO" note in the PR description. Consider exposing a lightmap hook in the engine's forward pass (e.g. a weak-symbol / macro injection point like PBR_INDIRECT_DIFFUSE_OVERRIDE) so this material can reduce to just the vertex entry + a small override function instead of copy-pasting the main body.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/bake-pbr/BakePBRMaterial.ts` around lines 41 -
107, BakePBRFragment duplicates the entire PBR pipeline from
PBR/ForwardPassPBR.glsl (surface/BSDF/shadow/direct-light/IBL/transmission/fog)
which will diverge from the engine; instead refactor to call into the engine
forward pass and only inject the lightmap override. Replace the body of
BakePBRFragment so it uses the included forward pass entry (keep Varyings
BakePBRVertex / PBRVertex) and implement a small override hook (e.g., implement
or call a macro like PBR_INDIRECT_DIFFUSE_OVERRIDE or a provided engine hook) to
apply texture2D(u_lightMapTexture, lightMapUV) * u_lightMapIntensity *
BRDF_Diffuse_Lambert(bsdfData.diffuseColor) to the indirect/diffuse term; remove
or delegate usages of initBSDFData, evaluateDirectRadiance, evaluateIBL,
sampleShadowMap, evaluateTransmission and fog so the engine implementation
remains authoritative.
packages/framebuffer-picker/src/FramebufferPicker.ts (1)

83-85: Nit: Varyings carries an unused _placeholder field.

The fragment shader doesn't read any varying, and vert returns v without assigning _placeholder, so the interpolated value is indeterminate (harmless here, just noise). If ShaderLab permits an empty struct you could drop the field; otherwise, a short comment explaining why the placeholder exists would help future readers.

Optional tweak
       struct Varyings {
-        float _placeholder;
+        float _placeholder; // ShaderLab requires a non-empty Varyings struct; unused by frag.
       };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/framebuffer-picker/src/FramebufferPicker.ts` around lines 83 - 85,
The Varyings struct contains an unused float _placeholder which produces
indeterminate interpolants; either remove the field if ShaderLab allows an empty
varying struct, or explicitly initialize it in the vertex function (the vert
function that returns v) to a deterministic value (e.g., 0.0) and/or add a
one-line comment on why the placeholder exists so readers understand it's
intentional; update the declaration of Varyings and the vert function (or add
the comment next to _placeholder) accordingly.
packages/custom-material/src/grid/GridMaterial.ts (1)

47-47: Consider consolidating includes at the top of the Pass.

#include "Common/Transform.glsl" is placed between the vert entry function and the fragment-side uniforms/helpers. Functionally this is fine in ShaderLab (pass body is concatenated), but splitting includes makes it harder to see, at a glance, what symbols are available to vert vs frag. Moving it up next to the Common/Common.glsl include would match the convention used by the other materials migrated in this PR.

♻️ Proposed refactor
       `#include` "Common/Common.glsl"
+      `#include` "Common/Transform.glsl"
 
-      mat4 camera_ViewInvMat;
-      mat4 camera_ProjMat;
-
       struct Attributes {
@@
         return v;
       }
 
-      `#include` "Common/Transform.glsl"
-
       float u_far;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/grid/GridMaterial.ts` at line 47, The include
"#include \"Common/Transform.glsl\"" is currently placed after the vert entry
function which splits shared symbols between vertex and fragment code; move this
include up next to the existing "#include \"Common/Common.glsl\"" in
GridMaterial.ts so both the vert entry function and the fragment-side
uniforms/helpers (frag) see the same transform definitions, preserving the
original pass semantics while matching the include ordering convention used by
other materials.
packages/geometry-sketch/src/material/WireframeMaterial.ts (1)

14-33: Remove dead uniforms and redundant attribute members.

Several declarations in this shader block are unused and add confusion:

  • u_lineScale (Line 14) and u_worldNormal (Line 17) are declared but never referenced anywhere in vert/frag. They appear to be leftovers from the pre‑ShaderLab version.
  • Inside struct Attributes, the POSITION, NORMAL, and TANGENT members are dead from the vertex body's perspective: the body refers to bare POSITION / NORMAL / TANGENT on lines 52/55/57, which are locals injected by ${geometryTextureVert} (texture‑sourced geometry), not attr.POSITION etc. Keeping them in Attributes still forces the engine to look up / bind those vertex‑buffer attributes on the draw, which is wasted work for this texture‑fed geometry.

Only JOINTS_0 / WEIGHTS_0 are actually consumed (via getSkinMatrix(attr)), so the struct can shrink substantially.

♻️ Suggested cleanup
-      float u_lineScale;
       mat4 camera_VPMat;
       mat4 u_worldMatrix;
-      mat4 u_worldNormal;

       ${geometryTextureDefine}

       struct Attributes {
-        vec3 POSITION;
         `#ifdef` RENDERER_HAS_SKIN
           vec4 JOINTS_0;
           vec4 WEIGHTS_0;
         `#endif`
-        `#ifdef` RENDERER_HAS_NORMAL
-          vec3 NORMAL;
-        `#endif`
-        `#ifdef` RENDERER_HAS_TANGENT
-          vec4 TANGENT;
-        `#endif`
       };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/geometry-sketch/src/material/WireframeMaterial.ts` around lines 14 -
33, Remove the unused uniforms and redundant attribute members: delete the
declarations u_lineScale and u_worldNormal from the uniform block, and simplify
the Attributes struct to only include JOINTS_0 and WEIGHTS_0 (since POSITION,
NORMAL, and TANGENT are provided by the injected ${geometryTextureVert} locals
and not via attr.*). Keep getSkinMatrix(attr) usage intact and ensure any code
paths that expect attr.POSITION/NORMAL/TANGENT instead use the texture-sourced
POSITION/NORMAL/TANGENT provided by geometryTextureVert so the engine no longer
binds those unused vertex attributes.
packages/lines/src/line/material/lineShader.ts (2)

18-36: v_direction varying is write-only; can be removed.

v.v_direction is assigned in vert but never read in either stage, and frag doesn't reference it. It's dead state passing through the pipeline.

♻️ Proposed change
       struct Varyings {
         vec2 v_origin;
         vec2 v_position;
-        float v_direction;
         float v_part;
       };

       Varyings vert(Attributes attr) {
         Varyings v;
-        v.v_direction = attr.a_data.x;
         v.v_part = attr.a_data.y;
-        float layer_index = 1.0;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/lines/src/line/material/lineShader.ts` around lines 18 - 36, The
Varyings struct contains an unused varying v_direction which is written in vert
but never read; remove the dead varying by deleting its declaration in Varyings
and removing the assignment v.v_direction = attr.a_data.x from the vert function
(ensure no other code references v_direction or relies on attr.a_data.x in this
shader). This keeps Varyings minimal and avoids passing unused state between
stages.

44-58: Unused finalColor local.

vec4 finalColor; is declared but never written or read. Minor cleanup.

♻️ Proposed change
       void frag(Varyings v) {
-        vec4 finalColor;
         if (u_cap == 0 && v.v_part == IS_CAP) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/lines/src/line/material/lineShader.ts` around lines 44 - 58, The
fragment shader function frag declares an unused local variable vec4 finalColor;
— remove that declaration from the frag(Varyings v) function (and any related
dead code) so only needed variables like u_color, u_cap, u_join, v.v_part,
v.v_position, v.v_origin, and u_width are used; ensure gl_FragColor = u_color;
remains as the final output and run a quick build/lint to confirm no other
references to finalColor exist.
packages/lines/src/line/material/dashShader.ts (1)

20-48: v_direction varying is never read in the fragment stage.

v.v_direction is written in vert (and used locally there) but never consumed by frag. It still costs an interpolator and vertex attribute copy. Consider dropping it from Varyings and treating it as a local float inside vert instead.

♻️ Proposed change
       struct Varyings {
         vec2 v_origin;
         vec2 v_position;
-        float v_direction;
         float v_part;
         vec2 v_tex;
       };

       Varyings vert(Attributes attr) {
         Varyings v;
-        v.v_direction = attr.a_data.x;
+        float v_direction = attr.a_data.x;
         v.v_part = attr.a_data.y;
         float layer_index = 1.0;

         v.v_origin = attr.a_pos;

         float texcoord_y = 0.0;

         texcoord_y = attr.a_lengthsofar / (u_dash.x + u_dash.y);
-        if (v.v_direction == 1.0) {
+        if (v_direction == 1.0) {
           v.v_tex = vec2(1.0, texcoord_y);
         } else {
           v.v_tex = vec2(0.0, texcoord_y);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/lines/src/line/material/dashShader.ts` around lines 20 - 48, The
Varyings struct currently includes v_direction which is written in vert but
never read in frag; remove v_direction from Varyings and instead read
attr.a_data.x into a local float (e.g., direction) inside vert, then use that
local to set v.v_tex; update vert to stop assigning v.v_direction and delete the
v.v_direction declaration in Varyings so you avoid wasting an interpolator and
vertex attribute copy (leave v_part, v_origin, v_position, v_tex unchanged).
packages/custom-material/src/plain-color/PlainColorMaterial.ts (1)

58-60: Consider removing the unused _placeholder field from the empty Varyings struct. Empty Varyings structs are syntactically valid in Galacean ShaderLab, so the placeholder is unnecessary. The vertex shader doesn't populate any data, and the fragment shader doesn't use the Varyings parameter, making this field a wasteful use of an interpolator slot.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/plain-color/PlainColorMaterial.ts` around lines
58 - 60, The empty Varyings struct contains an unnecessary interpolator field
`_placeholder`; remove `_placeholder` from the `struct Varyings` declaration and
update the vertex and fragment shader function signatures that reference
`Varyings` (in this file's shader code) to use an empty `Varyings` type instead,
ensuring no code references `_placeholder` remain; this avoids consuming an
interpolator slot while keeping the Galacean ShaderLab-compatible empty struct
`Varyings`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/custom-material/src/bake-pbr/BakePBRMaterial.ts`:
- Around line 99-106: The fragment currently writes gl_FragColor directly in
BakePBRFragment without applying the documented ACES tone mapping or using an
exposure uniform; add a uniform float (e.g. uExposure) and apply it to the
accumulated HDR color, then run the ACES tone mapping helper (use the existing
acesToneMapping/ACESFilm helper or add one if missing) and convert to sRGB
(linearToSRGB or equivalent) before assigning gl_FragColor; update
BakePBRFragment to multiply color.rgb by uExposure, pass the result through the
ACES tone mapping function, then set gl_FragColor = vec4(toneMappedColor,
color.a). If tone mapping is intentionally omitted instead, update the README to
remove the ACES/exposure claims.

In `@packages/custom-material/src/grid/GridMaterial.ts`:
- Around line 11-12: Remove the redundant uniform redeclarations for
camera_ViewInvMat and camera_ProjMat from GridMaterial shader source so the
shader relies on the shared includes (e.g., Common/Common.glsl and
Common/Transform.glsl) like the other migrated shaders; specifically delete the
two lines that declare mat4 camera_ViewInvMat; and mat4 camera_ProjMat; and
ensure references to camera_ViewMat and camera_ProjectionParams remain unchanged
so the common includes supply those uniforms consistently with outline, gizmo,
plain-color, and geometry-sketch shaders.

In `@packages/custom-material/src/plain-color/PlainColorMaterial.ts`:
- Around line 81-93: The fragment shader references material_AlphaCutoff inside
the frag function under the MATERIAL_IS_ALPHA_CUTOFF guard but never declares
it; add a declaration for material_AlphaCutoff (float) next to the existing vec4
material_BaseColor variable so the shader compiles when MATERIAL_IS_ALPHA_CUTOFF
is defined — update the declarations that contain material_BaseColor to also
declare material_AlphaCutoff so frag can use it safely.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`:
- Around line 190-194: The module currently calls Shader.find("PBR") and
constructs new ShaderPass(planarShadowPassSource) at import time which can NPE
if PBR isn't registered and produces orphan passes; fix by moving the
ShaderPass(planarShadowPassSource) construction and the
Shader.create("planarShadowShader", ...) call inside a guarded lazy initializer
function (e.g., registerPlanarShadowShader()) that first calls
Shader.find("PBR"), checks for null, and only then accesses
.subShaders[0].passes[2] and creates the shader; update replaceShader to call
registerPlanarShadowShader() before using the shader so registration is
deterministic and import-time side-effects are eliminated.
- Around line 108-114: In the Attributes struct inside PlanarShadowShaderFactory
(the struct named Attributes that currently declares vec4 POSITION), change the
POSITION field type from vec4 to vec3 so it matches the engine's glTF attribute
binding and other ShaderLab materials; update the declaration of POSITION in
Attributes to vec3 POSITION and leave the shader code that uses
vec4(attr.POSITION.xyz, 1.0) unchanged.

In `@packages/geometry-sketch/src/material/WireframeMaterial.ts`:
- Around line 15-17: Remove or guard the local uniform declaration camera_VPMat
in WireframeMaterial to avoid shadowing the engine-provided uniform from
Common/Transform.glsl; either delete the camera_VPMat declaration or wrap it in
a macro/ifdef that only defines it when the engine does not provide it, and keep
u_worldMatrix and u_worldNormal as-is (they are custom) while continuing to use
the engine's renderer_ModelMat where appropriate.
- Around line 41-45: The shader in WireframeMaterial.ts uses gl_VertexID (seen
in the snippet with gl_VertexID, getIndicesElement, u_indicesTextureWidth) which
requires GLSL ES 3.0/WebGL2; update the shader source to either prepend
"#version 300 es" at the top to enforce WebGL2 or replace gl_VertexID usage with
an explicit vertex attribute (e.g., pass a flat int/float index attribute from
the vertex buffer and use that instead of gl_VertexID) so it will compile on
WebGL1; also update any surrounding code that constructs the program to
document/require WebGL2 if you choose the version route.

In `@packages/gizmo/src/icon/Icon.ts`:
- Line 66: The load call using this.engine.resourceManager.load({ url: value,
type: AssetType.Texture }) is using a non-existent AssetType; change the asset
type to AssetType.Texture2D so the resource manager returns a Texture2D (update
the object literal to use type: AssetType.Texture2D), keeping the existing
then((texture: Texture2D) => ...) handler in the Icon class to ensure correct
typing and runtime resolution.

In `@packages/outline/src/OutlineManager.ts`:
- Around line 176-211: The shader is missing the Varyings struct used by
outlineReplaceShaderSource's vert and frag; add a Varyings declaration above the
vert function (in the outlineReplaceShaderSource string) that defines every
varying the vertex shader writes and the fragment shader reads (e.g., any
TEXCOORD, COLOR, or custom varyings used by frag), using the correct
interpolation qualifiers/precision as used elsewhere in our shaders so field
names/types match references in vert and frag.

---

Outside diff comments:
In `@packages/gizmo/src/icon/Icon.ts`:
- Around line 60-71: The texture setter's async URL branch currently lacks error
handling and can be conditionally overwritten by stale resolves; update the URL
branch in the set texture(value: string | Texture2D) method to (1) capture the
expected value (e.g., const expected = value) before calling
engine.resourceManager.load({ url: value, type: AssetType.Texture }) and in the
.then handler only assign this._material.baseTexture = texture if this._texture
=== expected, and (2) attach a .catch to the promise to log or handle load
errors (use process/error logger or throw as appropriate) to avoid unhandled
rejections; ensure the same guard is used if converting to a Texture2D
synchronously when value instanceof Texture2D.

---

Nitpick comments:
In `@packages/controls/src/box-selection/BoxSelectionSSMaterial.ts`:
- Around line 20-24: The Varyings struct instance 'v' in the vertex function
'vert' is returned without initializing its member(s); initialize v._placeholder
(or all Varyings fields) before returning from vert to ensure defined behavior
across GLSL backends—locate the function vert and the local variable v in
BoxSelectionSSMaterial.ts and set v._placeholder (or zero/appropriate default
for each field) prior to the return statement.

In `@packages/custom-material/src/bake-pbr/BakePBRMaterial.ts`:
- Around line 41-107: BakePBRFragment duplicates the entire PBR pipeline from
PBR/ForwardPassPBR.glsl (surface/BSDF/shadow/direct-light/IBL/transmission/fog)
which will diverge from the engine; instead refactor to call into the engine
forward pass and only inject the lightmap override. Replace the body of
BakePBRFragment so it uses the included forward pass entry (keep Varyings
BakePBRVertex / PBRVertex) and implement a small override hook (e.g., implement
or call a macro like PBR_INDIRECT_DIFFUSE_OVERRIDE or a provided engine hook) to
apply texture2D(u_lightMapTexture, lightMapUV) * u_lightMapIntensity *
BRDF_Diffuse_Lambert(bsdfData.diffuseColor) to the indirect/diffuse term; remove
or delegate usages of initBSDFData, evaluateDirectRadiance, evaluateIBL,
sampleShadowMap, evaluateTransmission and fog so the engine implementation
remains authoritative.

In `@packages/custom-material/src/grid/GridMaterial.ts`:
- Line 47: The include "#include \"Common/Transform.glsl\"" is currently placed
after the vert entry function which splits shared symbols between vertex and
fragment code; move this include up next to the existing "#include
\"Common/Common.glsl\"" in GridMaterial.ts so both the vert entry function and
the fragment-side uniforms/helpers (frag) see the same transform definitions,
preserving the original pass semantics while matching the include ordering
convention used by other materials.

In `@packages/custom-material/src/plain-color/PlainColorMaterial.ts`:
- Around line 58-60: The empty Varyings struct contains an unnecessary
interpolator field `_placeholder`; remove `_placeholder` from the `struct
Varyings` declaration and update the vertex and fragment shader function
signatures that reference `Varyings` (in this file's shader code) to use an
empty `Varyings` type instead, ensuring no code references `_placeholder`
remain; this avoids consuming an interpolator slot while keeping the Galacean
ShaderLab-compatible empty struct `Varyings`.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`:
- Line 190: Replace the inline TypeScript suppression at the ShaderPass
single-arg constructor site by changing the comment token from `@ts-ignore` to
`@ts-expect-error` so the build will fail once the engine publishes the matching
overload; update the adjacent explanatory comment (the one referencing
"ShaderPass single-arg constructor supported in engine but not yet published")
if needed to keep context while ensuring the suppression uses `@ts-expect-error`
instead of `@ts-ignore` in PlanarShadowShaderFactory where ShaderPass is
constructed.
- Around line 21-22: Update the JSDoc wording to be clearer: change "Replace
material Shader and initialization." to "Replace the material's shader and
initialize its render state." and change "Material to replace and
initialization." to "The material to configure."; locate these strings in the
JSDoc for the PlanarShadowShaderFactory (or the function/method that
replaces/configures the material) and update the comment blocks accordingly to
match the suggested phrasing.

In `@packages/framebuffer-picker/src/FramebufferPicker.ts`:
- Around line 83-85: The Varyings struct contains an unused float _placeholder
which produces indeterminate interpolants; either remove the field if ShaderLab
allows an empty varying struct, or explicitly initialize it in the vertex
function (the vert function that returns v) to a deterministic value (e.g., 0.0)
and/or add a one-line comment on why the placeholder exists so readers
understand it's intentional; update the declaration of Varyings and the vert
function (or add the comment next to _placeholder) accordingly.

In `@packages/geometry-sketch/src/material/TBNMaterial.ts`:
- Around line 14-17: Uniform declarations are split: move the material_BaseColor
uniform declaration so it is co-located with the other uniforms (u_lineScale,
camera_VPMat, u_worldMatrix, u_worldNormal) at the top of the Pass; locate the
material_BaseColor declaration between vert and frag and cut/paste it up with
those uniforms to keep all uniform declarations together and follow the
project's pattern.
- Around line 35-37: The Varyings struct is left uninitialized because vert()
returns a Varyings v without assigning its _placeholder field; either initialize
the struct in vert() (e.g., set v._placeholder = 0.0 before return) or remove
the placeholder field once empty structs are supported to avoid driver warnings;
apply the same fix to the other Varyings occurrence referenced in this file so
all vert() returns return initialized Varyings instances.

In `@packages/geometry-sketch/src/material/WireframeMaterial.ts`:
- Around line 14-33: Remove the unused uniforms and redundant attribute members:
delete the declarations u_lineScale and u_worldNormal from the uniform block,
and simplify the Attributes struct to only include JOINTS_0 and WEIGHTS_0 (since
POSITION, NORMAL, and TANGENT are provided by the injected
${geometryTextureVert} locals and not via attr.*). Keep getSkinMatrix(attr)
usage intact and ensure any code paths that expect attr.POSITION/NORMAL/TANGENT
instead use the texture-sourced POSITION/NORMAL/TANGENT provided by
geometryTextureVert so the engine no longer binds those unused vertex
attributes.

In `@packages/lines/src/line/material/dashShader.ts`:
- Around line 20-48: The Varyings struct currently includes v_direction which is
written in vert but never read in frag; remove v_direction from Varyings and
instead read attr.a_data.x into a local float (e.g., direction) inside vert,
then use that local to set v.v_tex; update vert to stop assigning v.v_direction
and delete the v.v_direction declaration in Varyings so you avoid wasting an
interpolator and vertex attribute copy (leave v_part, v_origin, v_position,
v_tex unchanged).

In `@packages/lines/src/line/material/lineShader.ts`:
- Around line 18-36: The Varyings struct contains an unused varying v_direction
which is written in vert but never read; remove the dead varying by deleting its
declaration in Varyings and removing the assignment v.v_direction =
attr.a_data.x from the vert function (ensure no other code references
v_direction or relies on attr.a_data.x in this shader). This keeps Varyings
minimal and avoids passing unused state between stages.
- Around line 44-58: The fragment shader function frag declares an unused local
variable vec4 finalColor; — remove that declaration from the frag(Varyings v)
function (and any related dead code) so only needed variables like u_color,
u_cap, u_join, v.v_part, v.v_position, v.v_origin, and u_width are used; ensure
gl_FragColor = u_color; remains as the final output and run a quick build/lint
to confirm no other references to finalColor exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cf9cc120-dcac-4943-bb92-1c71d5dbe90e

📥 Commits

Reviewing files that changed from the base of the PR and between c76e660 and e6f912e.

⛔ Files ignored due to path filters (11)
  • packages/custom-material/src/advanced-shader/eye/EyeForwardPass.glsl is excluded by !**/*.glsl
  • packages/custom-material/src/advanced-shader/hair/HairForwardPass.glsl is excluded by !**/*.glsl
  • packages/custom-material/src/advanced-shader/hair/HairLightDirect.glsl is excluded by !**/*.glsl
  • packages/custom-material/src/advanced-shader/sss/SSSForwardPass.glsl is excluded by !**/*.glsl
  • packages/custom-material/src/advanced-shader/sss/SSSLightDirect.glsl is excluded by !**/*.glsl
  • packages/framebuffer-picker/src/color.fs.glsl is excluded by !**/*.glsl
  • packages/framebuffer-picker/src/color.vs.glsl is excluded by !**/*.glsl
  • packages/outline/src/outline.fs.glsl is excluded by !**/*.glsl
  • packages/outline/src/outline.vs.glsl is excluded by !**/*.glsl
  • packages/outline/src/replace.fs.glsl is excluded by !**/*.glsl
  • packages/outline/src/replace.vs.glsl is excluded by !**/*.glsl
📒 Files selected for processing (22)
  • packages/controls/src/box-selection/BoxSelectionSSMaterial.ts
  • packages/custom-material/src/bake-pbr/BakePBRMaterial.ts
  • packages/custom-material/src/bake-pbr/fragment.ts
  • packages/custom-material/src/bake-pbr/vertex.ts
  • packages/custom-material/src/grid/GridMaterial.ts
  • packages/custom-material/src/plain-color/PlainColorMaterial.ts
  • packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts
  • packages/custom-material/src/water/WaterMaterial.ts
  • packages/custom-material/src/water/WaterRippleMaterial.ts
  • packages/custom-material/src/water/WaterfallMaterial.ts
  • packages/framebuffer-picker/src/FramebufferPicker.ts
  • packages/framebuffer-picker/src/global.d.ts
  • packages/geometry-sketch/src/material/GeometryShader.ts
  • packages/geometry-sketch/src/material/TBNMaterial.ts
  • packages/geometry-sketch/src/material/WireframeMaterial.ts
  • packages/gizmo/src/icon/Icon.ts
  • packages/gizmo/src/icon/IconMaterial.ts
  • packages/lines/src/line/material/dashShader.ts
  • packages/lines/src/line/material/lineShader.ts
  • packages/outline/src/OutlineManager.ts
  • packages/outline/src/global.d.ts
  • packages/skeleton-viewer/src/SkeletonViewer.ts
💤 Files with no reviewable changes (4)
  • packages/framebuffer-picker/src/global.d.ts
  • packages/outline/src/global.d.ts
  • packages/custom-material/src/bake-pbr/fragment.ts
  • packages/custom-material/src/bake-pbr/vertex.ts

Comment on lines +99 to +106
vec4 color = vec4((totalDiffuseColor + totalSpecularColor).rgb, surfaceData.opacity);
color.rgb += surfaceData.emissiveColor;

#if SCENE_FOG_MODE != 0
color = fog(color, varyings.positionVS);
#endif

gl_FragColor = color;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate engine's ForwardPassPBR.glsl and inspect the final-write section to confirm
# which tone-mapping / color-space helpers the standard path applies.
fd -t f 'ForwardPassPBR.glsl'
fd -t f 'ForwardPassPBR.glsl' --exec sh -c 'echo "=== $1 ==="; tail -n 80 "$1"' _ {}
# Also look for tone-map / gamma helpers referenced by the standard pass.
rg -nP '\b(linearToGamma|gammaToLinear|HDRToLDR|toneMapping|ACESToneMap)\s*\(' -C2

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

# First, let's understand the repository structure
git ls-files | head -20

Repository: galacean/engine-toolkit

Length of output: 515


🏁 Script executed:

# Look for shader files in the custom-material package
fd -t f '\.(glsl|frag|vert)$' packages/custom-material/

Repository: galacean/engine-toolkit

Length of output: 615


🏁 Script executed:

# Read the BakePBRMaterial.ts file to see the actual implementation
wc -l packages/custom-material/src/bake-pbr/BakePBRMaterial.ts

Repository: galacean/engine-toolkit

Length of output: 127


🏁 Script executed:

# Search for tone mapping related functions across the codebase
rg -i 'tone.?map|linear.?gamma|hdr.?ldr' --type glsl --type ts

Repository: galacean/engine-toolkit

Length of output: 95


🏁 Script executed:

cat -n packages/custom-material/src/bake-pbr/BakePBRMaterial.ts

Repository: galacean/engine-toolkit

Length of output: 6349


🏁 Script executed:

# Search for tone mapping functions without file type restriction
rg -i 'tone.?map|linear.?gamma|hdr.?ldr' -A2 -B2

Repository: galacean/engine-toolkit

Length of output: 1830


🏁 Script executed:

# Look for ForwardPassPBR references
rg -i 'forwardpass' -A2 -B2

Repository: galacean/engine-toolkit

Length of output: 1593


🏁 Script executed:

# Search for exposure property definitions
rg -i 'exposure' -A2 -B2 | head -60

Repository: galacean/engine-toolkit

Length of output: 1193


🏁 Script executed:

# Look at the base PBRMaterial to see what it inherits
rg -i 'class.*PBRMaterial' -A5

Repository: galacean/engine-toolkit

Length of output: 668


🏁 Script executed:

# Search for where tone mapping might be applied in forward pass or elsewhere
rg -i 'aces|tone' -A2 -B2 | head -80

Repository: galacean/engine-toolkit

Length of output: 6267


🏁 Script executed:

# Check if there are any other shader files that show how tone mapping is applied
fd -type f -name '*.glsl' -o -name '*.gs' | xargs rg -l 'gl_FragColor' | head -10

Repository: galacean/engine-toolkit

Length of output: 779


BakePBRFragment missing ACES tone mapping promised in README.

The README documents that the material "supports...ACES toneMapping to correct the highlights" with an "Exposure" parameter "adjusted by ACES toneMapping automatically." However, the BakePBRFragment function (lines 99–106) writes gl_FragColor = color directly without reading any exposure value or applying tone mapping. The fragment shader accumulates totalDiffuseColor + totalSpecularColor + emissiveColor and applies fog, but skips the tone mapping step that would compensate for HDR lighting and match the visual output of PBRMaterial in the same scene.

Either add the exposure uniform and apply ACES tone mapping to the final color before gl_FragColor assignment, or remove/update the README documentation if tone mapping is not actually intended for this material.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/bake-pbr/BakePBRMaterial.ts` around lines 99 -
106, The fragment currently writes gl_FragColor directly in BakePBRFragment
without applying the documented ACES tone mapping or using an exposure uniform;
add a uniform float (e.g. uExposure) and apply it to the accumulated HDR color,
then run the ACES tone mapping helper (use the existing acesToneMapping/ACESFilm
helper or add one if missing) and convert to sRGB (linearToSRGB or equivalent)
before assigning gl_FragColor; update BakePBRFragment to multiply color.rgb by
uExposure, pass the result through the ACES tone mapping function, then set
gl_FragColor = vec4(toneMappedColor, color.a). If tone mapping is intentionally
omitted instead, update the README to remove the ACES/exposure claims.

Comment thread packages/custom-material/src/grid/GridMaterial.ts Outdated
Comment thread packages/custom-material/src/plain-color/PlainColorMaterial.ts Outdated
Comment on lines +108 to +114
struct Attributes {
vec4 POSITION;
#ifdef RENDERER_HAS_SKIN
attribute vec4 JOINTS_0;
attribute vec4 WEIGHTS_0;
vec4 JOINTS_0;
vec4 WEIGHTS_0;
#endif
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how POSITION is declared in other ShaderLab-migrated factories in this PR.
rg -nP --type=ts -C2 '\b(vec3|vec4)\s+POSITION\b' -g '!**/node_modules/**'

Repository: galacean/engine-toolkit

Length of output: 5554


🏁 Script executed:

sed -n '145,165p' packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts

Repository: galacean/engine-toolkit

Length of output: 982


Change POSITION from vec4 to vec3 to match the engine's attribute binding and all other materials in this PR.

Every other ShaderLab-migrated material declares POSITION as vec3 (WaterMaterial, PlainColorMaterial, OutlineManager, etc.), but this file declares it as vec4. While the code vec4(attr.POSITION.xyz, 1.0) works regardless of the declaration type, the struct field should match how the engine actually binds the glTF attribute (as vec3). Change line 109 from vec4 POSITION; to vec3 POSITION; for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`
around lines 108 - 114, In the Attributes struct inside
PlanarShadowShaderFactory (the struct named Attributes that currently declares
vec4 POSITION), change the POSITION field type from vec4 to vec3 so it matches
the engine's glTF attribute binding and other ShaderLab materials; update the
declaration of POSITION in Attributes to vec3 POSITION and leave the shader code
that uses vec4(attr.POSITION.xyz, 1.0) unchanged.

Comment on lines +190 to +194
// @ts-ignore - ShaderPass single-arg constructor supported in engine but not yet published
const planarShadow = new ShaderPass(planarShadowPassSource);

// shadow color
color = u_planarShadowColor;
color.a *= falloff;
}
`,
`
varying vec4 color;
void main() {
gl_FragColor = color;
}
`
);
Shader.create("planarShadowShader", [Shader.find("pbr").subShaders[0].passes[0], planarShadow]);
if (!Shader.find("planarShadowShader")) {
Shader.create("planarShadowShader", [Shader.find("PBR").subShaders[0].passes[2], planarShadow]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Module-load ordering: unguarded Shader.find("PBR") can NPE.

Shader.find("PBR") is called at import time and its result is dereferenced as .subShaders[0].passes[2] without a null check. If this module is imported before the PBR shader is registered (e.g., depending on bundler/side-effect import order, or in a test environment), Shader.find("PBR") returns null and the whole module load crashes — and because the work sits at top level, there's no way for a caller to recover.

A few related concerns in the same block:

  • new ShaderPass(planarShadowPassSource) on Line 191 runs on every import even when planarShadowShader was already created by a previous load, producing an orphan ShaderPass. Move it inside the if (!Shader.find(...)) guard.
  • Consider wrapping the whole registration in a lazy init function invoked from replaceShader (or a single registerPlanarShadowShader() export), so shader creation is deterministic and ordered with respect to PBR registration rather than implicit on module import.
🛠️ Suggested fix
-// `@ts-ignore` - ShaderPass single-arg constructor supported in engine but not yet published
-const planarShadow = new ShaderPass(planarShadowPassSource);
-
-if (!Shader.find("planarShadowShader")) {
-  Shader.create("planarShadowShader", [Shader.find("PBR").subShaders[0].passes[2], planarShadow]);
-}
+if (!Shader.find("planarShadowShader")) {
+  const pbr = Shader.find("PBR");
+  if (!pbr) {
+    throw new Error(
+      `Cannot create "planarShadowShader": base "PBR" shader is not registered yet. ` +
+        `Ensure the engine's built-in shaders are initialized before importing PlanarShadowShaderFactory.`
+    );
+  }
+  // `@ts-expect-error` - ShaderPass single-arg constructor supported in engine but not yet published
+  const planarShadow = new ShaderPass(planarShadowPassSource);
+  Shader.create("planarShadowShader", [pbr.subShaders[0].passes[2], planarShadow]);
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`
around lines 190 - 194, The module currently calls Shader.find("PBR") and
constructs new ShaderPass(planarShadowPassSource) at import time which can NPE
if PBR isn't registered and produces orphan passes; fix by moving the
ShaderPass(planarShadowPassSource) construction and the
Shader.create("planarShadowShader", ...) call inside a guarded lazy initializer
function (e.g., registerPlanarShadowShader()) that first calls
Shader.find("PBR"), checks for null, and only then accesses
.subShaders[0].passes[2] and creates the shader; update replaceShader to call
registerPlanarShadowShader() before using the shader so registration is
deterministic and import-time side-effects are eliminated.

Comment thread packages/geometry-sketch/src/material/WireframeMaterial.ts Outdated
Comment thread packages/geometry-sketch/src/material/WireframeMaterial.ts Outdated
this._material.baseTexture = value;
} else {
this.engine.resourceManager.load({ url: value, type: AssetType.Texture2D }).then((texture: Texture2D) => {
this.engine.resourceManager.load({ url: value, type: AssetType.Texture }).then((texture: Texture2D) => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

galacean engine AssetType.Texture vs Texture2D resourceManager.load return type

💡 Result:

In Galacean Engine, use AssetType.Texture2D to load 2D textures via resourceManager.load, which returns a Texture2D object. There is no AssetType.Texture; official documentation consistently uses AssetType.Texture2D for image files (.png, .jpg, .webp) that create 2D textures. Texture refers to the general concept (including 2D, CubeTexture), while Texture2D is the specific class and asset type for 2D textures. Example from official docs: engine.resourceManager.load({ type: AssetType.Texture2D, url: 'image url' }).then((texture: Texture2D) => { ... }); AssetType values include Texture2D (for 2D images), with separate types like GLTF for models and Scene for scenes. Editor assets list "Texture" as UI label for 2D texture uploads, but script loading specifies AssetType.Texture2D.

Citations:


🏁 Script executed:

cat packages/gizmo/src/icon/Icon.ts | head -80 | tail -20

Repository: galacean/engine-toolkit

Length of output: 650


🏁 Script executed:

rg "enum AssetType|type AssetType" --type ts -A 10 -B 2

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

rg "AssetType\." --type ts | head -20

Repository: galacean/engine-toolkit

Length of output: 211


🏁 Script executed:

rg "AssetType" packages/gizmo/src/icon/Icon.ts -B 5 | head -30

Repository: galacean/engine-toolkit

Length of output: 367


🏁 Script executed:

rg "export.*enum.*AssetType|export.*const.*AssetType" -type ts

Repository: galacean/engine-toolkit

Length of output: 94


🏁 Script executed:

rg "Texture" packages/gizmo/src/icon/Icon.ts | head -10

Repository: galacean/engine-toolkit

Length of output: 445


🏁 Script executed:

rg "AssetType\s*[=:{]" --type ts -A 30 | head -100

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

fd "AssetType" --type ts

Repository: galacean/engine-toolkit

Length of output: 236


🏁 Script executed:

find . -name "*.ts" -o -name "*.d.ts" | xargs grep -l "enum AssetType\|export.*AssetType" | head -5

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

rg "AssetType\s*=" --type-list

Repository: galacean/engine-toolkit

Length of output: 456


🏁 Script executed:

rg "AssetType\." . -A 2 -B 2 | grep -E "(Texture|AssetType)" | sort -u | head -20

Repository: galacean/engine-toolkit

Length of output: 437


🏁 Script executed:

cat packages/gizmo/package.json | grep -A 10 -B 2 "galacean"

Repository: galacean/engine-toolkit

Length of output: 956


🏁 Script executed:

rg "import.*AssetType" packages/gizmo/src/icon/Icon.ts -B 5 -A 5

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

head -30 packages/gizmo/src/icon/Icon.ts

Repository: galacean/engine-toolkit

Length of output: 760


Use AssetType.Texture2D instead of AssetType.Texture.

The code passes AssetType.Texture, but Galacean engine documentation specifies AssetType.Texture2D for loading 2D texture assets. There is no AssetType.Texture in the engine; the correct asset type for image files (.png, .jpg, .webp) is AssetType.Texture2D, which properly resolves to Texture2D objects via resourceManager.load().

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/gizmo/src/icon/Icon.ts` at line 66, The load call using
this.engine.resourceManager.load({ url: value, type: AssetType.Texture }) is
using a non-existent AssetType; change the asset type to AssetType.Texture2D so
the resource manager returns a Texture2D (update the object literal to use type:
AssetType.Texture2D), keeping the existing then((texture: Texture2D) => ...)
handler in the Icon class to ensure correct typing and runtime resolution.

Comment thread packages/outline/src/OutlineManager.ts Outdated
- Replace inline struct Attributes with #include "Common/Attributes.glsl"
- Add #ifdef guards for unconditional attribute usage
- Replace PBR/AttributesPBR.glsl refs in ForwardPass shaders
- Use void vert/frag signature for shaders without varyings
- Affected: TBNMaterial, WireframeMaterial, FramebufferPicker,
  PlainColorMaterial, BoxSelectionSSMaterial
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
packages/custom-material/src/plain-color/PlainColorMaterial.ts (1)

31-43: ⚠️ Potential issue | 🔴 Critical

Declare material_AlphaCutoff before using it.

Line 37 references material_AlphaCutoff, but this shader source only declares material_BaseColor. Enabling MATERIAL_IS_ALPHA_CUTOFF can fail shader compilation.

Proposed fix
       vec4 material_BaseColor;
+      float material_AlphaCutoff;
 
       void frag() {

To verify the declaration is still missing:

#!/bin/bash
# Description: Confirm `material_AlphaCutoff` references/declarations in the repo.
# Expected: PlainColorMaterial references it in frag; a declaration should exist in the shader source or included shader library.

sed -n '25,43p' packages/custom-material/src/plain-color/PlainColorMaterial.ts
rg -nP '\bmaterial_AlphaCutoff\b' -C2
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/plain-color/PlainColorMaterial.ts` around lines
31 - 43, The shader uses material_AlphaCutoff inside the frag() function guarded
by MATERIAL_IS_ALPHA_CUTOFF but never declares it, causing compile errors when
that define is enabled; add a GLSL declaration for material_AlphaCutoff (e.g., a
float uniform or varying depending on how materials are passed) alongside the
existing material_BaseColor declaration in PlainColorMaterial so the symbol
material_AlphaCutoff is defined when MATERIAL_IS_ALPHA_CUTOFF is used in frag();
update the declarations block that contains material_BaseColor in the
PlainColorMaterial shader source to include this new material_AlphaCutoff
declaration.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/custom-material/src/water/WaterMaterial.ts`:
- Around line 22-56: The vert(Attributes attr) function leaves v.v_color,
v.waterTexCoords and v.normalTexCoords uninitialized when
RENDERER_HAS_UV/RENDERER_ENABLE_VERTEXCOLOR are not defined, while frag() always
reads those varyings (v.v_color, v.waterTexCoords, v.normalTexCoords); to fix,
set safe default values at the start of Varyings vert(Attributes attr) (e.g.
v.v_color = vec4(1.0), v.waterTexCoords = vec2(0.0), v.normalTexCoords =
vec2(0.0)) before any conditional assignments so the fragment shader always
receives defined values.

In `@packages/custom-material/src/water/WaterRippleMaterial.ts`:
- Around line 22-51: The Varyings struct fields used in frag (v.normalTexCoords,
v.waterTexCoords, v.v_color) are only set inside conditional blocks in vert and
can be left uninitialized when RENDERER_HAS_UV or RENDERER_ENABLE_VERTEXCOLOR
are disabled; update vert(Attributes attr) to initialize v.normalTexCoords,
v.waterTexCoords, and v.v_color to safe defaults (e.g., zero vec2/vec4 or
neutral values) before the `#ifdef` blocks so frag() always reads defined values
and avoids undefined behavior.

In `@packages/skeleton-viewer/src/SkeletonViewer.ts`:
- Around line 29-49: The frag shader reads v.v_normal unconditionally while vert
only writes it when RENDERER_HAS_NORMAL is defined, so make the usage symmetric:
either initialize v.v_normal with a safe default in Varyings/vert (e.g., set
v.v_normal = vec3(0,1,0) before the `#ifdef` in the vert function) or wrap the
dot() and related code in frag with `#ifdef` RENDERER_HAS_NORMAL to provide a
fallback diffuse (use a constant color or compute ndl=1.0). Update the Varyings
struct/vert/frag symbols (Varyings, vert, frag, v_normal, RENDERER_HAS_NORMAL)
accordingly so v.v_normal is never read uninitialized.

---

Duplicate comments:
In `@packages/custom-material/src/plain-color/PlainColorMaterial.ts`:
- Around line 31-43: The shader uses material_AlphaCutoff inside the frag()
function guarded by MATERIAL_IS_ALPHA_CUTOFF but never declares it, causing
compile errors when that define is enabled; add a GLSL declaration for
material_AlphaCutoff (e.g., a float uniform or varying depending on how
materials are passed) alongside the existing material_BaseColor declaration in
PlainColorMaterial so the symbol material_AlphaCutoff is defined when
MATERIAL_IS_ALPHA_CUTOFF is used in frag(); update the declarations block that
contains material_BaseColor in the PlainColorMaterial shader source to include
this new material_AlphaCutoff declaration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 78ef16c9-8467-485a-b6e1-3ee71a879b91

📥 Commits

Reviewing files that changed from the base of the PR and between e6f912e and 18253f4.

⛔ Files ignored due to path filters (3)
  • packages/custom-material/src/advanced-shader/eye/EyeForwardPass.glsl is excluded by !**/*.glsl
  • packages/custom-material/src/advanced-shader/hair/HairForwardPass.glsl is excluded by !**/*.glsl
  • packages/custom-material/src/advanced-shader/sss/SSSForwardPass.glsl is excluded by !**/*.glsl
📒 Files selected for processing (11)
  • packages/controls/src/box-selection/BoxSelectionSSMaterial.ts
  • packages/custom-material/src/plain-color/PlainColorMaterial.ts
  • packages/custom-material/src/water/WaterMaterial.ts
  • packages/custom-material/src/water/WaterRippleMaterial.ts
  • packages/custom-material/src/water/WaterfallMaterial.ts
  • packages/framebuffer-picker/src/FramebufferPicker.ts
  • packages/geometry-sketch/src/material/TBNMaterial.ts
  • packages/geometry-sketch/src/material/WireframeMaterial.ts
  • packages/gizmo/src/icon/IconMaterial.ts
  • packages/outline/src/OutlineManager.ts
  • packages/skeleton-viewer/src/SkeletonViewer.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/controls/src/box-selection/BoxSelectionSSMaterial.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/outline/src/OutlineManager.ts
  • packages/framebuffer-picker/src/FramebufferPicker.ts
  • packages/custom-material/src/water/WaterfallMaterial.ts
  • packages/geometry-sketch/src/material/WireframeMaterial.ts
  • packages/gizmo/src/icon/IconMaterial.ts
  • packages/geometry-sketch/src/material/TBNMaterial.ts

Comment on lines +22 to +56
Varyings vert(Attributes attr) {
Varyings v;
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);

#ifdef RENDERER_HAS_UV
v.waterTexCoords = attr.TEXCOORD_0 + vec2(u_water_speed.x * sin(u_time), u_water_speed.y * cos(u_time));
v.normalTexCoords = attr.TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
#endif

#ifdef RENDERER_ENABLE_VERTEXCOLOR
v.v_color = attr.COLOR_0;
#endif
return v;
}

#include "Common/Common.glsl"

sampler2D material_NormalTexture;
sampler2D u_waterTex;
sampler2D u_edgeTex;

vec4 u_edgeColor;
vec2 u_edgeParam;
float u_distorsion_amount;

void frag(Varyings v) {
vec4 normalTex = texture2D(material_NormalTexture, v.normalTexCoords) * 2.0 - 1.0;
vec4 waterTex = texture2D(u_waterTex, v.waterTexCoords + (normalTex.rg * u_distorsion_amount));
vec4 edgeTex = texture2D(u_edgeTex, v.waterTexCoords + (normalTex.rg * u_distorsion_amount));

float edge = pow((v.v_color.r + edgeTex.r) * v.v_color.r, 2.0);
edge = saturate(1.0 - smoothstep(u_edgeParam.x - u_edgeParam.y, u_edgeParam.x + u_edgeParam.y, edge));
vec4 finalCol = mix(waterTex, u_edgeColor, edge);

gl_FragColor = finalCol;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "WaterMaterial.ts" -type f

Repository: galacean/engine-toolkit

Length of output: 120


🏁 Script executed:

cat -n packages/custom-material/src/water/WaterMaterial.ts | head -100

Repository: galacean/engine-toolkit

Length of output: 3987


🏁 Script executed:

# Check if there are other shader files using similar patterns to understand the convention
find . -name "*.ts" -path "*/material*" -type f | head -10

Repository: galacean/engine-toolkit

Length of output: 489


🏁 Script executed:

cat -n packages/custom-material/src/water/WaterMaterial.ts | sed -n '47,60p'

Repository: galacean/engine-toolkit

Length of output: 789


🏁 Script executed:

# Check other shader files to see if they use similar patterns or guard against undefined varyings
grep -r "Varyings\|struct.*{" packages/geometry-sketch/src/material/*.ts packages/lines/src/line/material/*.ts -A 5 | head -50

Repository: galacean/engine-toolkit

Length of output: 4250


Initialize varyings to defaults before conditional assignment.

The vert() function conditionally initializes waterTexCoords, normalTexCoords (lines 27–28 under RENDERER_HAS_UV), and v_color (line 32 under RENDERER_ENABLE_VERTEXCOLOR), but frag() unconditionally reads all three varyings (lines 48–52). When these macros are absent, varyings propagate undefined values to the fragment shader, causing unpredictable rendering.

Initialize all varyings to defaults at the start of vert():

Varyings vert(Attributes attr) {
  Varyings v;
  v.v_color = vec4(1.0);
  v.waterTexCoords = vec2(0.0);
  v.normalTexCoords = vec2(0.0);
  gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
  // ... rest of function
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/water/WaterMaterial.ts` around lines 22 - 56,
The vert(Attributes attr) function leaves v.v_color, v.waterTexCoords and
v.normalTexCoords uninitialized when RENDERER_HAS_UV/RENDERER_ENABLE_VERTEXCOLOR
are not defined, while frag() always reads those varyings (v.v_color,
v.waterTexCoords, v.normalTexCoords); to fix, set safe default values at the
start of Varyings vert(Attributes attr) (e.g. v.v_color = vec4(1.0),
v.waterTexCoords = vec2(0.0), v.normalTexCoords = vec2(0.0)) before any
conditional assignments so the fragment shader always receives defined values.

Comment on lines +22 to +51
Varyings vert(Attributes attr) {
Varyings v;
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
#ifdef RENDERER_HAS_UV
v.waterTexCoords = attr.TEXCOORD_0 + vec2(u_foam_speed.x * u_time, u_foam_speed.y * u_time);
v.normalTexCoords = attr.TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
#endif
#ifdef RENDERER_ENABLE_VERTEXCOLOR
v.v_color = attr.COLOR_0;
#endif
return v;
}

#include "Common/Common.glsl"

sampler2D material_NormalTexture;
sampler2D u_foamTex;
vec3 u_foamColor;
vec2 u_foam_param;
float u_distorsion_amount;

void frag(Varyings v) {
vec4 normalTex = texture2D(material_NormalTexture, v.normalTexCoords) * 2.0 - 1.0;
vec4 waterTex = texture2D(u_foamTex, v.waterTexCoords + (normalTex.rg * u_distorsion_amount));
float alphaComp = v.v_color.r * waterTex.r * u_foam_param.x;
float alpha = pow(alphaComp, 2.0);
alpha = smoothstep(0.5 - u_foam_param.y, 0.5 + u_foam_param.y, alpha);
alpha = saturate(alpha);

gl_FragColor = vec4(u_foamColor.rgb, alpha);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -path "*/packages/custom-material/src/water/WaterRippleMaterial.ts" -type f

Repository: galacean/engine-toolkit

Length of output: 126


🏁 Script executed:

cat -n ./packages/custom-material/src/water/WaterRippleMaterial.ts

Repository: galacean/engine-toolkit

Length of output: 6177


🏁 Script executed:

rg "RENDERER_HAS_UV|RENDERER_ENABLE_VERTEXCOLOR" --type glsl -A 2 -B 2

Repository: galacean/engine-toolkit

Length of output: 95


🏁 Script executed:

rg "RENDERER_HAS_UV|RENDERER_ENABLE_VERTEXCOLOR" -A 2 -B 2 --max-count=20

Repository: galacean/engine-toolkit

Length of output: 9311


🏁 Script executed:

cat -n ./packages/custom-material/src/water/WaterMaterial.ts | head -60

Repository: galacean/engine-toolkit

Length of output: 2375


🏁 Script executed:

cat -n ./packages/custom-material/src/water/WaterfallMaterial.ts | head -70

Repository: galacean/engine-toolkit

Length of output: 2942


🏁 Script executed:

rg "struct Varyings" -A 10 packages/custom-material/src/water/ | head -80

Repository: galacean/engine-toolkit

Length of output: 2818


Initialize varyings to prevent undefined behavior when conditionals are disabled.

v.normalTexCoords, v.waterTexCoords, and v.v_color are only assigned when RENDERER_HAS_UV or RENDERER_ENABLE_VERTEXCOLOR are enabled (lines 25–31), but are unconditionally read in the fragment shader (lines 44–46). When these macros are disabled, undefined values propagate to the fragment shader, causing unstable foam rendering that may vary across GPUs.

Initialize all varyings to safe defaults before the conditional blocks:

Suggested fix
       Varyings vert(Attributes attr) {
         Varyings v;
+        v.waterTexCoords = vec2(0.0);
+        v.normalTexCoords = vec2(0.0);
+        v.v_color = vec4(1.0);
         gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
         `#ifdef` RENDERER_HAS_UV
           v.waterTexCoords = attr.TEXCOORD_0 + vec2(u_foam_speed.x * u_time, u_foam_speed.y * u_time);
           v.normalTexCoords = attr.TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Varyings vert(Attributes attr) {
Varyings v;
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
#ifdef RENDERER_HAS_UV
v.waterTexCoords = attr.TEXCOORD_0 + vec2(u_foam_speed.x * u_time, u_foam_speed.y * u_time);
v.normalTexCoords = attr.TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
#endif
#ifdef RENDERER_ENABLE_VERTEXCOLOR
v.v_color = attr.COLOR_0;
#endif
return v;
}
#include "Common/Common.glsl"
sampler2D material_NormalTexture;
sampler2D u_foamTex;
vec3 u_foamColor;
vec2 u_foam_param;
float u_distorsion_amount;
void frag(Varyings v) {
vec4 normalTex = texture2D(material_NormalTexture, v.normalTexCoords) * 2.0 - 1.0;
vec4 waterTex = texture2D(u_foamTex, v.waterTexCoords + (normalTex.rg * u_distorsion_amount));
float alphaComp = v.v_color.r * waterTex.r * u_foam_param.x;
float alpha = pow(alphaComp, 2.0);
alpha = smoothstep(0.5 - u_foam_param.y, 0.5 + u_foam_param.y, alpha);
alpha = saturate(alpha);
gl_FragColor = vec4(u_foamColor.rgb, alpha);
Varyings vert(Attributes attr) {
Varyings v;
v.waterTexCoords = vec2(0.0);
v.normalTexCoords = vec2(0.0);
v.v_color = vec4(1.0);
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
`#ifdef` RENDERER_HAS_UV
v.waterTexCoords = attr.TEXCOORD_0 + vec2(u_foam_speed.x * u_time, u_foam_speed.y * u_time);
v.normalTexCoords = attr.TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
`#endif`
`#ifdef` RENDERER_ENABLE_VERTEXCOLOR
v.v_color = attr.COLOR_0;
`#endif`
return v;
}
`#include` "Common/Common.glsl"
sampler2D material_NormalTexture;
sampler2D u_foamTex;
vec3 u_foamColor;
vec2 u_foam_param;
float u_distorsion_amount;
void frag(Varyings v) {
vec4 normalTex = texture2D(material_NormalTexture, v.normalTexCoords) * 2.0 - 1.0;
vec4 waterTex = texture2D(u_foamTex, v.waterTexCoords + (normalTex.rg * u_distorsion_amount));
float alphaComp = v.v_color.r * waterTex.r * u_foam_param.x;
float alpha = pow(alphaComp, 2.0);
alpha = smoothstep(0.5 - u_foam_param.y, 0.5 + u_foam_param.y, alpha);
alpha = saturate(alpha);
gl_FragColor = vec4(u_foamColor.rgb, alpha);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/water/WaterRippleMaterial.ts` around lines 22 -
51, The Varyings struct fields used in frag (v.normalTexCoords,
v.waterTexCoords, v.v_color) are only set inside conditional blocks in vert and
can be left uninitialized when RENDERER_HAS_UV or RENDERER_ENABLE_VERTEXCOLOR
are disabled; update vert(Attributes attr) to initialize v.normalTexCoords,
v.waterTexCoords, and v.v_color to safe defaults (e.g., zero vec2/vec4 or
neutral values) before the `#ifdef` blocks so frag() always reads defined values
and avoids undefined behavior.

Comment on lines +29 to +49
struct Varyings {
vec3 v_normal;
};

Varyings vert(Attributes attr) {
Varyings v;
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
#ifdef RENDERER_HAS_NORMAL
v.v_normal = normalize( mat3(renderer_NormalMat) * attr.NORMAL );
#endif
return v;
}

vec3 u_colorMin;
vec3 u_colorMax;

void frag(Varyings v) {
float ndl = dot(v.v_normal, vec3(0, 1, 0)) * 0.5 + 0.5;
vec3 diffuse = mix(u_colorMin, u_colorMax, ndl);
gl_FragColor = vec4(diffuse, 1.0);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unguarded read of v_normal when RENDERER_HAS_NORMAL is not defined.

v.v_normal is only written inside #ifdef RENDERER_HAS_NORMAL (Line 36–38), but frag unconditionally uses it in dot(v.v_normal, vec3(0, 1, 0)) (Line 46). When the renderer/mesh lacks a normal attribute, the varying is undefined, producing garbage shading (and on some drivers, NaNs).

Since _createSpur/PrimitiveMesh.createSphere both upload normals, the skeleton viewer's own meshes will set this macro; but the failure mode is silent if that ever changes. Either guard the frag read symmetrically or supply a safe default.

🛡️ Proposed fix
       Varyings vert(Attributes attr) {
         Varyings v;
         gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
         `#ifdef` RENDERER_HAS_NORMAL
           v.v_normal = normalize( mat3(renderer_NormalMat) * attr.NORMAL );
+        `#else`
+          v.v_normal = vec3(0.0, 1.0, 0.0);
         `#endif`
         return v;
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
struct Varyings {
vec3 v_normal;
};
Varyings vert(Attributes attr) {
Varyings v;
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
#ifdef RENDERER_HAS_NORMAL
v.v_normal = normalize( mat3(renderer_NormalMat) * attr.NORMAL );
#endif
return v;
}
vec3 u_colorMin;
vec3 u_colorMax;
void frag(Varyings v) {
float ndl = dot(v.v_normal, vec3(0, 1, 0)) * 0.5 + 0.5;
vec3 diffuse = mix(u_colorMin, u_colorMax, ndl);
gl_FragColor = vec4(diffuse, 1.0);
}
struct Varyings {
vec3 v_normal;
};
Varyings vert(Attributes attr) {
Varyings v;
gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
`#ifdef` RENDERER_HAS_NORMAL
v.v_normal = normalize( mat3(renderer_NormalMat) * attr.NORMAL );
`#else`
v.v_normal = vec3(0.0, 1.0, 0.0);
`#endif`
return v;
}
vec3 u_colorMin;
vec3 u_colorMax;
void frag(Varyings v) {
float ndl = dot(v.v_normal, vec3(0, 1, 0)) * 0.5 + 0.5;
vec3 diffuse = mix(u_colorMin, u_colorMax, ndl);
gl_FragColor = vec4(diffuse, 1.0);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/skeleton-viewer/src/SkeletonViewer.ts` around lines 29 - 49, The
frag shader reads v.v_normal unconditionally while vert only writes it when
RENDERER_HAS_NORMAL is defined, so make the usage symmetric: either initialize
v.v_normal with a safe default in Varyings/vert (e.g., set v.v_normal =
vec3(0,1,0) before the `#ifdef` in the vert function) or wrap the dot() and
related code in frag with `#ifdef` RENDERER_HAS_NORMAL to provide a fallback
diffuse (use a constant color or compute ndl=1.0). Update the Varyings
struct/vert/frag symbols (Varyings, vert, frag, v_normal, RENDERER_HAS_NORMAL)
accordingly so v.v_normal is never read uninitialized.

Replace the custom rollup-plugin-glslify + rollup-plugin-string pair with the
unified `shaderCompiler({ precompile })` plugin from
`@galacean/engine-shader-compiler/bundler`. Build now produces precompiled
`.gsp` artifacts under `packages/custom-material/libs/` (Eye, Hair, SSS, Grid,
PlanarShadow), mirroring the engine repo's shader build flow.

ShaderLab syntax fixes uncovered by the strict precompile pass:
- `struct Foo { ... }` requires a trailing semicolon
- Render state blocks need `=` (`DepthState = { ... }`, `StencilState = { ... }`)
- `RenderQueueType = RenderQueueType.Transparent` → `RenderQueueType = Transparent`
- PlanarShadow vert function: add missing `return o;` and move
  `VertexShader=`/`FragmentShader=` declarations to top-of-pass

Rename `Eye.gs`/`Hair.gs`/`SSS.gs` to `.shader` so the new bundler picks them
up. Drop `rollup-plugin-glslify` and `rollup-plugin-string` from devDeps.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
package.json (1)

27-27: Pin the shader compiler to a tested version.

>=2.0.0-0 will accept any future compiler release, including new majors, so fresh installs can silently change the generated .gsp output or break the bundler path. For build tooling, use the exact version validated with this PR (or at least a bounded ^2.0.0-0 range).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 27, The dependency "@galacean/engine-shader-compiler"
in package.json is too permissive (">=2.0.0-0"); change it to a pinned or
bounded version tested with this PR (e.g., an exact version "2.0.0-0" or a
bounded range like "^2.0.0-0") so installs produce consistent .gsp outputs and
bundler paths; update the value for the "@galacean/engine-shader-compiler" entry
in package.json and run your install/build to verify the validated version is
used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/custom-material/libs/advanced-shader/eye/Eye.gsp`:
- Line 1: The SurfaceData struct used in the fragment shader is missing the f0
member but later the shader assigns surfaceData.f0 = 0.04 in main; add a float
f0; declaration to the SurfaceData struct (the struct named SurfaceData in the
fragment shader, referenced by getSurfaceData and used in main) so the
assignment is valid and the shader compiles.

In `@packages/custom-material/libs/advanced-shader/hair/Hair.gsp`:
- Line 1: The SurfaceData struct in the generated fragment shaders is missing
the float f0 field while the code assigns surfaceData.f0 = 0.04, causing GLSL
compile errors; add a declaration "float f0;" to the SurfaceData struct in the
Hair, Eye, and SSS shader templates (the SurfaceData struct definitions used by
Hair.gsp / HairForwardPass.glsl, Eye.gsp / EyeForwardPass.glsl, and SSS.gsp /
SSSForwardPass.glsl) so the assigned field exists and is consistent with
initBRDFData and usage in fragment main.

In `@packages/custom-material/libs/advanced-shader/sss/SSS.gsp`:
- Line 1: The fragment shader assigns surfaceData.f0 = 0.04 but SurfaceData
struct lacks f0; fix by adding a float f0; field to the SurfaceData definition
(the struct named SurfaceData in the fragment shader) so the assignment is
valid, or alternatively remove the assignment to surfaceData.f0 = 0.04 if
initBRDFData or another routine is expected to compute f0; update whichever is
appropriate (SurfaceData struct or the assignment near initialization before
initBRDFData) to resolve the GLSL compile error.

In `@packages/custom-material/libs/grid/Grid.gsp`:
- Line 1: The vertex shader is missing the uniform declaration for
camera_ProjMat used by INVERSE_MAT(camera_ProjMat); add a uniform mat4
camera_ProjMat; declaration alongside camera_ViewInvMat in the vertex stage
(where UnprojectPoint and main use camera_ViewInvMat and INVERSE_MAT) so
INVERSE_MAT(camera_ProjMat) compiles correctly.

In `@packages/custom-material/libs/planar-shadow/PlanarShadow.gsp`:
- Line 1: The planar-shadow .gsp changes are ignored because planarShadowShader
in PlanarShadowShaderFactory (built via the inline pass +
Shader.find("PBR").subShaders[0].passes[2]) never uses PlanarShadowSource;
update the factory (symbol: planarShadowShader in PlanarShadowShaderFactory.ts)
to load/compile the PlanarShadowSource content instead of hardcoding that inline
pass — e.g., replace the inline pass composition that references
Shader.find("PBR").subShaders[0].passes[2] with a path that consumes
PlanarShadowSource (or registers/uses the GSP by name) so the shader creation
uses the generated .gsp output.

In `@rollup.config.mjs`:
- Around line 46-50: The shaderCompiler plugin is currently added globally and
will run for every package build; instead, remove the hardcoded
shaderCompiler(...) from the shared plugins array and add it only to the
per-package plugin list inside makeRollupConfig when pkg.location ===
"packages/custom-material"; also stop mutating the shared plugins array (the
.push(replace(...)) call) — create a local copy of the base plugins inside
makeRollupConfig (e.g., const localPlugins = [...plugins]) and push/attach
replace(...) and shaderCompiler(...) to localPlugins conditionally, then use
localPlugins for the package-specific Rollup config to avoid cross-package side
effects from shaderCompiler and replace.

---

Nitpick comments:
In `@package.json`:
- Line 27: The dependency "@galacean/engine-shader-compiler" in package.json is
too permissive (">=2.0.0-0"); change it to a pinned or bounded version tested
with this PR (e.g., an exact version "2.0.0-0" or a bounded range like
"^2.0.0-0") so installs produce consistent .gsp outputs and bundler paths;
update the value for the "@galacean/engine-shader-compiler" entry in
package.json and run your install/build to verify the validated version is used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f8f84a51-a262-428e-a677-6371f965a0dc

📥 Commits

Reviewing files that changed from the base of the PR and between 18253f4 and 842e555.

⛔ Files ignored due to path filters (5)
  • packages/custom-material/src/advanced-shader/eye/Eye.shader is excluded by !**/*.shader
  • packages/custom-material/src/advanced-shader/hair/Hair.shader is excluded by !**/*.shader
  • packages/custom-material/src/advanced-shader/sss/SSS.shader is excluded by !**/*.shader
  • packages/custom-material/src/grid/Grid.shader is excluded by !**/*.shader
  • packages/custom-material/src/planar-shadow/PlanarShadow.shader is excluded by !**/*.shader
📒 Files selected for processing (8)
  • package.json
  • packages/custom-material/libs/advanced-shader/eye/Eye.gsp
  • packages/custom-material/libs/advanced-shader/hair/Hair.gsp
  • packages/custom-material/libs/advanced-shader/sss/SSS.gsp
  • packages/custom-material/libs/grid/Grid.gsp
  • packages/custom-material/libs/index.ts
  • packages/custom-material/libs/planar-shadow/PlanarShadow.gsp
  • rollup.config.mjs

Comment thread packages/custom-material/libs/advanced-shader/eye/Eye.gsp Outdated
@@ -0,0 +1 @@
{"name":"DigitalHuman/Hair.gs","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"pbr/Default/ShadowCaster","isUsePass":true,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}}},{"name":"Forward Pass","isUsePass":false,"tags":{"pipelineStage":"Forward"},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[7,"IS_METALLIC_WORKFLOW"],[0,"\n\n"],[2,"FORWARD_PASS_PBR_INCLUDED",587],[0,"\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",35],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",29],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,33],[0,"\nmat2 inverseMat ( mat2 m ) { return mat2 ( m[1][1] , - m[0][1] , - m[1][0] , m[0][0] ) / ( m[0][0] * m[1][1] - m[0][1] * m[1][0] ) ; }\nmat3 inverseMat ( mat3 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] ;\nfloat a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] ;\nfloat a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] ;\nfloat b01 = a22 * a11 - a12 * a21 ;\nfloat b11 = - a22 * a10 + a12 * a20 ;\nfloat b21 = a21 * a10 - a11 * a20 ;\nfloat det = a00 * b01 + a01 * b11 + a02 * b21 ;\nreturn mat3 ( b01 , ( - a22 * a01 + a02 * a21 ) , ( a12 * a01 - a02 * a11 ) , b11 , ( a22 * a00 - a02 * a20 ) , ( - a12 * a00 + a02 * a10 ) , b21 , ( - a21 * a00 + a01 * a20 ) , ( a11 * a00 - a01 * a10 ) ) / det ; }\nmat4 inverseMat ( mat4 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] , a03 = m[0][3] , a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] , a13 = m[1][3] , a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] , a23 = m[2][3] , a30 = m[3][0] , a31 = m[3][1] , a32 = m[3][2] , a33 = m[3][3] , b00 = a00 * a11 - a01 * a10 , b01 = a00 * a12 - a02 * a10 , b02 = a00 * a13 - a03 * a10 , b03 = a01 * a12 - a02 * a11 , b04 = a01 * a13 - a03 * a11 , b05 = a02 * a13 - a03 * a12 , b06 = a20 * a31 - a21 * a30 , b07 = a20 * a32 - a22 * a30 , b08 = a20 * a33 - a23 * a30 , b09 = a21 * a32 - a22 * a31 , b10 = a21 * a33 - a23 * a31 , b11 = a22 * a33 - a23 * a32 , det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06 ;\nreturn mat4 ( a11 * b11 - a12 * b10 + a13 * b09 , a02 * b10 - a01 * b11 - a03 * b09 , a31 * b05 - a32 * b04 + a33 * b03 , a22 * b04 - a21 * b05 - a23 * b03 , a12 * b08 - a10 * b11 - a13 * b07 , a00 * b11 - a02 * b08 + a03 * b07 , a32 * b02 - a30 * b05 - a33 * b01 , a20 * b05 - a22 * b02 + a23 * b01 , a10 * b10 - a11 * b08 + a13 * b06 , a01 * b08 - a00 * b10 - a03 * b06 , a30 * b04 - a31 * b02 + a33 * b00 , a21 * b02 - a20 * b04 - a23 * b00 , a11 * b07 - a10 * b09 - a12 * b06 , a00 * b09 - a01 * b07 + a02 * b06 , a31 * b01 - a30 * b03 - a32 * b00 , a20 * b03 - a21 * b01 + a22 * b00 ) / det ; }\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",45],[0,"\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,43],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",103],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",77],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",75],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},57],[0,"\n"],[5,73],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},69],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",63],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",67],[0,"\n"],[6],[0,"\n"],[5,71],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",81],[0,"attribute vec2 TEXCOORD_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",85],[0,"attribute vec2 TEXCOORD_1;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",89],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",93],[0,"attribute vec4 COLOR_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",97],[0,"attribute vec3 NORMAL;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",101],[0,"attribute vec4 TANGENT;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",133],[0,"\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",111],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",115],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,119],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",127],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",125],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},131],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobehair"],[0,"\n\n"],[2,"BSDF_INCLUDED",193],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",149],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",147],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},159],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",163],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",167],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",171],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",175],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",179],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",183],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",187],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",191],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_HAIRANISOTROPY_TEXTURE",197],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",351],[0,"\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",207],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",213],[0,"\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",219],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",225],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",231],[0,"\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",289],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",245],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",243],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},255],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",259],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",263],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",267],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",271],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",275],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",279],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",283],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",287],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",331],[0,"\n"],[7,"LIGHT_INCLUDED"],[0,"\n\n"],[2,"GRAPHICS_API_WEBGL2",297],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",305],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",303],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",313],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",311],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",321],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",319],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SH",325],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",329],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",337],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",341],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",345],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",349],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",387],[0,"\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",361],[0,"\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",367],[0,"\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",373],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",379],[0,"\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",385],[0,"\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",453],[0,"\n"],[7,"VERTEX_INCLUDE"],[0,"\nstruct VertexInputs { vec4 positionOS ; vec3 positionWS ; \n"],[3,"SCENE_FOG_MODE","!=",0,395],[0," vec3 positionVS ; \n"],[6],[0," \n"],[1,"RENDERER_HAS_NORMAL",403],[0," vec3 normalWS ; \n"],[1,"RENDERER_HAS_TANGENT",401],[0," vec3 tangentWS ; vec3 bitangentWS ; \n"],[6],[0," \n"],[6],[0," } ;\nuniform vec4 material_TilingOffset;\nvec2 getUV0 ( ) { vec2 uv0 = vec2 ( 0 ) ;\n\n"],[1,"RENDERER_HAS_UV",407],[0," uv0 = TEXCOORD_0 ; \n"],[6],[0,"\nreturn uv0 * material_TilingOffset.xy + material_TilingOffset.zw ; }\nVertexInputs getVertexInputs ( ) { VertexInputs inputs ;\nvec4 position = vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",415],[0," vec3 normal = vec3 ( NORMAL ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",413],[0," vec4 tangent = vec4 ( TANGENT ) ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",427],[0," calculateBlendShape ( attributes , position \n"],[1,"RENDERER_HAS_NORMAL",425],[0," , normal \n"],[1,"RENDERER_HAS_TANGENT",423],[0," , tangent \n"],[6],[0," \n"],[6],[0," ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",439],[0," mat4 skinMatrix = getSkinMatrix ( attributes ) ;\nposition = skinMatrix * position ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},437],[0," mat3 skinNormalMatrix = INVERSE_MAT(mat3 ( skinMatrix )) ;\nnormal = normal * skinNormalMatrix ;\n\n"],[1,"RENDERER_HAS_TANGENT",435],[0," tangent.xyz = tangent.xyz * skinNormalMatrix ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},447],[0," inputs.normalWS = normalize ( mat3 ( renderer_NormalMat ) * normal ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",445],[0," vec3 tangentWS = normalize ( mat3 ( renderer_NormalMat ) * tangent.xyz ) ;\nvec3 bitangentWS = cross ( inputs.normalWS , tangentWS ) * tangent.w ;\ninputs.tangentWS = tangentWS ;\ninputs.bitangentWS = bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\ninputs.positionOS = position ;\nvec4 positionWS = renderer_ModelMat * position ;\ninputs.positionWS = positionWS.xyz / positionWS.w ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,451],[0," vec4 positionVS = renderer_MVMat * position ;\ninputs.positionVS = positionVS.xyz / positionVS.w ; \n"],[6],[0,"\nreturn inputs ; }\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",561],[0,"\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",463],[0,"\n"],[7,"NORMAL_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",467],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",471],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",487],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",477],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",481],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",485],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",495],[0,"\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",493],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",507],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",501],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",505],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",519],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",513],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",517],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",535],[0,"\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",525],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",533],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",531],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",539],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",543],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",547],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",551],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",555],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",559],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid main() { \nuv = getUV0() ;\n\n"],[1,"RENDERER_HAS_UV1",565],[0," uv1 = TEXCOORD_1 ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",569],[0," vertexColor = COLOR_0 ; \n"],[6],[0,"\nVertexInputs vertexInputs = getVertexInputs() ;\npositionWS = vertexInputs.positionWS ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,573],[0," positionVS = vertexInputs.positionVS ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",581],[0," normalWS = vertexInputs.normalWS ;\n\n"],[1,"RENDERER_HAS_TANGENT",579],[0," tangentWS = vertexInputs.tangentWS ;\nbitangentWS = vertexInputs.bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},585],[0," shadowCoord = getShadowCoord ( vertexInputs.positionWS ) ; \n"],[6],[0,"\ngl_Position = renderer_MVPMat * vertexInputs.positionOS ;\n }\n\n"],[6]],"fragmentShaderInstructions":[[7,"IS_METALLIC_WORKFLOW"],[0,"\n\n"],[2,"FORWARD_PASS_PBR_INCLUDED",788],[0,"\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",39],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\nfloat pow2 ( float x ) { return x * x ; }\nfloat sRGBToLinear ( float value ) { float linearRGBLo = value / 12.92 ;\nfloat linearRGBHi = pow ( ( value + 0.055 ) / 1.055 , 2.4 ) ;\nfloat linearRGB = ( value <= 0.04045 ) ? linearRGBLo : linearRGBHi ;\nreturn linearRGB ; }\nvec4 sRGBToLinear ( vec4 value ) { return vec4 ( sRGBToLinear(value.r) , sRGBToLinear(value.g) , sRGBToLinear(value.b) , value.a ) ; }\nvec4 texture2DSRGB ( sampler2D tex, vec2 uv ) { vec4 color = texture2D ( tex , uv ) ;\n\n"],[1,"ENGINE_NO_SRGB",27],[0," color = sRGBToLinear(color) ; \n"],[6],[0,"\nreturn color ; }\nuniform vec4 camera_ProjectionParams;\n\n"],[1,"GRAPHICS_API_WEBGL2",33],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,37],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",59],[0,"\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,57],[0,"\nuniform vec4 scene_FogColor;\nuniform vec4 scene_FogParams;\nvec4 fog ( vec4 color, vec3 positionVS ) { float fogDepth = length ( positionVS ) ;\n\n"],[3,"SCENE_FOG_MODE","==",1,49],[0," float fogIntensity = clamp ( fogDepth * scene_FogParams.x + scene_FogParams.y , 0.0 , 1.0 ) ; \n"],[5,55],[3,"SCENE_FOG_MODE","==",2,52],[0," float fogIntensity = clamp ( exp2 ( - fogDepth * scene_FogParams.z ) , 0.0 , 1.0 ) ; \n"],[5,55],[3,"SCENE_FOG_MODE","==",3,55],[0," float factor = fogDepth * scene_FogParams.w ;\nfloat fogIntensity = clamp ( exp2 ( - factor * factor ) , 0.0 , 1.0 ) ; \n"],[6],[0,"\ncolor.rgb = mix ( scene_FogColor.rgb , color.rgb , fogIntensity ) ;\nreturn color ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",65],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",95],[0,"\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",73],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",77],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,81],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",89],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",87],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},93],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"varying vec4 positionCS;\n\n\n"],[6],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobehair"],[0,"\n\n"],[2,"BSDF_INCLUDED",189],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",111],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",109],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},121],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",125],[0,"\n\n"],[6],[0,"\nstruct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; \n"],[1,"NEED_TANGENT",129],[0," vec3 tangent ; vec3 bitangent ; \n"],[6],[0," vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",133],[0," float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",137],[0," float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",141],[0," float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",145],[0," float sheenRoughness ; vec3 sheenColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_TRANSMISSION",149],[0," vec3 absorptionCoefficient ; float transmission ; float thickness ; \n"],[6],[0," } ;\nfloat F_Schlick ( float f0, float f90, float dotLH ) { return f0 + ( f90 - f0 ) * ( pow ( 1.0 - dotLH , 5.0 ) ) ; }\nvec3 F_Schlick ( vec3 f0, float f90, float dotLH ) { float fresnel = exp2 ( ( - 5.55473 * dotLH - 6.98316 ) * dotLH ) ;\nreturn ( f90 - f0 ) * fresnel + f0 ; }\nfloat G_GGX_SmithCorrelated ( float alpha, float dotNL, float dotNV ) { float a2 = pow2(alpha) ;\nfloat gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNV) ) ;\nfloat gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNL) ) ;\nreturn 0.5 / max ( gv + gl , EPSILON ) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",153],[0,"\nfloat G_GGX_SmithCorrelated_Anisotropic ( float at, float ab, float ToV, float BoV, float ToL, float BoL, float NoV, float NoL ) { float lambdaV = NoL * length ( vec3 ( at * ToV , ab * BoV , NoV ) ) ;\nfloat lambdaL = NoV * length ( vec3 ( at * ToL , ab * BoL , NoL ) ) ;\nreturn 0.5 / max ( lambdaV + lambdaL , EPSILON ) ; }\n\n"],[6],[0,"\nfloat D_GGX ( float alpha, float dotNH ) { float a2 = pow2(alpha) ;\nfloat denom = pow2(dotNH) * ( a2 - 1.0 ) + 1.0 ;\nreturn RECIPROCAL_PI * a2 / pow2(denom) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",157],[0,"\nfloat D_GGX_Anisotropic ( float at, float ab, float ToH, float BoH, float NoH ) { float a2 = at * ab ;\nhighp vec3 d = vec3 ( ab * ToH , at * BoH , a2 * NoH ) ;\nhighp float d2 = dot ( d , d ) ;\nfloat b2 = a2 / d2 ;\nreturn a2 * b2 * b2 * RECIPROCAL_PI ; }\n\n"],[6],[0,"\nfloat DG_GGX ( float alpha, float dotNV, float dotNL, float dotNH ) { float D = D_GGX(alpha, dotNH) ;\nfloat G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV) ;\nreturn G * D ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",161],[0,"\nfloat DG_GGX_anisotropic ( vec3 h, vec3 l, SurfaceData surfaceData, float alpha, float dotNV, float dotNL, float dotNH ) { vec3 t = surfaceData.anisotropicT ;\nvec3 b = surfaceData.anisotropicB ;\nvec3 v = surfaceData.viewDir ;\nfloat dotTV = dot ( t , v ) ;\nfloat dotBV = dot ( b , v ) ;\nfloat dotTL = dot ( t , l ) ;\nfloat dotBL = dot ( b , l ) ;\nfloat dotTH = dot ( t , h ) ;\nfloat dotBH = dot ( b , h ) ;\nfloat at = max ( alpha * ( 1.0 + surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat ab = max ( alpha * ( 1.0 - surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat D = D_GGX_Anisotropic(at, ab, dotTH, dotBH, dotNH) ;\nfloat G = G_GGX_SmithCorrelated_Anisotropic(at, ab, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL) ;\nreturn G * D ; }\n\n"],[6],[0,"\nvec3 BRDF_Specular_GGX ( vec3 incidentDirection, SurfaceData surfaceData, BSDFData bsdfData, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2(roughness) ;\nvec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( normal , incidentDirection )) ;\nfloat dotNV = saturate(dot ( normal , surfaceData.viewDir )) ;\nfloat dotNH = saturate(dot ( normal , halfDir )) ;\nfloat dotLH = saturate(dot ( incidentDirection , halfDir )) ;\nvec3 F = F_Schlick(specularColor, bsdfData.specularF90, dotLH) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",165],[0," F = mix ( F , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",169],[0," float GD = DG_GGX_anisotropic(halfDir, incidentDirection, surfaceData, alpha, dotNV, dotNL, dotNH) ; \n"],[5,171],[0," float GD = DG_GGX(alpha, dotNV, dotNL, dotNH) ; \n"],[6],[0,"\nreturn F * GD ; }\nvec3 BRDF_Diffuse_Lambert ( vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor ; }\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",175],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",179],[0,"\nfloat D_Charlie ( float roughness, float dotNH ) { float invAlpha = 1.0 / roughness ;\nfloat cos2h = dotNH * dotNH ;\nfloat sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;\nreturn ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ; }\nfloat V_Neubelt ( float NoV, float NoL ) { return saturate(1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) )) ; }\nvec3 sheenBRDF ( vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness ) { vec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nfloat dotNH = saturate(dot ( surfaceData.normal , halfDir )) ;\nfloat D = D_Charlie(sheenRoughness, dotNH) ;\nfloat V = V_Neubelt(surfaceData.dotNV, dotNL) ;\nvec3 F = sheenColor ;\nreturn D * V * F ; }\n\n"],[6],[0,"\nvec2 envDFGApprox ( float roughness, float dotNV ) { const vec4 c0 = vec4 ( - 1 , - 0.0275 , - 0.572 , 0.022 ) ;\nconst vec4 c1 = vec4 ( 1 , 0.0425 , 1.04 , - 0.04 ) ;\nvec4 r = roughness * c0 + c1 ;\nfloat a004 = min ( r.x * r.x , exp2 ( - 9.28 * dotNV ) ) * r.x + r.y ;\nreturn vec2 ( - 1.04 , 1.04 ) * a004 + r.zw ; }\nvec3 envBRDFApprox ( vec3 f0, float f90, float roughness, float dotNV ) { vec2 AB = envDFGApprox(roughness, dotNV) ;\nreturn f0 * AB.x + f90 * AB.y ; }\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",183],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",187],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nuniform float material_HairFirstWidth;\nuniform float material_HairSecondWidth;\nuniform float material_HairFirstStrength;\nuniform float material_HairSecondStrength;\nuniform float material_HairFirstOffset;\nuniform float material_HairSecondOffset;\nuniform vec4 material_HairFirstColor;\nuniform vec4 material_HairSecondColor;\n\n"],[1,"MATERIAL_HAS_HAIRANISOTROPY_TEXTURE",193],[0,"\nuniform sampler2D material_HairAnisotropyTexture;\n\n"],[6],[0,"\nvec3 shiftTangent ( vec3 tangent, vec3 normal, float shift ) { return ( normalize ( tangent + normal * shift ) ) ; }\nfloat anisotropySpecular ( SurfaceData surfaceData, vec3 light, float width, float strength, vec3 shiftedTangent ) { vec3 v = surfaceData.viewDir ;\nvec3 H = normalize ( light + v ) ;\nfloat dotTH = dot ( shiftedTangent , H ) ;\nfloat sinTH = sqrt ( 1.0 - dotTH * dotTH ) ;\nfloat dirAtten = smoothstep ( - 1.0 , 0.0 , dotTH ) ;\nreturn dirAtten * pow ( sinTH , width ) * strength ; }\nvoid specularLobehair ( SurfaceData surfaceData, BRDFData brdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor ) { vec3 worldtangentDir = surfaceData.tangent ;\nvec3 worldbitangentDir = surfaceData.bitangent ;\n\n"],[1,"MATERIAL_HAS_HAIRANISOTROPY_TEXTURE",197],[0," float shift = texture2D ( material_HairAnisotropyTexture , uv ).r - 0.5 ; \n"],[5,199],[0," float shift = 1.0 ; \n"],[6],[0,"\nvec3 shiftTangent1 = shiftTangent(worldbitangentDir, surfaceData.normal, shift + material_HairFirstOffset) ;\nvec3 shiftTangent2 = shiftTangent(worldbitangentDir, surfaceData.normal, shift + material_HairSecondOffset) ;\nvec3 firstcol = material_HairFirstColor.rgb ;\nvec3 firstSpecular = firstcol * anisotropySpecular(surfaceData, incidentDirection, material_HairFirstWidth * 15.0, material_HairFirstStrength, shiftTangent1) ;\nvec3 secondcol = material_HairSecondColor.rgb ;\nvec3 secondSpecular = secondcol * anisotropySpecular(surfaceData, incidentDirection, material_HairSecondWidth * 15.0, material_HairSecondStrength, shiftTangent2) ;\nvec3 hairSpecular = clamp ( firstSpecular + secondSpecular , 0.0 , 1.0 ) ;\nspecularColor += attenuationIrradiance * hairSpecular ; }\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",435],[0,"\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",209],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",215],[0,"\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",221],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",227],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",233],[0,"\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",325],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",247],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",245],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},257],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",261],[0,"\n\n"],[6],[0,"\nstruct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; \n"],[1,"NEED_TANGENT",265],[0," vec3 tangent ; vec3 bitangent ; \n"],[6],[0," vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",269],[0," float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",273],[0," float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",277],[0," float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",281],[0," float sheenRoughness ; vec3 sheenColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_TRANSMISSION",285],[0," vec3 absorptionCoefficient ; float transmission ; float thickness ; \n"],[6],[0," } ;\nfloat F_Schlick ( float f0, float f90, float dotLH ) { return f0 + ( f90 - f0 ) * ( pow ( 1.0 - dotLH , 5.0 ) ) ; }\nvec3 F_Schlick ( vec3 f0, float f90, float dotLH ) { float fresnel = exp2 ( ( - 5.55473 * dotLH - 6.98316 ) * dotLH ) ;\nreturn ( f90 - f0 ) * fresnel + f0 ; }\nfloat G_GGX_SmithCorrelated ( float alpha, float dotNL, float dotNV ) { float a2 = pow2(alpha) ;\nfloat gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNV) ) ;\nfloat gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNL) ) ;\nreturn 0.5 / max ( gv + gl , EPSILON ) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",289],[0,"\nfloat G_GGX_SmithCorrelated_Anisotropic ( float at, float ab, float ToV, float BoV, float ToL, float BoL, float NoV, float NoL ) { float lambdaV = NoL * length ( vec3 ( at * ToV , ab * BoV , NoV ) ) ;\nfloat lambdaL = NoV * length ( vec3 ( at * ToL , ab * BoL , NoL ) ) ;\nreturn 0.5 / max ( lambdaV + lambdaL , EPSILON ) ; }\n\n"],[6],[0,"\nfloat D_GGX ( float alpha, float dotNH ) { float a2 = pow2(alpha) ;\nfloat denom = pow2(dotNH) * ( a2 - 1.0 ) + 1.0 ;\nreturn RECIPROCAL_PI * a2 / pow2(denom) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",293],[0,"\nfloat D_GGX_Anisotropic ( float at, float ab, float ToH, float BoH, float NoH ) { float a2 = at * ab ;\nhighp vec3 d = vec3 ( ab * ToH , at * BoH , a2 * NoH ) ;\nhighp float d2 = dot ( d , d ) ;\nfloat b2 = a2 / d2 ;\nreturn a2 * b2 * b2 * RECIPROCAL_PI ; }\n\n"],[6],[0,"\nfloat DG_GGX ( float alpha, float dotNV, float dotNL, float dotNH ) { float D = D_GGX(alpha, dotNH) ;\nfloat G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV) ;\nreturn G * D ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",297],[0,"\nfloat DG_GGX_anisotropic ( vec3 h, vec3 l, SurfaceData surfaceData, float alpha, float dotNV, float dotNL, float dotNH ) { vec3 t = surfaceData.anisotropicT ;\nvec3 b = surfaceData.anisotropicB ;\nvec3 v = surfaceData.viewDir ;\nfloat dotTV = dot ( t , v ) ;\nfloat dotBV = dot ( b , v ) ;\nfloat dotTL = dot ( t , l ) ;\nfloat dotBL = dot ( b , l ) ;\nfloat dotTH = dot ( t , h ) ;\nfloat dotBH = dot ( b , h ) ;\nfloat at = max ( alpha * ( 1.0 + surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat ab = max ( alpha * ( 1.0 - surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat D = D_GGX_Anisotropic(at, ab, dotTH, dotBH, dotNH) ;\nfloat G = G_GGX_SmithCorrelated_Anisotropic(at, ab, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL) ;\nreturn G * D ; }\n\n"],[6],[0,"\nvec3 BRDF_Specular_GGX ( vec3 incidentDirection, SurfaceData surfaceData, BSDFData bsdfData, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2(roughness) ;\nvec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( normal , incidentDirection )) ;\nfloat dotNV = saturate(dot ( normal , surfaceData.viewDir )) ;\nfloat dotNH = saturate(dot ( normal , halfDir )) ;\nfloat dotLH = saturate(dot ( incidentDirection , halfDir )) ;\nvec3 F = F_Schlick(specularColor, bsdfData.specularF90, dotLH) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",301],[0," F = mix ( F , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",305],[0," float GD = DG_GGX_anisotropic(halfDir, incidentDirection, surfaceData, alpha, dotNV, dotNL, dotNH) ; \n"],[5,307],[0," float GD = DG_GGX(alpha, dotNV, dotNL, dotNH) ; \n"],[6],[0,"\nreturn F * GD ; }\nvec3 BRDF_Diffuse_Lambert ( vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor ; }\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",311],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",315],[0,"\nfloat D_Charlie ( float roughness, float dotNH ) { float invAlpha = 1.0 / roughness ;\nfloat cos2h = dotNH * dotNH ;\nfloat sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;\nreturn ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ; }\nfloat V_Neubelt ( float NoV, float NoL ) { return saturate(1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) )) ; }\nvec3 sheenBRDF ( vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness ) { vec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nfloat dotNH = saturate(dot ( surfaceData.normal , halfDir )) ;\nfloat D = D_Charlie(sheenRoughness, dotNH) ;\nfloat V = V_Neubelt(surfaceData.dotNV, dotNL) ;\nvec3 F = sheenColor ;\nreturn D * V * F ; }\n\n"],[6],[0,"\nvec2 envDFGApprox ( float roughness, float dotNV ) { const vec4 c0 = vec4 ( - 1 , - 0.0275 , - 0.572 , 0.022 ) ;\nconst vec4 c1 = vec4 ( 1 , 0.0425 , 1.04 , - 0.04 ) ;\nvec4 r = roughness * c0 + c1 ;\nfloat a004 = min ( r.x * r.x , exp2 ( - 9.28 * dotNV ) ) * r.x + r.y ;\nreturn vec2 ( - 1.04 , 1.04 ) * a004 + r.zw ; }\nvec3 envBRDFApprox ( vec3 f0, float f90, float roughness, float dotNV ) { vec2 AB = envDFGApprox(roughness, dotNV) ;\nreturn f0 * AB.x + f90 * AB.y ; }\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",319],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",323],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",373],[0,"\n"],[7,"LIGHT_INCLUDED"],[0,"\nuniform ivec4 renderer_Layer;\n\n"],[2,"GRAPHICS_API_WEBGL2",333],[0,"\nbool isBitSet ( float value, float mask, float bitIndex ) { return mod ( floor ( value / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 && mod ( floor ( mask / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 ; }\n\n"],[6],[0,"\nbool isRendererCulledByLight ( ivec2 rendererLayer, ivec2 lightCullingMask ) { \n"],[1,"GRAPHICS_API_WEBGL2",337],[0," return ! ( ( rendererLayer.x & lightCullingMask.x ) != 0 || ( rendererLayer.y & lightCullingMask.y ) != 0 ) ; \n"],[5,339],[0," for ( int i = 0 ; i < 16 ; i ++ ) { if ( isBitSet(float ( rendererLayer.x ), float ( lightCullingMask.x ), float ( i )) || isBitSet(float ( rendererLayer.y ), float ( lightCullingMask.y ), float ( i )) ) { return false ; } }\nreturn true ; \n"],[6],[0," }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",347],[0,"\nstruct DirectLight { vec3 color ; vec3 direction ; } ;\nuniform ivec2 scene_DirectLightCullingMask [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightColor [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightDirection [ SCENE_DIRECT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",345],[0,"\nDirectLight getDirectLight ( int index ) { DirectLight light ;\nlight.color = scene_DirectLightColor[index] ;\nlight.direction = scene_DirectLightDirection[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",355],[0,"\nstruct PointLight { vec3 color ; vec3 position ; float distance ; } ;\nuniform ivec2 scene_PointLightCullingMask [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightColor [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightPosition [ SCENE_POINT_LIGHT_COUNT ];\nuniform float scene_PointLightDistance [ SCENE_POINT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",353],[0,"\nPointLight getPointLight ( int index ) { PointLight light ;\nlight.color = scene_PointLightColor[index] ;\nlight.position = scene_PointLightPosition[index] ;\nlight.distance = scene_PointLightDistance[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",363],[0,"\nstruct SpotLight { vec3 color ; vec3 position ; vec3 direction ; float distance ; float angleCos ; float penumbraCos ; } ;\nuniform ivec2 scene_SpotLightCullingMask [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightColor [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightPosition [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightDirection [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightDistance [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightAngleCos [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightPenumbraCos [ SCENE_SPOT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",361],[0,"\nSpotLight getSpotLight ( int index ) { SpotLight light ;\nlight.color = scene_SpotLightColor[index] ;\nlight.position = scene_SpotLightPosition[index] ;\nlight.direction = scene_SpotLightDirection[index] ;\nlight.distance = scene_SpotLightDistance[index] ;\nlight.angleCos = scene_SpotLightAngleCos[index] ;\nlight.penumbraCos = scene_SpotLightPenumbraCos[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\nstruct EnvMapLight { vec3 diffuse ; float mipMapLevel ; float diffuseIntensity ; float specularIntensity ; } ;\nuniform EnvMapLight scene_EnvMapLight;\n\n"],[1,"SCENE_USE_SH",367],[0,"\nuniform vec3 scene_EnvSH [ 9 ];\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",371],[0,"\nuniform samplerCube scene_EnvSpecularSampler;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",387],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\nvoid diffuseLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 attenuationIrradiance, inout vec3 diffuseColor ) { diffuseColor += attenuationIrradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nvoid specularLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor ) { specularColor += attenuationIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.normal, bsdfData.specularF0, bsdfData.roughness) * bsdfData.energyCompensation ; }\nvoid sheenLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",381],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nspecularColor += attenuationIrradiance * sheenBRDF(incidentDirection, surfaceData, surfaceData.sheenColor, bsdfData.sheenRoughness) ; \n"],[6],[0," }\nfloat clearCoatLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 color, inout vec3 specularColor ) { float attenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",385],[0," float clearCoatDotNL = saturate(dot ( surfaceData.clearCoatNormal , incidentDirection )) ;\nvec3 clearCoatIrradiance = clearCoatDotNL * color ;\nspecularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.clearCoatNormal, bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness) ;\nattenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn attenuation ; }\n\n"],[6],[0,"\nvoid surfaceShading ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 lightColor, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nvec3 irradiance = dotNL * lightColor * PI ;\nfloat attenuation = FUNCTION_CLEAR_COAT_LOBE(surfaceData, bsdfData, incidentDirection, lightColor, specularColor) ;\nvec3 attenuationIrradiance = attenuation * irradiance ;\nFUNCTION_DIFFUSE_LOBE(surfaceData, bsdfData, attenuationIrradiance, diffuseColor) ;\nFUNCTION_SPECULAR_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, specularColor) ;\nFUNCTION_SHEEN_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",391],[0,"\nvoid addDirectionalDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, DirectLight directionalLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lightColor = directionalLight.color ;\nvec3 direction = - directionalLight.direction ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",395],[0,"\nvoid addPointDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, PointLight pointLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = pointLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nvec3 lightColor = pointLight.color ;\nlightColor *= clamp ( 1.0 - pow ( lightDistance / pointLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",399],[0,"\nvoid addSpotDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, SpotLight spotLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = spotLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nfloat angleCos = dot ( direction , - spotLight.direction ) ;\nfloat spotEffect = smoothstep ( spotLight.penumbraCos , spotLight.angleCos , angleCos ) ;\nfloat decayEffect = clamp ( 1.0 - pow ( lightDistance / spotLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nvec3 lightColor = spotLight.color ;\nlightColor *= spotEffect * decayEffect ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\nvoid evaluateDirectRadiance ( SurfaceData surfaceData, BSDFData bsdfData, float shadowAttenuation, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { \n"],[1,"SCENE_DIRECT_LIGHT_COUNT",413],[0," for ( int i = 0 ; i < SCENE_DIRECT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_DirectLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",405],[0," DirectLight directionalLight = getDirectLight(i) ; \n"],[5,407],[0," DirectLight directionalLight ;\ndirectionalLight.color = scene_DirectLightColor[i] ;\ndirectionalLight.direction = scene_DirectLightDirection[i] ; \n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",411],[0," if ( i == 0 ) { directionalLight.color *= shadowAttenuation ; } \n"],[6],[0,"\naddDirectionalDirectLightRadiance(surfaceData, bsdfData, directionalLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",423],[0," for ( int i = 0 ; i < SCENE_POINT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_PointLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",419],[0," PointLight pointLight = getPointLight(i) ; \n"],[5,421],[0," PointLight pointLight ;\npointLight.color = scene_PointLightColor[i] ;\npointLight.position = scene_PointLightPosition[i] ;\npointLight.distance = scene_PointLightDistance[i] ; \n"],[6],[0,"\naddPointDirectLightRadiance(surfaceData, bsdfData, pointLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",433],[0," for ( int i = 0 ; i < SCENE_SPOT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_SpotLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",429],[0," SpotLight spotLight = getSpotLight(i) ; \n"],[5,431],[0," SpotLight spotLight ;\nspotLight.color = scene_SpotLightColor[i] ;\nspotLight.position = scene_SpotLightPosition[i] ;\nspotLight.direction = scene_SpotLightDirection[i] ;\nspotLight.distance = scene_SpotLightDistance[i] ;\nspotLight.angleCos = scene_SpotLightAngleCos[i] ;\nspotLight.penumbraCos = scene_SpotLightPenumbraCos[i] ; \n"],[6],[0,"\naddSpotDirectLightRadiance(surfaceData, bsdfData, spotLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",511],[0,"\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",445],[0,"\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",451],[0,"\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",457],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",463],[0,"\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",495],[0,"\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\nvec3 getReflectedVector ( SurfaceData surfaceData, vec3 n ) { \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",471],[0," vec3 r = reflect ( - surfaceData.viewDir , surfaceData.anisotropicN ) ; \n"],[5,473],[0," vec3 r = reflect ( - surfaceData.viewDir , n ) ; \n"],[6],[0,"\nreturn r ; }\nfloat getSpecularMIPLevel ( float roughness, int maxMIPLevel ) { return roughness * float ( maxMIPLevel ) ; }\nvec3 getLightProbeRadiance ( SurfaceData surfaceData, vec3 normal, float roughness ) { \n"],[2,"SCENE_USE_SPECULAR_ENV",477],[0," return vec3 ( 0 ) ; \n"],[5,489],[0," vec3 reflectVec = getReflectedVector(surfaceData, normal) ;\nfloat specularMIPLevel = getSpecularMIPLevel(roughness, int ( scene_EnvMapLight.mipMapLevel )) ;\n\n"],[1,"HAS_TEX_LOD",481],[0," vec4 envMapColor = textureCubeLodEXT ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[5,483],[0," vec4 envMapColor = textureCube ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[6],[0,"\n\n"],[1,"ENGINE_NO_SRGB",487],[0," envMapColor = sRGBToLinear(envMapColor) ; \n"],[6],[0,"\nreturn envMapColor.rgb * scene_EnvMapLight.specularIntensity ; \n"],[6],[0," }\nfloat evaluateSpecularOcclusion ( float dotNV, float diffuseAO, float roughness ) { float specularAOFactor = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"or","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"SCENE_ENABLE_AMBIENT_OCCLUSION"}},"r":{"t":"def","m":"SCENE_USE_SPECULAR_ENV"}},493],[0," specularAOFactor = saturate(pow ( dotNV + diffuseAO , exp2 ( - 16.0 * roughness - 1.0 ) ) - 1.0 + diffuseAO) ; \n"],[6],[0,"\nreturn specularAOFactor ; }\n\n"],[6],[0,"\nvec3 getLightProbeIrradiance ( vec3 sh [ 9 ], vec3 normal ) { vec3 result = sh[0] + sh[1] * ( normal.y ) + sh[2] * ( normal.z ) + sh[3] * ( normal.x ) + sh[4] * ( normal.y * normal.x ) + sh[5] * ( normal.y * normal.z ) + sh[6] * ( 3.0 * normal.z * normal.z - 1.0 ) + sh[7] * ( normal.z * normal.x ) + sh[8] * ( normal.x * normal.x - normal.y * normal.y ) ;\nreturn max ( result , vec3 ( 0.0 ) ) ; }\nvoid evaluateDiffuseIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 diffuseColor ) { \n"],[1,"SCENE_USE_SH",499],[0," vec3 irradiance = getLightProbeIrradiance(scene_EnvSH, surfaceData.normal) ;\nirradiance *= scene_EnvMapLight.diffuseIntensity ; \n"],[5,501],[0," vec3 irradiance = scene_EnvMapLight.diffuse * scene_EnvMapLight.diffuseIntensity ;\nirradiance *= PI ; \n"],[6],[0,"\ndiffuseColor += bsdfData.diffuseAO * irradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nfloat evaluateClearCoatIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 specularColor ) { float radianceAttenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",505],[0," vec3 clearCoatRadiance = getLightProbeRadiance(surfaceData, surfaceData.clearCoatNormal, bsdfData.clearCoatRoughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.clearCoatRoughness) ;\nspecularColor += specularAO * clearCoatRadiance * surfaceData.clearCoat * envBRDFApprox(bsdfData.clearCoatSpecularColor, 1.0, bsdfData.clearCoatRoughness, surfaceData.clearCoatDotNV) ;\nradianceAttenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn radianceAttenuation ; }\nvoid evaluateSpecularIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 outSpecularColor ) { vec3 radiance = getLightProbeRadiance(surfaceData, surfaceData.normal, bsdfData.roughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.roughness) ;\noutSpecularColor += specularAO * radianceAttenuation * radiance * envBRDFApprox(bsdfData.resolvedSpecularF0, bsdfData.specularF90, bsdfData.roughness, surfaceData.dotNV) * bsdfData.energyCompensation ; }\nvoid evaluateSheenIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",509],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.sheenRoughness) ;\nvec3 reflectance = specularAO * radianceAttenuation * bsdfData.approxIBLSheenDG * surfaceData.sheenColor ;\nspecularColor += reflectance ; \n"],[6],[0," }\nvoid evaluateIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nFUNCTION_DIFFUSE_IBL(surfaceData, bsdfData, diffuseColor) ;\nfloat radianceAttenuation = FUNCTION_CLEAR_COAT_IBL(surfaceData, bsdfData, specularColor) ;\nFUNCTION_SPECULAR_IBL(surfaceData, bsdfData, radianceAttenuation, specularColor) ;\nFUNCTION_SHEEN_IBL(surfaceData, bsdfData, radianceAttenuation, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",517],[0,"\n"],[7,"VERTEX_INCLUDE"],[0,"\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",768],[0,"\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",533],[0,"\n"],[7,"NORMAL_INCLUDED"],[0,"\nvec3 getNormalByNormalTexture ( mat3 tbn, sampler2D normalTexture, float normalIntensity, vec2 uv, bool isFrontFacing ) { vec3 normal = ( texture2D ( normalTexture , uv ) ).rgb ;\nnormal = normalize ( tbn * ( ( 2.0 * normal - 1.0 ) * vec3 ( normalIntensity , normalIntensity , 1.0 ) ) ) ;\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nreturn normal ; }\nmat3 getTBNByDerivatives ( vec2 uv, vec3 normal, vec3 position, bool isFrontFacing ) { \n"],[1,"HAS_DERIVATIVES",529],[0," uv = isFrontFacing ? uv : - uv ;\nvec3 dp1 = dFdx ( position ) ;\nvec3 dp2 = dFdy ( position ) ;\nvec2 duv1 = dFdx ( uv ) ;\nvec2 duv2 = dFdy ( uv ) ;\nvec3 dp2perp = cross ( dp2 , normal ) ;\nvec3 dp1perp = cross ( normal , dp1 ) ;\nvec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x ;\nvec3 bitangent = dp2perp * duv1.y + dp1perp * duv2.y ;\nfloat denom = max ( dot ( tangent , tangent ) , dot ( bitangent , bitangent ) ) ;\nfloat invmax = ( denom == 0.0 ) ? 0.0 : camera_ProjectionParams.x / sqrt ( denom ) ;\nreturn mat3 ( tangent * invmax , bitangent * invmax , normal ) ; \n"],[5,531],[0," return mat3 ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , normal ) ; \n"],[6],[0," }\n\n"],[6],[0,"\nuniform float material_AlphaCutoff;\nuniform vec4 material_BaseColor;\nuniform float material_Metal;\nuniform float material_Roughness;\nuniform float material_IOR;\nuniform vec3 material_EmissiveColor;\nuniform float material_NormalIntensity;\nuniform float material_OcclusionIntensity;\nuniform float material_OcclusionTextureCoord;\nuniform float material_SpecularIntensity;\nuniform vec3 material_SpecularColor;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",537],[0,"\nuniform sampler2D material_SpecularIntensityTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",541],[0,"\nuniform sampler2D material_SpecularColorTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",557],[0,"\nuniform float material_ClearCoat;\nuniform float material_ClearCoatRoughness;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",547],[0,"\nuniform sampler2D material_ClearCoatTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",551],[0,"\nuniform sampler2D material_ClearCoatRoughnessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",555],[0,"\nuniform sampler2D material_ClearCoatNormalTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",565],[0,"\nuniform vec3 material_AnisotropyInfo;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",563],[0,"\nuniform sampler2D material_AnisotropyTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",577],[0,"\nuniform vec4 material_IridescenceInfo;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",571],[0,"\nuniform sampler2D material_IridescenceThicknessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",575],[0,"\nuniform sampler2D material_IridescenceTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",589],[0,"\nuniform float material_SheenRoughness;\nuniform vec3 material_SheenColor;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",583],[0,"\nuniform sampler2D material_SheenTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",587],[0,"\nuniform sampler2D material_SheenRoughnessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",605],[0,"\nuniform float material_Transmission;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",595],[0,"\nuniform sampler2D material_TransmissionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",603],[0,"\nuniform vec3 material_AttenuationColor;\nuniform float material_AttenuationDistance;\nuniform float material_Thickness;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",601],[0,"\nuniform sampler2D material_ThicknessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",609],[0,"\nuniform sampler2D material_BaseTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",613],[0,"\nuniform sampler2D material_NormalTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",617],[0,"\nuniform sampler2D material_EmissiveTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",621],[0,"\nuniform sampler2D material_RoughnessMetallicTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",625],[0,"\nuniform sampler2D material_OcclusionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",629],[0,"\nvec3 getAnisotropicBentNormal ( SurfaceData surfaceData ) { vec3 anisotropyDirection = ( surfaceData.anisotropy >= 0.0 ) ? surfaceData.anisotropicB : surfaceData.anisotropicT ;\nvec3 anisotropicTangent = cross ( anisotropyDirection , surfaceData.viewDir ) ;\nvec3 anisotropicNormal = cross ( anisotropicTangent , anisotropyDirection ) ;\nvec3 bentNormal = normalize ( mix ( surfaceData.normal , anisotropicNormal , abs ( surfaceData.anisotropy ) * saturate(5.0 * surfaceData.roughness) ) ) ;\nreturn bentNormal ; }\n\n"],[6],[0,"\nSurfaceData getSurfaceData ( vec2 aoUV, bool isFrontFacing ) { SurfaceData surfaceData ;\nvec2 uv = uv ;\nvec4 baseColor = material_BaseColor ;\nfloat metallic = material_Metal ;\nfloat roughness = material_Roughness ;\nvec3 emissiveRadiance = material_EmissiveColor ;\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",633],[0," baseColor *= texture2DSRGB(material_BaseTexture, uv) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",637],[0," baseColor *= vertexColor ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_IS_ALPHA_CUTOFF",641],[0," if ( baseColor.a < material_AlphaCutoff ) { discard ; } \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",645],[0," vec4 metalRoughMapColor = texture2D ( material_RoughnessMetallicTexture , uv ) ;\nroughness *= metalRoughMapColor.g ;\nmetallic *= metalRoughMapColor.b ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",649],[0," emissiveRadiance *= texture2DSRGB(material_EmissiveTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.albedoColor = baseColor.rgb ;\nsurfaceData.emissiveColor = emissiveRadiance ;\nsurfaceData.metallic = metallic ;\nsurfaceData.roughness = roughness ;\nsurfaceData.IOR = material_IOR ;\n\n"],[1,"MATERIAL_IS_TRANSPARENT",653],[0," surfaceData.opacity = baseColor.a ; \n"],[5,655],[0," surfaceData.opacity = 1.0 ; \n"],[6],[0,"\nsurfaceData.position = positionWS ;\nsurfaceData.positionCS = positionCS ;\n\n"],[1,"CAMERA_ORTHOGRAPHIC",659],[0," surfaceData.viewDir = - camera_Forward ; \n"],[5,661],[0," surfaceData.viewDir = normalize ( camera_Position - positionWS ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",665],[0," vec3 normal = normalize ( normalWS ) ; \n"],[5,670],[1,"HAS_DERIVATIVES",668],[0," vec3 pos_dx = dFdx ( positionWS ) ;\nvec3 pos_dy = dFdy ( positionWS ) ;\nvec3 normal = normalize ( cross ( pos_dx , pos_dy ) ) ;\nnormal *= camera_ProjectionParams.x ; \n"],[5,670],[0," vec3 normal = vec3 ( 0 , 0 , 1 ) ; \n"],[6],[0,"\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nsurfaceData.normal = normal ;\n\n"],[1,"NEED_TANGENT",684],[0," \n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},676],[0," surfaceData.tangent = tangentWS ;\nsurfaceData.bitangent = bitangentWS ;\nmat3 tbn = mat3 ( tangentWS , bitangentWS , normalWS ) ; \n"],[5,678],[0," mat3 tbn = getTBNByDerivatives(uv, normal, positionWS, isFrontFacing) ;\nsurfaceData.tangent = tbn[0] ;\nsurfaceData.bitangent = tbn[1] ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",682],[0," surfaceData.normal = getNormalByNormalTexture(tbn, material_NormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[6],[0," \n"],[6],[0,"\nsurfaceData.dotNV = saturate(dot ( surfaceData.normal , surfaceData.viewDir )) ;\nsurfaceData.specularIntensity = material_SpecularIntensity ;\nsurfaceData.specularColor = material_SpecularColor ;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",688],[0," surfaceData.specularIntensity *= texture2D ( material_SpecularIntensityTexture , uv ).a ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",692],[0," surfaceData.specularColor *= texture2D ( material_SpecularColorTexture , uv ).rgb ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",710],[0," \n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",698],[0," surfaceData.clearCoatNormal = getNormalByNormalTexture(tbn, material_ClearCoatNormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[5,700],[0," surfaceData.clearCoatNormal = normal ; \n"],[6],[0,"\nsurfaceData.clearCoatDotNV = saturate(dot ( surfaceData.clearCoatNormal , surfaceData.viewDir )) ;\nsurfaceData.clearCoat = material_ClearCoat ;\nsurfaceData.clearCoatRoughness = material_ClearCoatRoughness ;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",704],[0," surfaceData.clearCoat *= ( texture2D ( material_ClearCoatTexture , uv ) ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",708],[0," surfaceData.clearCoatRoughness *= ( texture2D ( material_ClearCoatRoughnessTexture , uv ) ).g ; \n"],[6],[0,"\nsurfaceData.clearCoat = saturate(surfaceData.clearCoat) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",718],[0," float anisotropy = material_AnisotropyInfo.z ;\nvec3 anisotropicDirection = vec3 ( material_AnisotropyInfo.xy , 0.0 ) ;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",716],[0," vec3 anisotropyTextureInfo = ( texture2D ( material_AnisotropyTexture , uv ) ).rgb ;\nanisotropy *= anisotropyTextureInfo.b ;\nanisotropicDirection.xy *= anisotropyTextureInfo.rg * 2.0 - 1.0 ; \n"],[6],[0,"\nsurfaceData.anisotropy = anisotropy ;\nsurfaceData.anisotropicT = normalize ( mat3 ( surfaceData.tangent , surfaceData.bitangent , surfaceData.normal ) * anisotropicDirection ) ;\nsurfaceData.anisotropicB = normalize ( cross ( surfaceData.normal , surfaceData.anisotropicT ) ) ;\nsurfaceData.anisotropicN = getAnisotropicBentNormal(surfaceData) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",732],[0," surfaceData.iridescenceFactor = material_IridescenceInfo.x ;\nsurfaceData.iridescenceIOR = material_IridescenceInfo.y ;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",724],[0," float iridescenceThicknessWeight = texture2D ( material_IridescenceThicknessTexture , uv ).g ;\nsurfaceData.iridescenceThickness = mix ( material_IridescenceInfo.z , material_IridescenceInfo.w , iridescenceThicknessWeight ) ; \n"],[5,726],[0," surfaceData.iridescenceThickness = material_IridescenceInfo.w ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",730],[0," surfaceData.iridescenceFactor *= texture2D ( material_IridescenceTexture , uv ).r ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",744],[0," vec3 sheenColor = material_SheenColor ;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",738],[0," sheenColor *= texture2DSRGB(material_SheenTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.sheenColor = sheenColor ;\nsurfaceData.sheenRoughness = material_SheenRoughness ;\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",742],[0," surfaceData.sheenRoughness *= texture2D ( material_SheenRoughnessTexture , uv ).a ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",760],[0," surfaceData.transmission = material_Transmission ;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",750],[0," surfaceData.transmission *= texture2D ( material_TransmissionTexture , uv ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",758],[0," surfaceData.absorptionCoefficient = - log ( material_AttenuationColor + HALF_EPS ) / max ( HALF_EPS , material_AttenuationDistance ) ;\nsurfaceData.thickness = max ( material_Thickness , 0.0001 ) ;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",756],[0," surfaceData.thickness *= texture2D ( material_ThicknessTexture , uv ).g ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",764],[0," surfaceData.ambientOcclusion = ( ( texture2D ( material_OcclusionTexture , aoUV ) ).r - 1.0 ) * material_OcclusionIntensity + 1.0 ; \n"],[5,766],[0," surfaceData.ambientOcclusion = 1.0 ; \n"],[6],[0,"\nreturn surfaceData ; }\n\n"],[6],[0,"\nvoid main() { BRDFData brdfData ;\nvec2 aoUV = uv ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"RENDERER_HAS_UV1"}},772],[0," if ( material_OcclusionTextureCoord == 1.0 ) { aoUV = uv1 ; } \n"],[6],[0,"\nSurfaceData surfaceData = getSurfaceData(aoUV, gl_FrontFacing) ;\nsurfaceData.f0 = 0.04 ;\ninitBRDFData ( surfaceData , brdfData ) ;\nvec3 totalDiffuseColor = vec3 ( 0 , 0 , 0 ) ;\nvec3 totalSpecularColor = vec3 ( 0 , 0 , 0 ) ;\nfloat shadowAttenuation = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_DIRECT_LIGHT_COUNT"},"r":{"t":"def","m":"NEED_CALCULATE_SHADOWS"}},782],[0," \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,778],[0," vec3 shadowCoord = shadowCoord ; \n"],[5,780],[0," vec3 shadowCoord = getShadowCoord ( positionWS ) ; \n"],[6],[0,"\nshadowAttenuation *= sampleShadowMap ( positionWS , shadowCoord ) ; \n"],[6],[0,"\nevaluateDirectRadiance(surfaceData, brdfData, shadowAttenuation, totalDiffuseColor, totalSpecularColor) ;\nevaluateIBL(surfaceData, brdfData, totalDiffuseColor, totalSpecularColor) ;\nvec4 color = vec4 ( totalDiffuseColor + totalSpecularColor , surfaceData.opacity ) ;\ncolor.rgb += surfaceData.emissiveColor ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,786],[0," color = fog(color, positionVS) ; \n"],[6],[0,"\ngl_FragColor = color ; }\n\n"],[6]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd packages/custom-material/libs/advanced-shader/hair && \
python3 << 'EOF'
import json
import re

# Read the file
with open('Hair.gsp', 'r') as f:
    content = f.read()

# Parse as JSON
try:
    data = json.loads(content)
except:
    print("Failed to parse JSON")
    exit(1)

# Extract fragment shader instructions
if 'subShaders' in data and len(data['subShaders']) > 0:
    passes = data['subShaders'][0].get('passes', [])
    for pass_info in passes:
        if pass_info.get('name') == 'Forward Pass':
            frag_instructions = pass_info.get('fragmentShaderInstructions', [])
            
            # Find and print struct definition
            in_struct = False
            struct_content = []
            for i, instr in enumerate(frag_instructions):
                if isinstance(instr, list) and len(instr) > 0:
                    if isinstance(instr[0], int) and instr[0] == 0:  # type 0 = text
                        text = instr[1] if len(instr) > 1 else ""
                        if 'struct SurfaceData' in text:
                            in_struct = True
                            struct_content.append(text)
                        elif in_struct:
                            struct_content.append(text)
                            if '} ;' in text:
                                break
            
            print("=== SurfaceData Struct Definition ===")
            struct_text = ''.join(struct_content)
            print(struct_text[:500])
            print()
            
            # Find f0 assignments
            print("=== Searching for f0 assignments ===")
            for i, instr in enumerate(frag_instructions):
                if isinstance(instr, list) and len(instr) > 1:
                    if isinstance(instr[0], int) and instr[0] == 0:
                        text = instr[1] if len(instr) > 1 else ""
                        if 'surfaceData.f0' in text:
                            print(f"Found at instruction {i}: {text}")

EOF

Repository: galacean/engine-toolkit

Length of output: 929


🏁 Script executed:

cd packages/custom-material/libs/advanced-shader/hair && \
python3 << 'EOF'
import json

# Read the file
with open('Hair.gsp', 'r') as f:
    content = f.read()

# Parse as JSON
data = json.loads(content)

# Extract fragment shader instructions
passes = data['subShaders'][0].get('passes', [])
for pass_info in passes:
    if pass_info.get('name') == 'Forward Pass':
        frag_instructions = pass_info.get('fragmentShaderInstructions', [])
        
        # Collect all text to search for struct
        all_text = []
        for instr in frag_instructions:
            if isinstance(instr, list) and len(instr) > 0:
                if isinstance(instr[0], int) and instr[0] == 0:
                    text = instr[1] if len(instr) > 1 else ""
                    all_text.append(text)
        
        full_shader = ''.join(all_text)
        
        # Find struct definition
        struct_start = full_shader.find('struct SurfaceData {')
        if struct_start != -1:
            struct_end = full_shader.find('} ;', struct_start) + 3
            struct_def = full_shader[struct_start:struct_end]
            print("=== Full SurfaceData Struct ===")
            print(struct_def)
            print()
            
            # Check if f0 exists
            if 'f0' in struct_def:
                print("✓ 'f0' field FOUND in struct definition")
            else:
                print("✗ 'f0' field NOT found in struct definition")
            
            print()
            # Find the assignment
            assign_idx = full_shader.find('surfaceData.f0 = 0.04')
            if assign_idx != -1:
                context = full_shader[max(0, assign_idx-50):assign_idx+60]
                print("=== f0 Assignment Context ===")
                print(context)

EOF

Repository: galacean/engine-toolkit

Length of output: 976


🏁 Script executed:

cd packages/custom-material/libs/advanced-shader && \
# Check if BRDFData struct has f0 or if there's a pattern
find . -name "*.gsp" -o -name "*.gs" | head -10 && \
echo "---" && \
# Check if BRDFData is defined anywhere and what it contains
rg "struct BRDFData" -A 15 --max-count=5

Repository: galacean/engine-toolkit

Length of output: 115


🏁 Script executed:

cd packages/custom-material/libs/advanced-shader/hair && \
python3 << 'EOF'
import json

with open('Hair.gsp', 'r') as f:
    content = f.read()

data = json.loads(content)

# Check both vertex and fragment shaders
for pass_info in data['subShaders'][0].get('passes', []):
    if pass_info.get('name') == 'Forward Pass':
        for shader_type in ['vertexShaderInstructions', 'fragmentShaderInstructions']:
            instructions = pass_info.get(shader_type, [])
            
            all_text = []
            for instr in instructions:
                if isinstance(instr, list) and len(instr) > 0:
                    if isinstance(instr[0], int) and instr[0] == 0:
                        text = instr[1] if len(instr) > 1 else ""
                        all_text.append(text)
            
            full_shader = ''.join(all_text)
            
            # Search for BRDFData struct
            if 'struct BRDFData' in full_shader:
                print(f"=== Found BRDFData in {shader_type} ===")
                start = full_shader.find('struct BRDFData')
                end = full_shader.find('} ;', start) + 3
                print(full_shader[start:end])
                print()
            
            # Search for initBRDFData function
            if 'initBRDFData' in full_shader:
                print(f"=== Found initBRDFData in {shader_type} ===")
                start = full_shader.find('initBRDFData')
                end = min(start + 200, len(full_shader))
                print(full_shader[start:end])
                print()

EOF

Repository: galacean/engine-toolkit

Length of output: 326


🏁 Script executed:

cd packages/custom-material && \
find . -type f \( -name "*.gsp" -o -name "*.glsl" -o -name "*.gs" \) | xargs rg "struct BRDFData" -A 20 | head -100

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

cd packages/custom-material/libs/advanced-shader/hair && \
python3 << 'EOF'
import json

with open('Hair.gsp', 'r') as f:
    content = f.read()

data = json.loads(content)

# Look for all structs defined in the fragment shader
for pass_info in data['subShaders'][0].get('passes', []):
    if pass_info.get('name') == 'Forward Pass':
        instructions = pass_info.get('fragmentShaderInstructions', [])
        
        all_text = []
        for instr in instructions:
            if isinstance(instr, list) and len(instr) > 0:
                if isinstance(instr[0], int) and instr[0] == 0:
                    text = instr[1] if len(instr) > 1 else ""
                    all_text.append(text)
        
        full_shader = ''.join(all_text)
        
        # Find all struct definitions
        print("=== All structs in fragment shader ===")
        import re
        structs = re.findall(r'struct \w+ \{[^}]*\}', full_shader, re.DOTALL)
        for i, struct in enumerate(structs):
            print(f"\n--- Struct {i+1} ---")
            print(struct[:300])
        
        # Check what happens with surfaceData.f0
        print("\n\n=== Context around surfaceData.f0 assignment ===")
        idx = full_shader.find('SurfaceData surfaceData = getSurfaceData')
        if idx != -1:
            print(full_shader[idx:idx+300])

EOF

Repository: galacean/engine-toolkit

Length of output: 1519


🏁 Script executed:

cd packages/custom-material/libs/advanced-shader && \
# Check the other shader files
for file in eye/Eye.gsp sss/SSS.gsp; do
  echo "=== Checking $file ==="
  python3 << PYEOF
import json

try:
    with open('$file', 'r') as f:
        content = f.read()
    data = json.loads(content)
    
    for pass_info in data.get('subShaders', [{}])[0].get('passes', []):
        if pass_info.get('name') == 'Forward Pass':
            instructions = pass_info.get('fragmentShaderInstructions', [])
            
            all_text = []
            for instr in instructions:
                if isinstance(instr, list) and len(instr) > 0:
                    if isinstance(instr[0], int) and instr[0] == 0:
                        text = instr[1] if len(instr) > 1 else ""
                        all_text.append(text)
            
            full_shader = ''.join(all_text)
            
            # Check for f0 assignment
            if 'surfaceData.f0' in full_shader:
                print("✗ Found surfaceData.f0 assignment")
                # Check if f0 is in struct
                struct_start = full_shader.find('struct SurfaceData {')
                if struct_start != -1:
                    struct_end = full_shader.find('} ;', struct_start) + 3
                    struct_def = full_shader[struct_start:struct_end]
                    if 'float f0' in struct_def:
                        print("  ✓ f0 field IS defined in SurfaceData")
                    else:
                        print("  ✗ f0 field NOT defined in SurfaceData")
            else:
                print("✓ No surfaceData.f0 assignment found")
except Exception as e:
    print(f"Error: {e}")
PYEOF
  echo ""
done

Repository: galacean/engine-toolkit

Length of output: 275


🏁 Script executed:

cd packages/custom-material && \
# Check the source shader templates or generation code
find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.glsl" \) | xargs rg "surfaceData.f0|float f0" | head -20

Repository: galacean/engine-toolkit

Length of output: 285


🏁 Script executed:

cd packages/custom-material && \
# Check the source GLSL files to see the struct definition
for file in src/advanced-shader/hair/HairForwardPass.glsl src/advanced-shader/sss/SSSForwardPass.glsl src/advanced-shader/eye/EyeForwardPass.glsl; do
  echo "=== $file ==="
  grep -A 20 "struct SurfaceData" "$file" | head -25
  echo ""
done

Repository: galacean/engine-toolkit

Length of output: 228


🏁 Script executed:

cd packages/custom-material && \
# Find where SurfaceData is defined in GLSL files
rg "struct SurfaceData" --type glsl -A 20 | head -80

Repository: galacean/engine-toolkit

Length of output: 96


🏁 Script executed:

cd packages/custom-material && \
# Search for SurfaceData struct in source files
find src -type f -name "*.glsl" -o -name "*.ts" | xargs grep -l "struct SurfaceData" && \
echo "---" && \
# Look at the actual struct definitions
find src -type f \( -name "*.glsl" -o -name "*.ts" \) -exec grep -H -A 30 "struct SurfaceData" {} \; | head -150

Repository: galacean/engine-toolkit

Length of output: 51


🏁 Script executed:

cd packages/custom-material && \
# Search more carefully
rg "struct SurfaceData" src/ -A 25 --max-count 1

Repository: galacean/engine-toolkit

Length of output: 49


🏁 Script executed:

cd packages/custom-material && \
# List the source directory structure
find src -type f | head -30 && \
echo "---" && \
# Search for where SurfaceData or f0 is mentioned in source
rg "SurfaceData\|float f0" src/ --max-count 5

Repository: galacean/engine-toolkit

Length of output: 1034


🏁 Script executed:

cd packages/custom-material && \
# Check the actual shader source files
cat src/advanced-shader/hair/HairForwardPass.glsl | grep -A 20 "surfaceData.f0" && \
echo "---" && \
# Look for struct SurfaceData in the include files
cat src/advanced-shader/hair/HairFunction.glsl | grep -B 5 -A 25 "struct SurfaceData" | head -50

Repository: galacean/engine-toolkit

Length of output: 681


🏁 Script executed:

cd packages/custom-material && \
# Check what's in the Hair shader files
cat src/advanced-shader/hair/Hair.shader | head -50 && \
echo "---" && \
# Search for includes or references to struct definitions
rg "struct SurfaceData" src/advanced-shader/ -B 3 -A 30

Repository: galacean/engine-toolkit

Length of output: 2073


🏁 Script executed:

cd packages/custom-material && \
# Search for struct SurfaceData in all files
find . -type f \( -name "*.glsl" -o -name "*.shader" -o -name "*.ts" -o -name "*.gsp" \) -exec grep -l "struct SurfaceData" {} \; && \
echo "---" && \
# Look for common shader includes
find src -name "*common*" -o -name "*BSDF*" -o -name "*surface*" | grep -i shader

Repository: galacean/engine-toolkit

Length of output: 178


The SurfaceData struct is missing the f0 field across all three advanced shaders (Hair, Eye, SSS), causing a compile error.

Verification confirms that surfaceData.f0 = 0.04; is assigned in the generated fragment shaders, but the SurfaceData struct definition in all three files (Hair.gsp, Eye.gsp, SSS.gsp) does not declare a float f0 field. This will result in GLSL compilation failure when these shaders are used. The source files (HairForwardPass.glsl, EyeForwardPass.glsl, SSSForwardPass.glsl) also contain the same problematic assignment. Fix the upstream shader generation or source templates to include the missing f0 field in the SurfaceData struct.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/advanced-shader/hair/Hair.gsp` at line 1, The
SurfaceData struct in the generated fragment shaders is missing the float f0
field while the code assigns surfaceData.f0 = 0.04, causing GLSL compile errors;
add a declaration "float f0;" to the SurfaceData struct in the Hair, Eye, and
SSS shader templates (the SurfaceData struct definitions used by Hair.gsp /
HairForwardPass.glsl, Eye.gsp / EyeForwardPass.glsl, and SSS.gsp /
SSSForwardPass.glsl) so the assigned field exists and is consistent with
initBRDFData and usage in fragment main.

@@ -0,0 +1 @@
{"name":"DigitalHuman/SSS.gs","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"pbr/Default/ShadowCaster","isUsePass":true,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}}},{"name":"Forward Pass","isUsePass":false,"tags":{"pipelineStage":"Forward"},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[7,"IS_METALLIC_WORKFLOW"],[0,"\n\n"],[2,"FORWARD_PASS_PBR_INCLUDED",593],[0,"\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",35],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",29],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,33],[0,"\nmat2 inverseMat ( mat2 m ) { return mat2 ( m[1][1] , - m[0][1] , - m[1][0] , m[0][0] ) / ( m[0][0] * m[1][1] - m[0][1] * m[1][0] ) ; }\nmat3 inverseMat ( mat3 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] ;\nfloat a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] ;\nfloat a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] ;\nfloat b01 = a22 * a11 - a12 * a21 ;\nfloat b11 = - a22 * a10 + a12 * a20 ;\nfloat b21 = a21 * a10 - a11 * a20 ;\nfloat det = a00 * b01 + a01 * b11 + a02 * b21 ;\nreturn mat3 ( b01 , ( - a22 * a01 + a02 * a21 ) , ( a12 * a01 - a02 * a11 ) , b11 , ( a22 * a00 - a02 * a20 ) , ( - a12 * a00 + a02 * a10 ) , b21 , ( - a21 * a00 + a01 * a20 ) , ( a11 * a00 - a01 * a10 ) ) / det ; }\nmat4 inverseMat ( mat4 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] , a03 = m[0][3] , a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] , a13 = m[1][3] , a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] , a23 = m[2][3] , a30 = m[3][0] , a31 = m[3][1] , a32 = m[3][2] , a33 = m[3][3] , b00 = a00 * a11 - a01 * a10 , b01 = a00 * a12 - a02 * a10 , b02 = a00 * a13 - a03 * a10 , b03 = a01 * a12 - a02 * a11 , b04 = a01 * a13 - a03 * a11 , b05 = a02 * a13 - a03 * a12 , b06 = a20 * a31 - a21 * a30 , b07 = a20 * a32 - a22 * a30 , b08 = a20 * a33 - a23 * a30 , b09 = a21 * a32 - a22 * a31 , b10 = a21 * a33 - a23 * a31 , b11 = a22 * a33 - a23 * a32 , det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06 ;\nreturn mat4 ( a11 * b11 - a12 * b10 + a13 * b09 , a02 * b10 - a01 * b11 - a03 * b09 , a31 * b05 - a32 * b04 + a33 * b03 , a22 * b04 - a21 * b05 - a23 * b03 , a12 * b08 - a10 * b11 - a13 * b07 , a00 * b11 - a02 * b08 + a03 * b07 , a32 * b02 - a30 * b05 - a33 * b01 , a20 * b05 - a22 * b02 + a23 * b01 , a10 * b10 - a11 * b08 + a13 * b06 , a01 * b08 - a00 * b10 - a03 * b06 , a30 * b04 - a31 * b02 + a33 * b00 , a21 * b02 - a20 * b04 - a23 * b00 , a11 * b07 - a10 * b09 - a12 * b06 , a00 * b09 - a01 * b07 + a02 * b06 , a31 * b01 - a30 * b03 - a32 * b00 , a20 * b03 - a21 * b01 + a22 * b00 ) / det ; }\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",45],[0,"\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,43],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",103],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",77],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",75],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},57],[0,"\n"],[5,73],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},69],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",63],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",67],[0,"\n"],[6],[0,"\n"],[5,71],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",81],[0,"attribute vec2 TEXCOORD_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",85],[0,"attribute vec2 TEXCOORD_1;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",89],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",93],[0,"attribute vec4 COLOR_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",97],[0,"attribute vec3 NORMAL;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",101],[0,"attribute vec4 TANGENT;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",133],[0,"\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",111],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",115],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,119],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",127],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",125],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},131],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShadingSSS"],[0,"\n\n"],[2,"BSDF_INCLUDED",193],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",149],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",147],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},159],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",163],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",167],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",171],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",175],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",179],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",183],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",187],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",191],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",199],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CURVATEXTURE",203],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",357],[0,"\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",213],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",219],[0,"\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",225],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",231],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",237],[0,"\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",295],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",251],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",249],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},261],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",265],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",269],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",273],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",277],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",281],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",285],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",289],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",293],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",337],[0,"\n"],[7,"LIGHT_INCLUDED"],[0,"\n\n"],[2,"GRAPHICS_API_WEBGL2",303],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",311],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",309],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",319],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",317],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",327],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",325],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SH",331],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",335],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",343],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",347],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",351],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",355],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",393],[0,"\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",367],[0,"\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",373],[0,"\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",379],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",385],[0,"\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",391],[0,"\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",459],[0,"\n"],[7,"VERTEX_INCLUDE"],[0,"\nstruct VertexInputs { vec4 positionOS ; vec3 positionWS ; \n"],[3,"SCENE_FOG_MODE","!=",0,401],[0," vec3 positionVS ; \n"],[6],[0," \n"],[1,"RENDERER_HAS_NORMAL",409],[0," vec3 normalWS ; \n"],[1,"RENDERER_HAS_TANGENT",407],[0," vec3 tangentWS ; vec3 bitangentWS ; \n"],[6],[0," \n"],[6],[0," } ;\nuniform vec4 material_TilingOffset;\nvec2 getUV0 ( ) { vec2 uv0 = vec2 ( 0 ) ;\n\n"],[1,"RENDERER_HAS_UV",413],[0," uv0 = TEXCOORD_0 ; \n"],[6],[0,"\nreturn uv0 * material_TilingOffset.xy + material_TilingOffset.zw ; }\nVertexInputs getVertexInputs ( ) { VertexInputs inputs ;\nvec4 position = vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",421],[0," vec3 normal = vec3 ( NORMAL ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",419],[0," vec4 tangent = vec4 ( TANGENT ) ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",433],[0," calculateBlendShape ( attributes , position \n"],[1,"RENDERER_HAS_NORMAL",431],[0," , normal \n"],[1,"RENDERER_HAS_TANGENT",429],[0," , tangent \n"],[6],[0," \n"],[6],[0," ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",445],[0," mat4 skinMatrix = getSkinMatrix ( attributes ) ;\nposition = skinMatrix * position ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},443],[0," mat3 skinNormalMatrix = INVERSE_MAT(mat3 ( skinMatrix )) ;\nnormal = normal * skinNormalMatrix ;\n\n"],[1,"RENDERER_HAS_TANGENT",441],[0," tangent.xyz = tangent.xyz * skinNormalMatrix ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},453],[0," inputs.normalWS = normalize ( mat3 ( renderer_NormalMat ) * normal ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",451],[0," vec3 tangentWS = normalize ( mat3 ( renderer_NormalMat ) * tangent.xyz ) ;\nvec3 bitangentWS = cross ( inputs.normalWS , tangentWS ) * tangent.w ;\ninputs.tangentWS = tangentWS ;\ninputs.bitangentWS = bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\ninputs.positionOS = position ;\nvec4 positionWS = renderer_ModelMat * position ;\ninputs.positionWS = positionWS.xyz / positionWS.w ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,457],[0," vec4 positionVS = renderer_MVMat * position ;\ninputs.positionVS = positionVS.xyz / positionVS.w ; \n"],[6],[0,"\nreturn inputs ; }\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",567],[0,"\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",469],[0,"\n"],[7,"NORMAL_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",473],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",477],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",493],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",483],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",487],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",491],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",501],[0,"\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",499],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",513],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",507],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",511],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",525],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",519],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",523],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",541],[0,"\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",531],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",539],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",537],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",545],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",549],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",553],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",557],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",561],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",565],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid main() { \nuv = getUV0() ;\n\n"],[1,"RENDERER_HAS_UV1",571],[0," uv1 = TEXCOORD_1 ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",575],[0," vertexColor = COLOR_0 ; \n"],[6],[0,"\nVertexInputs vertexInputs = getVertexInputs() ;\npositionWS = vertexInputs.positionWS ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,579],[0," positionVS = vertexInputs.positionVS ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",587],[0," normalWS = vertexInputs.normalWS ;\n\n"],[1,"RENDERER_HAS_TANGENT",585],[0," tangentWS = vertexInputs.tangentWS ;\nbitangentWS = vertexInputs.bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},591],[0," shadowCoord = getShadowCoord ( vertexInputs.positionWS ) ; \n"],[6],[0,"\ngl_Position = renderer_MVPMat * vertexInputs.positionOS ;\n }\n\n"],[6]],"fragmentShaderInstructions":[[7,"IS_METALLIC_WORKFLOW"],[0,"\n\n"],[2,"FORWARD_PASS_PBR_INCLUDED",802],[0,"\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",39],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\nfloat pow2 ( float x ) { return x * x ; }\nfloat sRGBToLinear ( float value ) { float linearRGBLo = value / 12.92 ;\nfloat linearRGBHi = pow ( ( value + 0.055 ) / 1.055 , 2.4 ) ;\nfloat linearRGB = ( value <= 0.04045 ) ? linearRGBLo : linearRGBHi ;\nreturn linearRGB ; }\nvec4 sRGBToLinear ( vec4 value ) { return vec4 ( sRGBToLinear(value.r) , sRGBToLinear(value.g) , sRGBToLinear(value.b) , value.a ) ; }\nvec4 texture2DSRGB ( sampler2D tex, vec2 uv ) { vec4 color = texture2D ( tex , uv ) ;\n\n"],[1,"ENGINE_NO_SRGB",27],[0," color = sRGBToLinear(color) ; \n"],[6],[0,"\nreturn color ; }\nuniform vec4 camera_ProjectionParams;\n\n"],[1,"GRAPHICS_API_WEBGL2",33],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,37],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",59],[0,"\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,57],[0,"\nuniform vec4 scene_FogColor;\nuniform vec4 scene_FogParams;\nvec4 fog ( vec4 color, vec3 positionVS ) { float fogDepth = length ( positionVS ) ;\n\n"],[3,"SCENE_FOG_MODE","==",1,49],[0," float fogIntensity = clamp ( fogDepth * scene_FogParams.x + scene_FogParams.y , 0.0 , 1.0 ) ; \n"],[5,55],[3,"SCENE_FOG_MODE","==",2,52],[0," float fogIntensity = clamp ( exp2 ( - fogDepth * scene_FogParams.z ) , 0.0 , 1.0 ) ; \n"],[5,55],[3,"SCENE_FOG_MODE","==",3,55],[0," float factor = fogDepth * scene_FogParams.w ;\nfloat fogIntensity = clamp ( exp2 ( - factor * factor ) , 0.0 , 1.0 ) ; \n"],[6],[0,"\ncolor.rgb = mix ( scene_FogColor.rgb , color.rgb , fogIntensity ) ;\nreturn color ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",65],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",95],[0,"\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",73],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",77],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,81],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",89],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",87],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},93],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"varying vec4 positionCS;\n\n\n"],[6],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShadingSSS"],[0,"\n\n"],[2,"BSDF_INCLUDED",189],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",111],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",109],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},121],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",125],[0,"\n\n"],[6],[0,"\nstruct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; \n"],[1,"NEED_TANGENT",129],[0," vec3 tangent ; vec3 bitangent ; \n"],[6],[0," vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",133],[0," float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",137],[0," float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",141],[0," float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",145],[0," float sheenRoughness ; vec3 sheenColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_TRANSMISSION",149],[0," vec3 absorptionCoefficient ; float transmission ; float thickness ; \n"],[6],[0," } ;\nfloat F_Schlick ( float f0, float f90, float dotLH ) { return f0 + ( f90 - f0 ) * ( pow ( 1.0 - dotLH , 5.0 ) ) ; }\nvec3 F_Schlick ( vec3 f0, float f90, float dotLH ) { float fresnel = exp2 ( ( - 5.55473 * dotLH - 6.98316 ) * dotLH ) ;\nreturn ( f90 - f0 ) * fresnel + f0 ; }\nfloat G_GGX_SmithCorrelated ( float alpha, float dotNL, float dotNV ) { float a2 = pow2(alpha) ;\nfloat gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNV) ) ;\nfloat gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNL) ) ;\nreturn 0.5 / max ( gv + gl , EPSILON ) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",153],[0,"\nfloat G_GGX_SmithCorrelated_Anisotropic ( float at, float ab, float ToV, float BoV, float ToL, float BoL, float NoV, float NoL ) { float lambdaV = NoL * length ( vec3 ( at * ToV , ab * BoV , NoV ) ) ;\nfloat lambdaL = NoV * length ( vec3 ( at * ToL , ab * BoL , NoL ) ) ;\nreturn 0.5 / max ( lambdaV + lambdaL , EPSILON ) ; }\n\n"],[6],[0,"\nfloat D_GGX ( float alpha, float dotNH ) { float a2 = pow2(alpha) ;\nfloat denom = pow2(dotNH) * ( a2 - 1.0 ) + 1.0 ;\nreturn RECIPROCAL_PI * a2 / pow2(denom) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",157],[0,"\nfloat D_GGX_Anisotropic ( float at, float ab, float ToH, float BoH, float NoH ) { float a2 = at * ab ;\nhighp vec3 d = vec3 ( ab * ToH , at * BoH , a2 * NoH ) ;\nhighp float d2 = dot ( d , d ) ;\nfloat b2 = a2 / d2 ;\nreturn a2 * b2 * b2 * RECIPROCAL_PI ; }\n\n"],[6],[0,"\nfloat DG_GGX ( float alpha, float dotNV, float dotNL, float dotNH ) { float D = D_GGX(alpha, dotNH) ;\nfloat G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV) ;\nreturn G * D ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",161],[0,"\nfloat DG_GGX_anisotropic ( vec3 h, vec3 l, SurfaceData surfaceData, float alpha, float dotNV, float dotNL, float dotNH ) { vec3 t = surfaceData.anisotropicT ;\nvec3 b = surfaceData.anisotropicB ;\nvec3 v = surfaceData.viewDir ;\nfloat dotTV = dot ( t , v ) ;\nfloat dotBV = dot ( b , v ) ;\nfloat dotTL = dot ( t , l ) ;\nfloat dotBL = dot ( b , l ) ;\nfloat dotTH = dot ( t , h ) ;\nfloat dotBH = dot ( b , h ) ;\nfloat at = max ( alpha * ( 1.0 + surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat ab = max ( alpha * ( 1.0 - surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat D = D_GGX_Anisotropic(at, ab, dotTH, dotBH, dotNH) ;\nfloat G = G_GGX_SmithCorrelated_Anisotropic(at, ab, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL) ;\nreturn G * D ; }\n\n"],[6],[0,"\nvec3 BRDF_Specular_GGX ( vec3 incidentDirection, SurfaceData surfaceData, BSDFData bsdfData, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2(roughness) ;\nvec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( normal , incidentDirection )) ;\nfloat dotNV = saturate(dot ( normal , surfaceData.viewDir )) ;\nfloat dotNH = saturate(dot ( normal , halfDir )) ;\nfloat dotLH = saturate(dot ( incidentDirection , halfDir )) ;\nvec3 F = F_Schlick(specularColor, bsdfData.specularF90, dotLH) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",165],[0," F = mix ( F , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",169],[0," float GD = DG_GGX_anisotropic(halfDir, incidentDirection, surfaceData, alpha, dotNV, dotNL, dotNH) ; \n"],[5,171],[0," float GD = DG_GGX(alpha, dotNV, dotNL, dotNH) ; \n"],[6],[0,"\nreturn F * GD ; }\nvec3 BRDF_Diffuse_Lambert ( vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor ; }\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",175],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",179],[0,"\nfloat D_Charlie ( float roughness, float dotNH ) { float invAlpha = 1.0 / roughness ;\nfloat cos2h = dotNH * dotNH ;\nfloat sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;\nreturn ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ; }\nfloat V_Neubelt ( float NoV, float NoL ) { return saturate(1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) )) ; }\nvec3 sheenBRDF ( vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness ) { vec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nfloat dotNH = saturate(dot ( surfaceData.normal , halfDir )) ;\nfloat D = D_Charlie(sheenRoughness, dotNH) ;\nfloat V = V_Neubelt(surfaceData.dotNV, dotNL) ;\nvec3 F = sheenColor ;\nreturn D * V * F ; }\n\n"],[6],[0,"\nvec2 envDFGApprox ( float roughness, float dotNV ) { const vec4 c0 = vec4 ( - 1 , - 0.0275 , - 0.572 , 0.022 ) ;\nconst vec4 c1 = vec4 ( 1 , 0.0425 , 1.04 , - 0.04 ) ;\nvec4 r = roughness * c0 + c1 ;\nfloat a004 = min ( r.x * r.x , exp2 ( - 9.28 * dotNV ) ) * r.x + r.y ;\nreturn vec2 ( - 1.04 , 1.04 ) * a004 + r.zw ; }\nvec3 envBRDFApprox ( vec3 f0, float f90, float roughness, float dotNV ) { vec2 AB = envDFGApprox(roughness, dotNV) ;\nreturn f0 * AB.x + f90 * AB.y ; }\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",183],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",187],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",203],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\nvoid diffuseLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 attenuationIrradiance, inout vec3 diffuseColor ) { diffuseColor += attenuationIrradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nvoid specularLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor ) { specularColor += attenuationIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.normal, bsdfData.specularF0, bsdfData.roughness) * bsdfData.energyCompensation ; }\nvoid sheenLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",197],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nspecularColor += attenuationIrradiance * sheenBRDF(incidentDirection, surfaceData, surfaceData.sheenColor, bsdfData.sheenRoughness) ; \n"],[6],[0," }\nfloat clearCoatLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 color, inout vec3 specularColor ) { float attenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",201],[0," float clearCoatDotNL = saturate(dot ( surfaceData.clearCoatNormal , incidentDirection )) ;\nvec3 clearCoatIrradiance = clearCoatDotNL * color ;\nspecularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.clearCoatNormal, bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness) ;\nattenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn attenuation ; }\n\n"],[6],[0,"\nuniform vec4 material_SkinScatterAmount;\nuniform float material_CurvaturePower;\n\n"],[1,"MATERIAL_HAS_CURVATEXTURE",207],[0,"\nuniform sampler2D material_CurvatureTexture;\n\n"],[6],[0,"\nstruct FsphericalGaussian { vec3 Axis ; vec3 Sharpness ; vec3 Amplitude ; } ;\nvec3 dotCosineLobe ( FsphericalGaussian G, vec3 N ) { float muDotN = dot ( G.Axis , N ) ;\nconst vec3 c0 = vec3 ( 0.36 ) ;\nconst vec3 c1 = vec3 ( 0.25 / c0 ) ;\nvec3 eml = exp ( - G.Sharpness ) ;\nvec3 em2l = eml * eml ;\nvec3 rl = 1.0 / G.Sharpness ;\nvec3 scale = 1.0 + 2.0 * em2l - rl ;\nvec3 bias = ( eml - em2l ) * rl - em2l ;\nvec3 x = sqrt ( vec3 ( 1.0 ) - scale ) ;\nvec3 x0 = c0 * muDotN ;\nvec3 x1 = c1 * x ;\nvec3 n = x0 + x1 ;\nvec3 y ;\nif ( all ( lessThanEqual ( abs ( x0 ) , x1 ) ) ) { y = ( n * n ) / x ; } else { y = clamp ( vec3 ( muDotN ) , vec3 ( 0.0 ) , vec3 ( 1.0 ) ) ; }\nreturn scale * y + bias ; }\nFsphericalGaussian makeNormalizedSG ( vec3 lightdir, vec3 sharpness ) { FsphericalGaussian sg ;\nsg.Axis = lightdir ;\nsg.Sharpness = sharpness ;\nsg.Amplitude = sg.Sharpness / ( ( 2.0 * PI ) * ( 1.0 - exp ( - 2.0 * sg.Sharpness ) ) ) ;\nreturn sg ; }\nvec3 sgdiffuseLighting ( vec3 light, vec3 normal, vec3 scatterAmt ) { FsphericalGaussian Kernel = makeNormalizedSG(light, 1.0 / max ( scatterAmt.xyz , 0.0001 )) ;\nvec3 diffuse = dotCosineLobe(Kernel, normal) ;\nvec3 diffuselobe = max ( vec3 ( 0.0 ) , ( diffuse - 0.004 ) ) ;\ndiffuse = ( diffuselobe * ( 6.2 * diffuselobe + 0.5 ) ) / ( diffuselobe * ( 6.2 * diffuselobe + 1.7 ) + 0.06 ) ;\nreturn diffuse ; }\nvoid surfaceShadingSSS ( SurfaceData surfaceData, BRDFData brdfData, vec3 incidentDirection, vec3 lightColor, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\n\n"],[1,"MATERIAL_HAS_CURVATEXTURE",211],[0," vec4 skinCurvatureTexture = texture2D ( material_CurvatureTexture , uv ) ; \n"],[5,213],[0," vec4 skinCurvatureTexture = vec4 ( 1 ) ; \n"],[6],[0,"\nfloat skintexture = skinCurvatureTexture.r * material_CurvaturePower ;\nvec3 scatterAmt = material_SkinScatterAmount.rgb * skintexture ;\nvec3 sg = sgdiffuseLighting(incidentDirection, surfaceData.normal, scatterAmt) ;\nvec3 irradiance = sg * lightColor * PI ;\nfloat attenuation = clearCoatLobe(surfaceData, brdfData, incidentDirection, lightColor, specularColor) ;\nvec3 attenuationIrradiance = attenuation * irradiance ;\ndiffuseLobe(surfaceData, brdfData, attenuationIrradiance, diffuseColor) ;\nif ( surfaceData.dotNV > EPSILON ) { specularLobe(surfaceData, brdfData, incidentDirection, attenuationIrradiance, specularColor) ; }\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",449],[0,"\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",223],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",229],[0,"\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",235],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",241],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",247],[0,"\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",339],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",261],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",259],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},271],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",275],[0,"\n\n"],[6],[0,"\nstruct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; \n"],[1,"NEED_TANGENT",279],[0," vec3 tangent ; vec3 bitangent ; \n"],[6],[0," vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",283],[0," float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",287],[0," float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",291],[0," float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",295],[0," float sheenRoughness ; vec3 sheenColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_TRANSMISSION",299],[0," vec3 absorptionCoefficient ; float transmission ; float thickness ; \n"],[6],[0," } ;\nfloat F_Schlick ( float f0, float f90, float dotLH ) { return f0 + ( f90 - f0 ) * ( pow ( 1.0 - dotLH , 5.0 ) ) ; }\nvec3 F_Schlick ( vec3 f0, float f90, float dotLH ) { float fresnel = exp2 ( ( - 5.55473 * dotLH - 6.98316 ) * dotLH ) ;\nreturn ( f90 - f0 ) * fresnel + f0 ; }\nfloat G_GGX_SmithCorrelated ( float alpha, float dotNL, float dotNV ) { float a2 = pow2(alpha) ;\nfloat gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNV) ) ;\nfloat gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNL) ) ;\nreturn 0.5 / max ( gv + gl , EPSILON ) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",303],[0,"\nfloat G_GGX_SmithCorrelated_Anisotropic ( float at, float ab, float ToV, float BoV, float ToL, float BoL, float NoV, float NoL ) { float lambdaV = NoL * length ( vec3 ( at * ToV , ab * BoV , NoV ) ) ;\nfloat lambdaL = NoV * length ( vec3 ( at * ToL , ab * BoL , NoL ) ) ;\nreturn 0.5 / max ( lambdaV + lambdaL , EPSILON ) ; }\n\n"],[6],[0,"\nfloat D_GGX ( float alpha, float dotNH ) { float a2 = pow2(alpha) ;\nfloat denom = pow2(dotNH) * ( a2 - 1.0 ) + 1.0 ;\nreturn RECIPROCAL_PI * a2 / pow2(denom) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",307],[0,"\nfloat D_GGX_Anisotropic ( float at, float ab, float ToH, float BoH, float NoH ) { float a2 = at * ab ;\nhighp vec3 d = vec3 ( ab * ToH , at * BoH , a2 * NoH ) ;\nhighp float d2 = dot ( d , d ) ;\nfloat b2 = a2 / d2 ;\nreturn a2 * b2 * b2 * RECIPROCAL_PI ; }\n\n"],[6],[0,"\nfloat DG_GGX ( float alpha, float dotNV, float dotNL, float dotNH ) { float D = D_GGX(alpha, dotNH) ;\nfloat G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV) ;\nreturn G * D ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",311],[0,"\nfloat DG_GGX_anisotropic ( vec3 h, vec3 l, SurfaceData surfaceData, float alpha, float dotNV, float dotNL, float dotNH ) { vec3 t = surfaceData.anisotropicT ;\nvec3 b = surfaceData.anisotropicB ;\nvec3 v = surfaceData.viewDir ;\nfloat dotTV = dot ( t , v ) ;\nfloat dotBV = dot ( b , v ) ;\nfloat dotTL = dot ( t , l ) ;\nfloat dotBL = dot ( b , l ) ;\nfloat dotTH = dot ( t , h ) ;\nfloat dotBH = dot ( b , h ) ;\nfloat at = max ( alpha * ( 1.0 + surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat ab = max ( alpha * ( 1.0 - surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat D = D_GGX_Anisotropic(at, ab, dotTH, dotBH, dotNH) ;\nfloat G = G_GGX_SmithCorrelated_Anisotropic(at, ab, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL) ;\nreturn G * D ; }\n\n"],[6],[0,"\nvec3 BRDF_Specular_GGX ( vec3 incidentDirection, SurfaceData surfaceData, BSDFData bsdfData, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2(roughness) ;\nvec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( normal , incidentDirection )) ;\nfloat dotNV = saturate(dot ( normal , surfaceData.viewDir )) ;\nfloat dotNH = saturate(dot ( normal , halfDir )) ;\nfloat dotLH = saturate(dot ( incidentDirection , halfDir )) ;\nvec3 F = F_Schlick(specularColor, bsdfData.specularF90, dotLH) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",315],[0," F = mix ( F , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",319],[0," float GD = DG_GGX_anisotropic(halfDir, incidentDirection, surfaceData, alpha, dotNV, dotNL, dotNH) ; \n"],[5,321],[0," float GD = DG_GGX(alpha, dotNV, dotNL, dotNH) ; \n"],[6],[0,"\nreturn F * GD ; }\nvec3 BRDF_Diffuse_Lambert ( vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor ; }\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",325],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",329],[0,"\nfloat D_Charlie ( float roughness, float dotNH ) { float invAlpha = 1.0 / roughness ;\nfloat cos2h = dotNH * dotNH ;\nfloat sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;\nreturn ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ; }\nfloat V_Neubelt ( float NoV, float NoL ) { return saturate(1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) )) ; }\nvec3 sheenBRDF ( vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness ) { vec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nfloat dotNH = saturate(dot ( surfaceData.normal , halfDir )) ;\nfloat D = D_Charlie(sheenRoughness, dotNH) ;\nfloat V = V_Neubelt(surfaceData.dotNV, dotNL) ;\nvec3 F = sheenColor ;\nreturn D * V * F ; }\n\n"],[6],[0,"\nvec2 envDFGApprox ( float roughness, float dotNV ) { const vec4 c0 = vec4 ( - 1 , - 0.0275 , - 0.572 , 0.022 ) ;\nconst vec4 c1 = vec4 ( 1 , 0.0425 , 1.04 , - 0.04 ) ;\nvec4 r = roughness * c0 + c1 ;\nfloat a004 = min ( r.x * r.x , exp2 ( - 9.28 * dotNV ) ) * r.x + r.y ;\nreturn vec2 ( - 1.04 , 1.04 ) * a004 + r.zw ; }\nvec3 envBRDFApprox ( vec3 f0, float f90, float roughness, float dotNV ) { vec2 AB = envDFGApprox(roughness, dotNV) ;\nreturn f0 * AB.x + f90 * AB.y ; }\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",333],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",337],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",387],[0,"\n"],[7,"LIGHT_INCLUDED"],[0,"\nuniform ivec4 renderer_Layer;\n\n"],[2,"GRAPHICS_API_WEBGL2",347],[0,"\nbool isBitSet ( float value, float mask, float bitIndex ) { return mod ( floor ( value / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 && mod ( floor ( mask / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 ; }\n\n"],[6],[0,"\nbool isRendererCulledByLight ( ivec2 rendererLayer, ivec2 lightCullingMask ) { \n"],[1,"GRAPHICS_API_WEBGL2",351],[0," return ! ( ( rendererLayer.x & lightCullingMask.x ) != 0 || ( rendererLayer.y & lightCullingMask.y ) != 0 ) ; \n"],[5,353],[0," for ( int i = 0 ; i < 16 ; i ++ ) { if ( isBitSet(float ( rendererLayer.x ), float ( lightCullingMask.x ), float ( i )) || isBitSet(float ( rendererLayer.y ), float ( lightCullingMask.y ), float ( i )) ) { return false ; } }\nreturn true ; \n"],[6],[0," }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",361],[0,"\nstruct DirectLight { vec3 color ; vec3 direction ; } ;\nuniform ivec2 scene_DirectLightCullingMask [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightColor [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightDirection [ SCENE_DIRECT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",359],[0,"\nDirectLight getDirectLight ( int index ) { DirectLight light ;\nlight.color = scene_DirectLightColor[index] ;\nlight.direction = scene_DirectLightDirection[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",369],[0,"\nstruct PointLight { vec3 color ; vec3 position ; float distance ; } ;\nuniform ivec2 scene_PointLightCullingMask [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightColor [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightPosition [ SCENE_POINT_LIGHT_COUNT ];\nuniform float scene_PointLightDistance [ SCENE_POINT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",367],[0,"\nPointLight getPointLight ( int index ) { PointLight light ;\nlight.color = scene_PointLightColor[index] ;\nlight.position = scene_PointLightPosition[index] ;\nlight.distance = scene_PointLightDistance[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",377],[0,"\nstruct SpotLight { vec3 color ; vec3 position ; vec3 direction ; float distance ; float angleCos ; float penumbraCos ; } ;\nuniform ivec2 scene_SpotLightCullingMask [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightColor [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightPosition [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightDirection [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightDistance [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightAngleCos [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightPenumbraCos [ SCENE_SPOT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",375],[0,"\nSpotLight getSpotLight ( int index ) { SpotLight light ;\nlight.color = scene_SpotLightColor[index] ;\nlight.position = scene_SpotLightPosition[index] ;\nlight.direction = scene_SpotLightDirection[index] ;\nlight.distance = scene_SpotLightDistance[index] ;\nlight.angleCos = scene_SpotLightAngleCos[index] ;\nlight.penumbraCos = scene_SpotLightPenumbraCos[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\nstruct EnvMapLight { vec3 diffuse ; float mipMapLevel ; float diffuseIntensity ; float specularIntensity ; } ;\nuniform EnvMapLight scene_EnvMapLight;\n\n"],[1,"SCENE_USE_SH",381],[0,"\nuniform vec3 scene_EnvSH [ 9 ];\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",385],[0,"\nuniform samplerCube scene_EnvSpecularSampler;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",401],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\nvoid diffuseLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 attenuationIrradiance, inout vec3 diffuseColor ) { diffuseColor += attenuationIrradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nvoid specularLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor ) { specularColor += attenuationIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.normal, bsdfData.specularF0, bsdfData.roughness) * bsdfData.energyCompensation ; }\nvoid sheenLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",395],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nspecularColor += attenuationIrradiance * sheenBRDF(incidentDirection, surfaceData, surfaceData.sheenColor, bsdfData.sheenRoughness) ; \n"],[6],[0," }\nfloat clearCoatLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 color, inout vec3 specularColor ) { float attenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",399],[0," float clearCoatDotNL = saturate(dot ( surfaceData.clearCoatNormal , incidentDirection )) ;\nvec3 clearCoatIrradiance = clearCoatDotNL * color ;\nspecularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.clearCoatNormal, bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness) ;\nattenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn attenuation ; }\n\n"],[6],[0,"\nvoid surfaceShading ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 lightColor, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nvec3 irradiance = dotNL * lightColor * PI ;\nfloat attenuation = FUNCTION_CLEAR_COAT_LOBE(surfaceData, bsdfData, incidentDirection, lightColor, specularColor) ;\nvec3 attenuationIrradiance = attenuation * irradiance ;\nFUNCTION_DIFFUSE_LOBE(surfaceData, bsdfData, attenuationIrradiance, diffuseColor) ;\nFUNCTION_SPECULAR_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, specularColor) ;\nFUNCTION_SHEEN_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",405],[0,"\nvoid addDirectionalDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, DirectLight directionalLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lightColor = directionalLight.color ;\nvec3 direction = - directionalLight.direction ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",409],[0,"\nvoid addPointDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, PointLight pointLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = pointLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nvec3 lightColor = pointLight.color ;\nlightColor *= clamp ( 1.0 - pow ( lightDistance / pointLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",413],[0,"\nvoid addSpotDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, SpotLight spotLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = spotLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nfloat angleCos = dot ( direction , - spotLight.direction ) ;\nfloat spotEffect = smoothstep ( spotLight.penumbraCos , spotLight.angleCos , angleCos ) ;\nfloat decayEffect = clamp ( 1.0 - pow ( lightDistance / spotLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nvec3 lightColor = spotLight.color ;\nlightColor *= spotEffect * decayEffect ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\nvoid evaluateDirectRadiance ( SurfaceData surfaceData, BSDFData bsdfData, float shadowAttenuation, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { \n"],[1,"SCENE_DIRECT_LIGHT_COUNT",427],[0," for ( int i = 0 ; i < SCENE_DIRECT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_DirectLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",419],[0," DirectLight directionalLight = getDirectLight(i) ; \n"],[5,421],[0," DirectLight directionalLight ;\ndirectionalLight.color = scene_DirectLightColor[i] ;\ndirectionalLight.direction = scene_DirectLightDirection[i] ; \n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",425],[0," if ( i == 0 ) { directionalLight.color *= shadowAttenuation ; } \n"],[6],[0,"\naddDirectionalDirectLightRadiance(surfaceData, bsdfData, directionalLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",437],[0," for ( int i = 0 ; i < SCENE_POINT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_PointLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",433],[0," PointLight pointLight = getPointLight(i) ; \n"],[5,435],[0," PointLight pointLight ;\npointLight.color = scene_PointLightColor[i] ;\npointLight.position = scene_PointLightPosition[i] ;\npointLight.distance = scene_PointLightDistance[i] ; \n"],[6],[0,"\naddPointDirectLightRadiance(surfaceData, bsdfData, pointLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",447],[0," for ( int i = 0 ; i < SCENE_SPOT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_SpotLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",443],[0," SpotLight spotLight = getSpotLight(i) ; \n"],[5,445],[0," SpotLight spotLight ;\nspotLight.color = scene_SpotLightColor[i] ;\nspotLight.position = scene_SpotLightPosition[i] ;\nspotLight.direction = scene_SpotLightDirection[i] ;\nspotLight.distance = scene_SpotLightDistance[i] ;\nspotLight.angleCos = scene_SpotLightAngleCos[i] ;\nspotLight.penumbraCos = scene_SpotLightPenumbraCos[i] ; \n"],[6],[0,"\naddSpotDirectLightRadiance(surfaceData, bsdfData, spotLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",525],[0,"\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",459],[0,"\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",465],[0,"\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",471],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",477],[0,"\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",509],[0,"\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\nvec3 getReflectedVector ( SurfaceData surfaceData, vec3 n ) { \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",485],[0," vec3 r = reflect ( - surfaceData.viewDir , surfaceData.anisotropicN ) ; \n"],[5,487],[0," vec3 r = reflect ( - surfaceData.viewDir , n ) ; \n"],[6],[0,"\nreturn r ; }\nfloat getSpecularMIPLevel ( float roughness, int maxMIPLevel ) { return roughness * float ( maxMIPLevel ) ; }\nvec3 getLightProbeRadiance ( SurfaceData surfaceData, vec3 normal, float roughness ) { \n"],[2,"SCENE_USE_SPECULAR_ENV",491],[0," return vec3 ( 0 ) ; \n"],[5,503],[0," vec3 reflectVec = getReflectedVector(surfaceData, normal) ;\nfloat specularMIPLevel = getSpecularMIPLevel(roughness, int ( scene_EnvMapLight.mipMapLevel )) ;\n\n"],[1,"HAS_TEX_LOD",495],[0," vec4 envMapColor = textureCubeLodEXT ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[5,497],[0," vec4 envMapColor = textureCube ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[6],[0,"\n\n"],[1,"ENGINE_NO_SRGB",501],[0," envMapColor = sRGBToLinear(envMapColor) ; \n"],[6],[0,"\nreturn envMapColor.rgb * scene_EnvMapLight.specularIntensity ; \n"],[6],[0," }\nfloat evaluateSpecularOcclusion ( float dotNV, float diffuseAO, float roughness ) { float specularAOFactor = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"or","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"SCENE_ENABLE_AMBIENT_OCCLUSION"}},"r":{"t":"def","m":"SCENE_USE_SPECULAR_ENV"}},507],[0," specularAOFactor = saturate(pow ( dotNV + diffuseAO , exp2 ( - 16.0 * roughness - 1.0 ) ) - 1.0 + diffuseAO) ; \n"],[6],[0,"\nreturn specularAOFactor ; }\n\n"],[6],[0,"\nvec3 getLightProbeIrradiance ( vec3 sh [ 9 ], vec3 normal ) { vec3 result = sh[0] + sh[1] * ( normal.y ) + sh[2] * ( normal.z ) + sh[3] * ( normal.x ) + sh[4] * ( normal.y * normal.x ) + sh[5] * ( normal.y * normal.z ) + sh[6] * ( 3.0 * normal.z * normal.z - 1.0 ) + sh[7] * ( normal.z * normal.x ) + sh[8] * ( normal.x * normal.x - normal.y * normal.y ) ;\nreturn max ( result , vec3 ( 0.0 ) ) ; }\nvoid evaluateDiffuseIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 diffuseColor ) { \n"],[1,"SCENE_USE_SH",513],[0," vec3 irradiance = getLightProbeIrradiance(scene_EnvSH, surfaceData.normal) ;\nirradiance *= scene_EnvMapLight.diffuseIntensity ; \n"],[5,515],[0," vec3 irradiance = scene_EnvMapLight.diffuse * scene_EnvMapLight.diffuseIntensity ;\nirradiance *= PI ; \n"],[6],[0,"\ndiffuseColor += bsdfData.diffuseAO * irradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nfloat evaluateClearCoatIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 specularColor ) { float radianceAttenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",519],[0," vec3 clearCoatRadiance = getLightProbeRadiance(surfaceData, surfaceData.clearCoatNormal, bsdfData.clearCoatRoughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.clearCoatRoughness) ;\nspecularColor += specularAO * clearCoatRadiance * surfaceData.clearCoat * envBRDFApprox(bsdfData.clearCoatSpecularColor, 1.0, bsdfData.clearCoatRoughness, surfaceData.clearCoatDotNV) ;\nradianceAttenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn radianceAttenuation ; }\nvoid evaluateSpecularIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 outSpecularColor ) { vec3 radiance = getLightProbeRadiance(surfaceData, surfaceData.normal, bsdfData.roughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.roughness) ;\noutSpecularColor += specularAO * radianceAttenuation * radiance * envBRDFApprox(bsdfData.resolvedSpecularF0, bsdfData.specularF90, bsdfData.roughness, surfaceData.dotNV) * bsdfData.energyCompensation ; }\nvoid evaluateSheenIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",523],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.sheenRoughness) ;\nvec3 reflectance = specularAO * radianceAttenuation * bsdfData.approxIBLSheenDG * surfaceData.sheenColor ;\nspecularColor += reflectance ; \n"],[6],[0," }\nvoid evaluateIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nFUNCTION_DIFFUSE_IBL(surfaceData, bsdfData, diffuseColor) ;\nfloat radianceAttenuation = FUNCTION_CLEAR_COAT_IBL(surfaceData, bsdfData, specularColor) ;\nFUNCTION_SPECULAR_IBL(surfaceData, bsdfData, radianceAttenuation, specularColor) ;\nFUNCTION_SHEEN_IBL(surfaceData, bsdfData, radianceAttenuation, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",531],[0,"\n"],[7,"VERTEX_INCLUDE"],[0,"\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",782],[0,"\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",547],[0,"\n"],[7,"NORMAL_INCLUDED"],[0,"\nvec3 getNormalByNormalTexture ( mat3 tbn, sampler2D normalTexture, float normalIntensity, vec2 uv, bool isFrontFacing ) { vec3 normal = ( texture2D ( normalTexture , uv ) ).rgb ;\nnormal = normalize ( tbn * ( ( 2.0 * normal - 1.0 ) * vec3 ( normalIntensity , normalIntensity , 1.0 ) ) ) ;\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nreturn normal ; }\nmat3 getTBNByDerivatives ( vec2 uv, vec3 normal, vec3 position, bool isFrontFacing ) { \n"],[1,"HAS_DERIVATIVES",543],[0," uv = isFrontFacing ? uv : - uv ;\nvec3 dp1 = dFdx ( position ) ;\nvec3 dp2 = dFdy ( position ) ;\nvec2 duv1 = dFdx ( uv ) ;\nvec2 duv2 = dFdy ( uv ) ;\nvec3 dp2perp = cross ( dp2 , normal ) ;\nvec3 dp1perp = cross ( normal , dp1 ) ;\nvec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x ;\nvec3 bitangent = dp2perp * duv1.y + dp1perp * duv2.y ;\nfloat denom = max ( dot ( tangent , tangent ) , dot ( bitangent , bitangent ) ) ;\nfloat invmax = ( denom == 0.0 ) ? 0.0 : camera_ProjectionParams.x / sqrt ( denom ) ;\nreturn mat3 ( tangent * invmax , bitangent * invmax , normal ) ; \n"],[5,545],[0," return mat3 ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , normal ) ; \n"],[6],[0," }\n\n"],[6],[0,"\nuniform float material_AlphaCutoff;\nuniform vec4 material_BaseColor;\nuniform float material_Metal;\nuniform float material_Roughness;\nuniform float material_IOR;\nuniform vec3 material_EmissiveColor;\nuniform float material_NormalIntensity;\nuniform float material_OcclusionIntensity;\nuniform float material_OcclusionTextureCoord;\nuniform float material_SpecularIntensity;\nuniform vec3 material_SpecularColor;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",551],[0,"\nuniform sampler2D material_SpecularIntensityTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",555],[0,"\nuniform sampler2D material_SpecularColorTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",571],[0,"\nuniform float material_ClearCoat;\nuniform float material_ClearCoatRoughness;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",561],[0,"\nuniform sampler2D material_ClearCoatTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",565],[0,"\nuniform sampler2D material_ClearCoatRoughnessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",569],[0,"\nuniform sampler2D material_ClearCoatNormalTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",579],[0,"\nuniform vec3 material_AnisotropyInfo;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",577],[0,"\nuniform sampler2D material_AnisotropyTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",591],[0,"\nuniform vec4 material_IridescenceInfo;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",585],[0,"\nuniform sampler2D material_IridescenceThicknessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",589],[0,"\nuniform sampler2D material_IridescenceTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",603],[0,"\nuniform float material_SheenRoughness;\nuniform vec3 material_SheenColor;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",597],[0,"\nuniform sampler2D material_SheenTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",601],[0,"\nuniform sampler2D material_SheenRoughnessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",619],[0,"\nuniform float material_Transmission;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",609],[0,"\nuniform sampler2D material_TransmissionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",617],[0,"\nuniform vec3 material_AttenuationColor;\nuniform float material_AttenuationDistance;\nuniform float material_Thickness;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",615],[0,"\nuniform sampler2D material_ThicknessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",623],[0,"\nuniform sampler2D material_BaseTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",627],[0,"\nuniform sampler2D material_NormalTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",631],[0,"\nuniform sampler2D material_EmissiveTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",635],[0,"\nuniform sampler2D material_RoughnessMetallicTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",639],[0,"\nuniform sampler2D material_OcclusionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",643],[0,"\nvec3 getAnisotropicBentNormal ( SurfaceData surfaceData ) { vec3 anisotropyDirection = ( surfaceData.anisotropy >= 0.0 ) ? surfaceData.anisotropicB : surfaceData.anisotropicT ;\nvec3 anisotropicTangent = cross ( anisotropyDirection , surfaceData.viewDir ) ;\nvec3 anisotropicNormal = cross ( anisotropicTangent , anisotropyDirection ) ;\nvec3 bentNormal = normalize ( mix ( surfaceData.normal , anisotropicNormal , abs ( surfaceData.anisotropy ) * saturate(5.0 * surfaceData.roughness) ) ) ;\nreturn bentNormal ; }\n\n"],[6],[0,"\nSurfaceData getSurfaceData ( vec2 aoUV, bool isFrontFacing ) { SurfaceData surfaceData ;\nvec2 uv = uv ;\nvec4 baseColor = material_BaseColor ;\nfloat metallic = material_Metal ;\nfloat roughness = material_Roughness ;\nvec3 emissiveRadiance = material_EmissiveColor ;\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",647],[0," baseColor *= texture2DSRGB(material_BaseTexture, uv) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",651],[0," baseColor *= vertexColor ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_IS_ALPHA_CUTOFF",655],[0," if ( baseColor.a < material_AlphaCutoff ) { discard ; } \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",659],[0," vec4 metalRoughMapColor = texture2D ( material_RoughnessMetallicTexture , uv ) ;\nroughness *= metalRoughMapColor.g ;\nmetallic *= metalRoughMapColor.b ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",663],[0," emissiveRadiance *= texture2DSRGB(material_EmissiveTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.albedoColor = baseColor.rgb ;\nsurfaceData.emissiveColor = emissiveRadiance ;\nsurfaceData.metallic = metallic ;\nsurfaceData.roughness = roughness ;\nsurfaceData.IOR = material_IOR ;\n\n"],[1,"MATERIAL_IS_TRANSPARENT",667],[0," surfaceData.opacity = baseColor.a ; \n"],[5,669],[0," surfaceData.opacity = 1.0 ; \n"],[6],[0,"\nsurfaceData.position = positionWS ;\nsurfaceData.positionCS = positionCS ;\n\n"],[1,"CAMERA_ORTHOGRAPHIC",673],[0," surfaceData.viewDir = - camera_Forward ; \n"],[5,675],[0," surfaceData.viewDir = normalize ( camera_Position - positionWS ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",679],[0," vec3 normal = normalize ( normalWS ) ; \n"],[5,684],[1,"HAS_DERIVATIVES",682],[0," vec3 pos_dx = dFdx ( positionWS ) ;\nvec3 pos_dy = dFdy ( positionWS ) ;\nvec3 normal = normalize ( cross ( pos_dx , pos_dy ) ) ;\nnormal *= camera_ProjectionParams.x ; \n"],[5,684],[0," vec3 normal = vec3 ( 0 , 0 , 1 ) ; \n"],[6],[0,"\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nsurfaceData.normal = normal ;\n\n"],[1,"NEED_TANGENT",698],[0," \n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},690],[0," surfaceData.tangent = tangentWS ;\nsurfaceData.bitangent = bitangentWS ;\nmat3 tbn = mat3 ( tangentWS , bitangentWS , normalWS ) ; \n"],[5,692],[0," mat3 tbn = getTBNByDerivatives(uv, normal, positionWS, isFrontFacing) ;\nsurfaceData.tangent = tbn[0] ;\nsurfaceData.bitangent = tbn[1] ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",696],[0," surfaceData.normal = getNormalByNormalTexture(tbn, material_NormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[6],[0," \n"],[6],[0,"\nsurfaceData.dotNV = saturate(dot ( surfaceData.normal , surfaceData.viewDir )) ;\nsurfaceData.specularIntensity = material_SpecularIntensity ;\nsurfaceData.specularColor = material_SpecularColor ;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",702],[0," surfaceData.specularIntensity *= texture2D ( material_SpecularIntensityTexture , uv ).a ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",706],[0," surfaceData.specularColor *= texture2D ( material_SpecularColorTexture , uv ).rgb ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",724],[0," \n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",712],[0," surfaceData.clearCoatNormal = getNormalByNormalTexture(tbn, material_ClearCoatNormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[5,714],[0," surfaceData.clearCoatNormal = normal ; \n"],[6],[0,"\nsurfaceData.clearCoatDotNV = saturate(dot ( surfaceData.clearCoatNormal , surfaceData.viewDir )) ;\nsurfaceData.clearCoat = material_ClearCoat ;\nsurfaceData.clearCoatRoughness = material_ClearCoatRoughness ;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",718],[0," surfaceData.clearCoat *= ( texture2D ( material_ClearCoatTexture , uv ) ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",722],[0," surfaceData.clearCoatRoughness *= ( texture2D ( material_ClearCoatRoughnessTexture , uv ) ).g ; \n"],[6],[0,"\nsurfaceData.clearCoat = saturate(surfaceData.clearCoat) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",732],[0," float anisotropy = material_AnisotropyInfo.z ;\nvec3 anisotropicDirection = vec3 ( material_AnisotropyInfo.xy , 0.0 ) ;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",730],[0," vec3 anisotropyTextureInfo = ( texture2D ( material_AnisotropyTexture , uv ) ).rgb ;\nanisotropy *= anisotropyTextureInfo.b ;\nanisotropicDirection.xy *= anisotropyTextureInfo.rg * 2.0 - 1.0 ; \n"],[6],[0,"\nsurfaceData.anisotropy = anisotropy ;\nsurfaceData.anisotropicT = normalize ( mat3 ( surfaceData.tangent , surfaceData.bitangent , surfaceData.normal ) * anisotropicDirection ) ;\nsurfaceData.anisotropicB = normalize ( cross ( surfaceData.normal , surfaceData.anisotropicT ) ) ;\nsurfaceData.anisotropicN = getAnisotropicBentNormal(surfaceData) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",746],[0," surfaceData.iridescenceFactor = material_IridescenceInfo.x ;\nsurfaceData.iridescenceIOR = material_IridescenceInfo.y ;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",738],[0," float iridescenceThicknessWeight = texture2D ( material_IridescenceThicknessTexture , uv ).g ;\nsurfaceData.iridescenceThickness = mix ( material_IridescenceInfo.z , material_IridescenceInfo.w , iridescenceThicknessWeight ) ; \n"],[5,740],[0," surfaceData.iridescenceThickness = material_IridescenceInfo.w ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",744],[0," surfaceData.iridescenceFactor *= texture2D ( material_IridescenceTexture , uv ).r ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",758],[0," vec3 sheenColor = material_SheenColor ;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",752],[0," sheenColor *= texture2DSRGB(material_SheenTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.sheenColor = sheenColor ;\nsurfaceData.sheenRoughness = material_SheenRoughness ;\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",756],[0," surfaceData.sheenRoughness *= texture2D ( material_SheenRoughnessTexture , uv ).a ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",774],[0," surfaceData.transmission = material_Transmission ;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",764],[0," surfaceData.transmission *= texture2D ( material_TransmissionTexture , uv ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",772],[0," surfaceData.absorptionCoefficient = - log ( material_AttenuationColor + HALF_EPS ) / max ( HALF_EPS , material_AttenuationDistance ) ;\nsurfaceData.thickness = max ( material_Thickness , 0.0001 ) ;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",770],[0," surfaceData.thickness *= texture2D ( material_ThicknessTexture , uv ).g ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",778],[0," surfaceData.ambientOcclusion = ( ( texture2D ( material_OcclusionTexture , aoUV ) ).r - 1.0 ) * material_OcclusionIntensity + 1.0 ; \n"],[5,780],[0," surfaceData.ambientOcclusion = 1.0 ; \n"],[6],[0,"\nreturn surfaceData ; }\n\n"],[6],[0,"\nvoid main() { BRDFData brdfData ;\nvec2 aoUV = uv ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"RENDERER_HAS_UV1"}},786],[0," if ( material_OcclusionTextureCoord == 1.0 ) { aoUV = uv1 ; } \n"],[6],[0,"\nSurfaceData surfaceData = getSurfaceData(aoUV, gl_FrontFacing) ;\nsurfaceData.f0 = 0.04 ;\ninitBRDFData ( surfaceData , brdfData ) ;\nvec3 totalDiffuseColor = vec3 ( 0 , 0 , 0 ) ;\nvec3 totalSpecularColor = vec3 ( 0 , 0 , 0 ) ;\nfloat shadowAttenuation = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_DIRECT_LIGHT_COUNT"},"r":{"t":"def","m":"NEED_CALCULATE_SHADOWS"}},796],[0," \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,792],[0," vec3 shadowCoord = shadowCoord ; \n"],[5,794],[0," vec3 shadowCoord = getShadowCoord ( positionWS ) ; \n"],[6],[0,"\nshadowAttenuation *= sampleShadowMap ( positionWS , shadowCoord ) ; \n"],[6],[0,"\nevaluateDirectRadiance(surfaceData, brdfData, shadowAttenuation, totalDiffuseColor, totalSpecularColor) ;\nevaluateIBL(surfaceData, brdfData, totalDiffuseColor, totalSpecularColor) ;\nvec4 color = vec4 ( totalDiffuseColor + totalSpecularColor , surfaceData.opacity ) ;\ncolor.rgb += surfaceData.emissiveColor ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,800],[0," color = fog(color, positionVS) ; \n"],[6],[0,"\ngl_FragColor = color ; }\n\n"],[6]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Extract the fragmentShaderInstructions section and reconstruct readable code
# The JSON structure uses arrays where index 0 is the instruction type and subsequent indices are values

# Write a Python script to parse and extract relevant parts
python3 << 'EOF'
import json
import re

# The provided snippet shows vertexShaderInstructions and fragmentShaderInstructions
# Let's focus on finding the SurfaceData struct definition and f0 assignments

# Read the code text from the review (the actual GLSL code is embedded in the JSON)
code_snippet = '''struct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; 
 vec3 tangent ; vec3 bitangent ; 
 vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; 
 float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; 
 float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; 
 float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; 
 float sheenRoughness ; vec3 sheenColor ; 
 vec3 absorptionCoefficient ; float transmission ; float thickness ; 
 } ;'''

print("=== SurfaceData struct definition ===")
print(code_snippet)
print("\n=== Searching for 'f0' in struct ===")
if 'f0' in code_snippet.lower():
    print("Found: 'f0' is declared in struct")
else:
    print("NOT FOUND: 'f0' is NOT declared in struct")

print("\n=== Now checking for surfaceData.f0 assignment ===")
assignment_code = '''SurfaceData surfaceData = getSurfaceData(aoUV, gl_FrontFacing) ;
surfaceData.f0 = 0.04 ;
initBRDFData ( surfaceData , brdfData ) ;'''

print(assignment_code)
if 'surfaceData.f0' in assignment_code:
    print("\nFOUND: Code assigns to surfaceData.f0")
else:
    print("\nNOT FOUND: No assignment to surfaceData.f0")

EOF

Repository: galacean/engine-toolkit

Length of output: 1089


🏁 Script executed:

# Now let's verify this is indeed the actual code by searching the original file
cd packages/custom-material/libs/advanced-shader/sss || exit 1
ls -la SSS.gsp 2>/dev/null || echo "File not found in expected location"

Repository: galacean/engine-toolkit

Length of output: 125


Add f0 member to SurfaceData struct or remove the assignment.

The fragment shader defines struct SurfaceData { ... } without an f0 field, but later assigns surfaceData.f0 = 0.04;. This causes a GLSL compile error. Add float f0; to the struct definition, or if initBRDFData() should derive it from existing fields, remove the assignment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/advanced-shader/sss/SSS.gsp` at line 1, The
fragment shader assigns surfaceData.f0 = 0.04 but SurfaceData struct lacks f0;
fix by adding a float f0; field to the SurfaceData definition (the struct named
SurfaceData in the fragment shader) so the assignment is valid, or alternatively
remove the assignment to surfaceData.f0 = 0.04 if initBRDFData or another
routine is expected to compute f0; update whichever is appropriate (SurfaceData
struct or the assignment near initialization before initBRDFData) to resolve the
GLSL compile error.

Comment thread packages/custom-material/libs/grid/Grid.gsp Outdated
Comment thread packages/custom-material/libs/planar-shadow/PlanarShadow.gsp
Comment thread rollup.config.mjs Outdated
Comment on lines +46 to +50
shaderCompiler({
precompile: {
input: path.join(process.cwd(), "packages/custom-material/src"),
output: path.join(process.cwd(), "packages/custom-material/libs")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "rollup.config.mjs" -type f

Repository: galacean/engine-toolkit

Length of output: 87


🏁 Script executed:

# Check if the file exists and get its total line count
if [ -f "rollup.config.mjs" ]; then
  wc -l rollup.config.mjs
  echo "---"
  # Show the relevant sections mentioned in the review
  sed -n '40,70p' rollup.config.mjs
  echo "---"
  sed -n '74,120p' rollup.config.mjs
fi

Repository: galacean/engine-toolkit

Length of output: 1997


🏁 Script executed:

# Get more context to see how packages are iterated and if there's any conditional logic
sed -n '1,50p' rollup.config.mjs && echo "..." && sed -n '70,175p' rollup.config.mjs

Repository: galacean/engine-toolkit

Length of output: 4540


Scope shaderCompiler() to the custom-material package.

The global plugins array is reused across all packages (the pkgs.map(makeRollupConfig) call on line 173 iterates over every package directory). The hardcoded shaderCompiler() plugin will execute its precompile step against packages/custom-material/src for every ES/CJS/UMD/miniprogram build of every package (engine, controls, etc.), causing redundant writes to packages/custom-material/libs during unrelated builds. Additionally, line 94 mutates the shared plugins array with .push(replace(...)) on each iteration, compounding state issues. Move the shader compiler to a per-package plugin list and conditionally attach it only when pkg.location is packages/custom-material.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup.config.mjs` around lines 46 - 50, The shaderCompiler plugin is
currently added globally and will run for every package build; instead, remove
the hardcoded shaderCompiler(...) from the shared plugins array and add it only
to the per-package plugin list inside makeRollupConfig when pkg.location ===
"packages/custom-material"; also stop mutating the shared plugins array (the
.push(replace(...)) call) — create a local copy of the base plugins inside
makeRollupConfig (e.g., const localPlugins = [...plugins]) and push/attach
replace(...) and shaderCompiler(...) to localPlugins conditionally, then use
localPlugins for the package-specific Rollup config to avoid cross-package side
effects from shaderCompiler and replace.

Move every TS-inlined ShaderLab template literal across all toolkit
packages into a sibling `.shader` file, then have the host `.ts` import
the file as a string. Plugin now runs transform-only — each package owns
its own `precompile` npm script that drives the
`shader-compiler-precompile` CLI to emit `.gsp` artifacts under
`<pkg>/libs/`. Top-level `pnpm run precompile` fans out via
`pnpm -r --filter='./packages/*' --if-present run precompile`.

Coverage (16 inline shaders → 21 total `.gsp` outputs):
- custom-material: water/{Water,WaterFall,WaterRipple}, bake-pbr/BakePBR,
  plain-color/PlainColor, grid/Grid (overwritten with canonical inline),
  planar-shadow/PlanarShadowOnly (new — extracted from
  PlanarShadowShaderFactory's partial pass source, wrapped in a full
  Shader/SubShader/Pass; factory now loads it via Shader.find and
  combines its single pass with PBR's ShadowCaster).
- geometry-sketch: TBN, Wireframe (also extract two `.glsl` includes
  GeometryTextureDefine and GeometryTextureVert from the now-removed
  GeometryShader.ts string-interpolation helper).
- gizmo: Icon
- skeleton-viewer: SkeletonViewer
- controls: BoxSelection (was inline "box")
- outline: OutlinePostprocess + OutlineReplace
- framebuffer-picker: FramebufferPickerColor
- lines: Line, Dash

Add `./sources` subpath export to custom-material so the editor can
import raw `.shader` strings via
`@galacean/engine-toolkit-custom-material/sources` (mirrors
engine-shader's pattern). Other packages don't need this — only
custom-material exposes shaders to editor authors.

Each affected package gains:
- `precompile` script in package.json
- `src/global.d.ts` declaring `*.shader` module type
- `libs/` precompiled `.gsp` outputs + auto-generated index.ts

Drop `rollup-plugin-glslify` and `rollup-plugin-string` from devDeps
(replaced by `@galacean/engine-shader-compiler/bundler`'s transform).
Auto-generated `<pkg>/libs/index.ts` re-exports `.gsp` JSON imports
that the toolkit packages don't currently declare a TypeScript
module shape for, so the IDE shows red squiggles on every import
line. And `tsconfig.json`'s `include: ["src/**/*"]` excludes
`libs/`, so even a `declare module "*.gsp"` in `src/global.d.ts`
isn't picked up by the language server when editing the libs file
directly.

Two fixes per affected package:
- Append `declare module "*.gsp" { const value: object; export
  default value; }` to `src/global.d.ts` (alongside the existing
  `*.shader` declaration).
- Extend `tsconfig.json`'s `include` to `["src/**/*", "libs/**/*"]`
  so the module-type declarations in `src/global.d.ts` apply when
  the language server type-checks `libs/index.ts`.

Eight packages updated: custom-material, geometry-sketch, gizmo,
skeleton-viewer, controls, outline, framebuffer-picker, lines.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (3)
packages/outline/libs/OutlineReplace.gsp (1)

1-1: ⚠️ Potential issue | 🔴 Critical

Varyings is used without a declaration (shader compile blocker).

On Line 1, the vertex shader body uses Varyings v and return v, but there is no struct Varyings declaration in this asset. This can fail shader compilation for outline-replace-shader. Since this is generated output, fix the source OutlineReplace.shader and regenerate .gsp.

🔍 Verification script (read-only)
#!/bin/bash
set -euo pipefail

python - <<'PY'
from pathlib import Path

gsp_path = Path("packages/outline/libs/OutlineReplace.gsp")
text = gsp_path.read_text()

uses_varyings = "Varyings v" in text or "return v" in text
declares_varyings = "struct Varyings" in text

print(f"{gsp_path}:")
print(f"  uses Varyings: {uses_varyings}")
print(f"  declares struct Varyings: {declares_varyings}")

if uses_varyings and not declares_varyings:
    print("  RESULT: FAIL (type used but not declared)")
else:
    print("  RESULT: OK")
PY

fd -i 'OutlineReplace.shader' | while read -r f; do
  echo
  echo "Inspecting source shader: $f"
  rg -n -C2 'struct Varyings|Varyings vert|Varyings v|return v|void main\(' "$f"
done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/outline/libs/OutlineReplace.gsp` at line 1, The vertex shader uses
an undeclared type Varyings (it does "Varyings v" and "return v") causing
compilation to fail; update the source OutlineReplace.shader to declare the
struct Varyings (or replace usages with the correct existing varying type),
regenerate the .gsp so the generated OutlineReplace.gsp contains a matching
"struct Varyings { ... }" declaration that includes all necessary varyings used
in main(), and ensure the vertex shader's return/usage matches that struct
(check functions calculateBlendShape, getSkinMatrix and main for referenced
varyings).
packages/custom-material/libs/water/Water.gsp (1)

1-1: ⚠️ Potential issue | 🟠 Major

Initialize the varyings before the conditional branches.

The compiled vertex stage still leaves v_color, waterTexCoords, and normalTexCoords undefined when RENDERER_HAS_UV / RENDERER_ENABLE_VERTEXCOLOR are absent, so the fragment shader can consume garbage. This is the same issue previously called out in the source shader.

Suggested fix
 Varyings vert(Attributes attr) {
   Varyings v;
+  v.v_color = vec4(1.0);
+  v.waterTexCoords = vec2(0.0);
+  v.normalTexCoords = vec2(0.0);
   gl_Position = renderer_MVPMat * vec4(attr.POSITION, 1.0);
   ...
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/water/Water.gsp` at line 1, The vertex shader
leaves varyings v_color, waterTexCoords, and normalTexCoords uninitialized when
the conditionals RENDERER_HAS_UV and RENDERER_ENABLE_VERTEXCOLOR are false;
initialize these varyings to safe default values at the top of main() (e.g.,
v_color = vec4(1.0); waterTexCoords = vec2(0.0); normalTexCoords = vec2(0.0))
before any conditional blocks so the fragment shader always receives defined
values; update the main() implementation in the vertex shader (the function main
and its handling of RENDERER_HAS_UV / RENDERER_ENABLE_VERTEXCOLOR) to set these
defaults.
packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts (1)

25-26: ⚠️ Potential issue | 🔴 Critical

Lazy-init planarShadowShader instead of dereferencing PBR at module load.

This still evaluates Shader.find("PBR").subShaders[0].passes[2] during module import. If this file loads before the built-in PBR shader is registered, the module throws and replaceShader() never gets a chance to recover.

Suggested fix
+function getPlanarShadowShader() {
+  const cached = Shader.find("planarShadowShader");
+  if (cached) return cached;
+
+  const pbr = Shader.find("PBR");
+  if (!pbr) {
+    throw new Error('Cannot create "planarShadowShader" before "PBR" is registered.');
+  }
+
+  Shader.find("PlanarShadowOnly") || Shader.create(planarShadowOnlySource);
+  const planarShadowOnly = Shader.find("PlanarShadowOnly");
+  if (!planarShadowOnly) {
+    throw new Error('Cannot create "planarShadowShader": "PlanarShadowOnly" registration failed.');
+  }
+
+  Shader.create("planarShadowShader", [pbr.subShaders[0].passes[2], planarShadowOnly.subShaders[0].passes[0]]);
+  return Shader.find("planarShadowShader");
+}
+
 export class PlanarShadowShaderFactory {
@@
   static replaceShader(material: Material) {
-    material.shader = Shader.find("planarShadowShader");
+    material.shader = getPlanarShadowShader();
@@
-}
-
-if (!Shader.find("planarShadowShader")) {
-  // The .shader file precompiles to a standalone Shader; we steal its single
-  // pass and combine it with PBR's shadow caster pass for the actual material
-  // shader.
-  Shader.create(planarShadowOnlySource);
-  const planarShadowPass = Shader.find("PlanarShadowOnly").subShaders[0].passes[0];
-  Shader.create("planarShadowShader", [Shader.find("PBR").subShaders[0].passes[2], planarShadowPass]);
 }

Also applies to: 96-103

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`
around lines 25 - 26, The module currently dereferences the built-in PBR shader
at module load which can throw if PBR isn't registered; change to lazy-init and
cache the custom shader inside PlanarShadowShaderFactory only when needed: move
any direct calls like Shader.find("PBR").subShaders[0].passes[2] out of
top-level scope and into ReplaceShader and the other affected methods (e.g., the
code around lines 96-103), lookup Shader.find("planarShadowShader") or
Shader.find("PBR") at runtime, guard against null returns, construct the
replacement shader when first requested, store it on a static property (e.g.,
PlanarShadowShaderFactory._planarShadowShader) and reuse that cached value for
subsequent calls so module import no longer triggers PBR dereference.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/custom-material/libs/bake-pbr/BakePBR.gsp`:
- Line 1: Summary: The generated fragment contains a self-assignment "vec3
shadowCoord = shadowCoord;" for the single-cascade path, which shadows the
varying and yields undefined data. Fix: change the generator output so when
SCENE_SHADOW_CASCADED_COUNT == 1 the fragment uses the varying explicitly (e.g.
reference varyings.shadowCoord) instead of emitting a local self-assignment;
update the codegen rule that serializes the conditional block to preserve the
"varyings." prefix rather than stripping/minifying it. Locate references to
SCENE_SHADOW_CASCADED_COUNT, the varying shadowCoord (declared in
VARYINGS_PBR_INCLUDED and set in the vertex: shadowCoord = getShadowCoord(...))
and the fragment usage before sampleShadowMap, and ensure the generator emits
"vec3 shadowCoord = varyings.shadowCoord;" (or simply uses varyings.shadowCoord
directly) in that conditional branch.

In `@packages/custom-material/libs/water/WaterFall.gsp`:
- Line 1: The vertex shader conditionally assigns varying variables used by the
fragment shader (waterTexCoords, waterfallTexCoords, normalTexCoords, v_color),
which can lead to undefined reads; initialize these varyings to safe defaults at
the top of the vertex shader (e.g., zero vec2/vec4) before any feature-gated
assignments in the function (main) so they are always written, update the source
shader WaterFall.shader accordingly, and then re-run the shader precompile to
regenerate the .gsp.

In `@packages/custom-material/libs/water/WaterRipple.gsp`:
- Line 1: The fragment shader reads varyings waterTexCoords, normalTexCoords and
v_color but the vertex shader only assigns them conditionally; fix by adding
default assignments in the vertex shader's main (e.g., set waterTexCoords =
vec2(0.0); normalTexCoords = vec2(0.0); v_color = vec4(1.0);) before the
feature-gated blocks that overwrite them so they are always defined, update the
source shader (WaterRipple.shader) accordingly and then re-run the shader
precompile to regenerate the .gsp.

In `@packages/custom-material/package.json`:
- Around line 23-34: The package exports use the non-standard "module"
condition; update the "exports" entries so ESM consumers get the ES build by
renaming "module" to the standard "import" condition for both the "." and
"./sources" keys, and add an explicit "require" condition that mirrors the
existing "default" CommonJS path so CommonJS consumers still resolve correctly;
keep the "types" fields intact.

In `@packages/geometry-sketch/libs/material/TBN.gsp`:
- Line 1: The vertex shader redundantly declares the uniform mat4 camera_VPMat
already provided by TRANSFORM_INCLUDED; remove the explicit "uniform mat4
camera_VPMat;" declaration from the tbnShader source so only the included
TRANSFORM_INCLUDED declaration remains (search for camera_VPMat in the vertex
shader block and delete the standalone uniform line).

In `@packages/skeleton-viewer/libs/SkeletonViewer.gsp`:
- Line 1: The fragment shader always reads varying v_normal but the vertex
shader only assigns it when RENDERER_HAS_NORMAL is defined; update the vertex
shader (in the vertex main function that declares v_normal and uses
renderer_NormalMat/NORMAL) to initialize v_normal to a safe default (e.g.,
vec3(0,1,0)) before the conditional write so v_normal is defined even when
normals are absent, then regenerate the .gsp output so the change is reflected
in the generated SkeletonViewer.gsp.

---

Duplicate comments:
In `@packages/custom-material/libs/water/Water.gsp`:
- Line 1: The vertex shader leaves varyings v_color, waterTexCoords, and
normalTexCoords uninitialized when the conditionals RENDERER_HAS_UV and
RENDERER_ENABLE_VERTEXCOLOR are false; initialize these varyings to safe default
values at the top of main() (e.g., v_color = vec4(1.0); waterTexCoords =
vec2(0.0); normalTexCoords = vec2(0.0)) before any conditional blocks so the
fragment shader always receives defined values; update the main() implementation
in the vertex shader (the function main and its handling of RENDERER_HAS_UV /
RENDERER_ENABLE_VERTEXCOLOR) to set these defaults.

In `@packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts`:
- Around line 25-26: The module currently dereferences the built-in PBR shader
at module load which can throw if PBR isn't registered; change to lazy-init and
cache the custom shader inside PlanarShadowShaderFactory only when needed: move
any direct calls like Shader.find("PBR").subShaders[0].passes[2] out of
top-level scope and into ReplaceShader and the other affected methods (e.g., the
code around lines 96-103), lookup Shader.find("planarShadowShader") or
Shader.find("PBR") at runtime, guard against null returns, construct the
replacement shader when first requested, store it on a static property (e.g.,
PlanarShadowShaderFactory._planarShadowShader) and reuse that cached value for
subsequent calls so module import no longer triggers PBR dereference.

In `@packages/outline/libs/OutlineReplace.gsp`:
- Line 1: The vertex shader uses an undeclared type Varyings (it does "Varyings
v" and "return v") causing compilation to fail; update the source
OutlineReplace.shader to declare the struct Varyings (or replace usages with the
correct existing varying type), regenerate the .gsp so the generated
OutlineReplace.gsp contains a matching "struct Varyings { ... }" declaration
that includes all necessary varyings used in main(), and ensure the vertex
shader's return/usage matches that struct (check functions calculateBlendShape,
getSkinMatrix and main for referenced varyings).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 86ed78ea-c42b-4a10-adec-6a1a8ac8eeb3

📥 Commits

Reviewing files that changed from the base of the PR and between 842e555 and 2aecdce.

⛔ Files ignored due to path filters (19)
  • packages/controls/src/box-selection/BoxSelection.shader is excluded by !**/*.shader
  • packages/custom-material/src/bake-pbr/BakePBR.shader is excluded by !**/*.shader
  • packages/custom-material/src/grid/Grid.shader is excluded by !**/*.shader
  • packages/custom-material/src/plain-color/PlainColor.shader is excluded by !**/*.shader
  • packages/custom-material/src/planar-shadow/PlanarShadowOnly.shader is excluded by !**/*.shader
  • packages/custom-material/src/water/Water.shader is excluded by !**/*.shader
  • packages/custom-material/src/water/WaterFall.shader is excluded by !**/*.shader
  • packages/custom-material/src/water/WaterRipple.shader is excluded by !**/*.shader
  • packages/framebuffer-picker/src/FramebufferPickerColor.shader is excluded by !**/*.shader
  • packages/geometry-sketch/src/material/GeometryTextureDefine.glsl is excluded by !**/*.glsl
  • packages/geometry-sketch/src/material/GeometryTextureVert.glsl is excluded by !**/*.glsl
  • packages/geometry-sketch/src/material/TBN.shader is excluded by !**/*.shader
  • packages/geometry-sketch/src/material/Wireframe.shader is excluded by !**/*.shader
  • packages/gizmo/src/icon/Icon.shader is excluded by !**/*.shader
  • packages/lines/src/line/material/Dash.shader is excluded by !**/*.shader
  • packages/lines/src/line/material/Line.shader is excluded by !**/*.shader
  • packages/outline/src/OutlinePostprocess.shader is excluded by !**/*.shader
  • packages/outline/src/OutlineReplace.shader is excluded by !**/*.shader
  • packages/skeleton-viewer/src/SkeletonViewer.shader is excluded by !**/*.shader
📒 Files selected for processing (69)
  • package.json
  • packages/controls/libs/box-selection/BoxSelection.gsp
  • packages/controls/libs/index.ts
  • packages/controls/package.json
  • packages/controls/src/box-selection/BoxSelectionSSMaterial.ts
  • packages/controls/src/global.d.ts
  • packages/controls/tsconfig.json
  • packages/custom-material/libs/bake-pbr/BakePBR.gsp
  • packages/custom-material/libs/grid/Grid.gsp
  • packages/custom-material/libs/index.ts
  • packages/custom-material/libs/plain-color/PlainColor.gsp
  • packages/custom-material/libs/planar-shadow/PlanarShadowOnly.gsp
  • packages/custom-material/libs/water/Water.gsp
  • packages/custom-material/libs/water/WaterFall.gsp
  • packages/custom-material/libs/water/WaterRipple.gsp
  • packages/custom-material/package.json
  • packages/custom-material/src/bake-pbr/BakePBRMaterial.ts
  • packages/custom-material/src/global.d.ts
  • packages/custom-material/src/grid/GridMaterial.ts
  • packages/custom-material/src/plain-color/PlainColorMaterial.ts
  • packages/custom-material/src/planar-shadow/PlanarShadowShaderFactory.ts
  • packages/custom-material/src/sources.ts
  • packages/custom-material/src/water/WaterMaterial.ts
  • packages/custom-material/src/water/WaterRippleMaterial.ts
  • packages/custom-material/src/water/WaterfallMaterial.ts
  • packages/custom-material/tsconfig.json
  • packages/framebuffer-picker/libs/FramebufferPickerColor.gsp
  • packages/framebuffer-picker/libs/index.ts
  • packages/framebuffer-picker/package.json
  • packages/framebuffer-picker/src/FramebufferPicker.ts
  • packages/framebuffer-picker/src/global.d.ts
  • packages/framebuffer-picker/tsconfig.json
  • packages/geometry-sketch/libs/index.ts
  • packages/geometry-sketch/libs/material/TBN.gsp
  • packages/geometry-sketch/libs/material/Wireframe.gsp
  • packages/geometry-sketch/package.json
  • packages/geometry-sketch/src/global.d.ts
  • packages/geometry-sketch/src/material/GeometryShader.ts
  • packages/geometry-sketch/src/material/TBNMaterial.ts
  • packages/geometry-sketch/src/material/WireframeMaterial.ts
  • packages/geometry-sketch/tsconfig.json
  • packages/gizmo/libs/icon/Icon.gsp
  • packages/gizmo/libs/index.ts
  • packages/gizmo/package.json
  • packages/gizmo/src/global.d.ts
  • packages/gizmo/src/icon/IconMaterial.ts
  • packages/gizmo/tsconfig.json
  • packages/lines/libs/index.ts
  • packages/lines/libs/line/material/Dash.gsp
  • packages/lines/libs/line/material/Line.gsp
  • packages/lines/package.json
  • packages/lines/src/global.d.ts
  • packages/lines/src/line/material/dashShader.ts
  • packages/lines/src/line/material/lineShader.ts
  • packages/lines/tsconfig.json
  • packages/outline/libs/OutlinePostprocess.gsp
  • packages/outline/libs/OutlineReplace.gsp
  • packages/outline/libs/index.ts
  • packages/outline/package.json
  • packages/outline/src/OutlineManager.ts
  • packages/outline/src/global.d.ts
  • packages/outline/tsconfig.json
  • packages/skeleton-viewer/libs/SkeletonViewer.gsp
  • packages/skeleton-viewer/libs/index.ts
  • packages/skeleton-viewer/package.json
  • packages/skeleton-viewer/src/SkeletonViewer.ts
  • packages/skeleton-viewer/src/global.d.ts
  • packages/skeleton-viewer/tsconfig.json
  • rollup.config.mjs
💤 Files with no reviewable changes (1)
  • packages/geometry-sketch/src/material/GeometryShader.ts
✅ Files skipped from review due to trivial changes (29)
  • packages/geometry-sketch/package.json
  • packages/outline/package.json
  • packages/gizmo/package.json
  • packages/gizmo/tsconfig.json
  • packages/framebuffer-picker/package.json
  • packages/lines/package.json
  • packages/geometry-sketch/tsconfig.json
  • packages/controls/libs/index.ts
  • packages/outline/tsconfig.json
  • packages/gizmo/libs/index.ts
  • packages/skeleton-viewer/tsconfig.json
  • packages/framebuffer-picker/libs/index.ts
  • packages/custom-material/src/global.d.ts
  • packages/lines/tsconfig.json
  • packages/lines/libs/index.ts
  • packages/controls/tsconfig.json
  • packages/framebuffer-picker/tsconfig.json
  • packages/skeleton-viewer/libs/index.ts
  • packages/geometry-sketch/libs/index.ts
  • packages/skeleton-viewer/src/global.d.ts
  • packages/controls/src/global.d.ts
  • packages/lines/src/global.d.ts
  • packages/custom-material/tsconfig.json
  • packages/geometry-sketch/src/global.d.ts
  • packages/custom-material/src/bake-pbr/BakePBRMaterial.ts
  • packages/outline/libs/index.ts
  • packages/gizmo/src/global.d.ts
  • packages/lines/libs/line/material/Line.gsp
  • packages/gizmo/libs/icon/Icon.gsp
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/lines/src/line/material/dashShader.ts
  • packages/custom-material/libs/index.ts
  • packages/skeleton-viewer/src/SkeletonViewer.ts
  • packages/outline/src/global.d.ts
  • packages/custom-material/src/plain-color/PlainColorMaterial.ts
  • packages/controls/src/box-selection/BoxSelectionSSMaterial.ts
  • packages/custom-material/src/grid/GridMaterial.ts
  • packages/custom-material/src/water/WaterRippleMaterial.ts
  • rollup.config.mjs
  • packages/gizmo/src/icon/IconMaterial.ts

@@ -0,0 +1 @@
{"name":"bake-pbr","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Utility/ShadowMap/Default/ShadowCaster","isUsePass":true,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}}},{"name":"Utility/DepthOnly/Default/DepthOnly","isUsePass":true,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}}},{"name":"Forward Pass","isUsePass":false,"tags":{"pipelineStage":"Forward"},"renderStates":{"constantMap":{},"variableMap":{"0":"blendEnabled","3":"sourceColorBlendFactor","4":"sourceAlphaBlendFactor","5":"destinationColorBlendFactor","6":"destinationAlphaBlendFactor","11":"depthWriteEnabled","25":"rasterStateCullMode","28":"renderQueueType"}},"vertexShaderInstructions":[[0,"\n"],[2,"FORWARD_PASS_PBR_INCLUDED",708],[0,"\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",34],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",28],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,32],[0,"\nmat2 inverseMat ( mat2 m ) { return mat2 ( m[1][1] , - m[0][1] , - m[1][0] , m[0][0] ) / ( m[0][0] * m[1][1] - m[0][1] * m[1][0] ) ; }\nmat3 inverseMat ( mat3 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] ;\nfloat a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] ;\nfloat a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] ;\nfloat b01 = a22 * a11 - a12 * a21 ;\nfloat b11 = - a22 * a10 + a12 * a20 ;\nfloat b21 = a21 * a10 - a11 * a20 ;\nfloat det = a00 * b01 + a01 * b11 + a02 * b21 ;\nreturn mat3 ( b01 , ( - a22 * a01 + a02 * a21 ) , ( a12 * a01 - a02 * a11 ) , b11 , ( a22 * a00 - a02 * a20 ) , ( - a12 * a00 + a02 * a10 ) , b21 , ( - a21 * a00 + a01 * a20 ) , ( a11 * a00 - a01 * a10 ) ) / det ; }\nmat4 inverseMat ( mat4 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] , a03 = m[0][3] , a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] , a13 = m[1][3] , a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] , a23 = m[2][3] , a30 = m[3][0] , a31 = m[3][1] , a32 = m[3][2] , a33 = m[3][3] , b00 = a00 * a11 - a01 * a10 , b01 = a00 * a12 - a02 * a10 , b02 = a00 * a13 - a03 * a10 , b03 = a01 * a12 - a02 * a11 , b04 = a01 * a13 - a03 * a11 , b05 = a02 * a13 - a03 * a12 , b06 = a20 * a31 - a21 * a30 , b07 = a20 * a32 - a22 * a30 , b08 = a20 * a33 - a23 * a30 , b09 = a21 * a32 - a22 * a31 , b10 = a21 * a33 - a23 * a31 , b11 = a22 * a33 - a23 * a32 , det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06 ;\nreturn mat4 ( a11 * b11 - a12 * b10 + a13 * b09 , a02 * b10 - a01 * b11 - a03 * b09 , a31 * b05 - a32 * b04 + a33 * b03 , a22 * b04 - a21 * b05 - a23 * b03 , a12 * b08 - a10 * b11 - a13 * b07 , a00 * b11 - a02 * b08 + a03 * b07 , a32 * b02 - a30 * b05 - a33 * b01 , a20 * b05 - a22 * b02 + a23 * b01 , a10 * b10 - a11 * b08 + a13 * b06 , a01 * b08 - a00 * b10 - a03 * b06 , a30 * b04 - a31 * b02 + a33 * b00 , a21 * b02 - a20 * b04 - a23 * b00 , a11 * b07 - a10 * b09 - a12 * b06 , a00 * b09 - a01 * b07 + a02 * b06 , a31 * b01 - a30 * b03 - a32 * b00 , a20 * b03 - a21 * b01 + a22 * b00 ) / det ; }\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",44],[0,"\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,42],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",50],[0,"\n"],[7,"TRANSFORM_INCLUDED"],[0,"\nuniform mat4 renderer_ModelMat;\nuniform mat4 renderer_MVMat;\nuniform mat4 renderer_MVPMat;\nuniform mat4 renderer_NormalMat;\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",108],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",82],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",80],[0,"attribute vec3 POSITION_BS0;\nattribute vec3 POSITION_BS1;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},62],[0,"attribute vec3 NORMAL_BS0;\nattribute vec3 NORMAL_BS1;\nattribute vec3 TANGENT_BS0;\nattribute vec3 TANGENT_BS1;\n\n"],[5,78],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},74],[0,"attribute vec3 POSITION_BS2;\nattribute vec3 POSITION_BS3;\n\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",68],[0,"attribute vec3 NORMAL_BS0;\nattribute vec3 NORMAL_BS1;\nattribute vec3 NORMAL_BS2;\nattribute vec3 NORMAL_BS3;\n\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",72],[0,"attribute vec3 TANGENT_BS0;\nattribute vec3 TANGENT_BS1;\nattribute vec3 TANGENT_BS2;\nattribute vec3 TANGENT_BS3;\n\n"],[6],[0,"\n"],[5,76],[0,"attribute vec3 POSITION_BS2;\nattribute vec3 POSITION_BS3;\nattribute vec3 POSITION_BS4;\nattribute vec3 POSITION_BS5;\nattribute vec3 POSITION_BS6;\nattribute vec3 POSITION_BS7;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",86],[0,"attribute vec2 TEXCOORD_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",90],[0,"attribute vec2 TEXCOORD_1;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",94],[0,"attribute vec4 JOINTS_0;\nattribute vec4 WEIGHTS_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",98],[0,"attribute vec4 COLOR_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",102],[0,"attribute vec3 NORMAL;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",106],[0,"attribute vec4 TANGENT;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",130],[0,"\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",128],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",118],[0,"\nuniform sampler2D renderer_JointSampler;\nuniform float renderer_JointCount;\nmat4 getJointMatrix ( sampler2D smp, float index ) { float base = index / renderer_JointCount ;\nfloat hf = 0.5 / renderer_JointCount ;\nfloat v = base + hf ;\nvec4 m0 = texture2D ( smp , vec2 ( 0.125 , v ) ) ;\nvec4 m1 = texture2D ( smp , vec2 ( 0.375 , v ) ) ;\nvec4 m2 = texture2D ( smp , vec2 ( 0.625 , v ) ) ;\nvec4 m3 = texture2D ( smp , vec2 ( 0.875 , v ) ) ;\nreturn mat4 ( m0 , m1 , m2 , m3 ) ; }\n\n"],[5,120],[0,"\nuniform mat4 renderer_JointMatrix [ RENDERER_JOINTS_NUM ];\n\n"],[6],[0,"\nmat4 getSkinMatrix ( ) { \n"],[1,"RENDERER_USE_JOINT_TEXTURE",124],[0," mat4 skinMatrix = WEIGHTS_0.x * getJointMatrix(renderer_JointSampler, JOINTS_0.x) + WEIGHTS_0.y * getJointMatrix(renderer_JointSampler, JOINTS_0.y) + WEIGHTS_0.z * getJointMatrix(renderer_JointSampler, JOINTS_0.z) + WEIGHTS_0.w * getJointMatrix(renderer_JointSampler, JOINTS_0.w) ; \n"],[5,126],[0," mat4 skinMatrix = WEIGHTS_0.x * renderer_JointMatrix[int ( JOINTS_0.x )] + WEIGHTS_0.y * renderer_JointMatrix[int ( JOINTS_0.y )] + WEIGHTS_0.z * renderer_JointMatrix[int ( JOINTS_0.z )] + WEIGHTS_0.w * renderer_JointMatrix[int ( JOINTS_0.w )] ; \n"],[6],[0,"\nreturn skinMatrix ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"BLENDSHAPE_INCLUDED",208],[0,"\n"],[7,"BLENDSHAPE_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",206],[0,"\n\n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",140],[0,"\nuniform mediump sampler2DArray renderer_BlendShapeTexture;\nuniform ivec3 renderer_BlendShapeTextureInfo;\nuniform float renderer_BlendShapeWeights [ RENDERER_BLENDSHAPE_COUNT ];\nvec3 getBlendShapeVertexElement ( int blendShapeIndex, int vertexElementIndex ) { int y = vertexElementIndex / renderer_BlendShapeTextureInfo.y ;\nint x = vertexElementIndex - y * renderer_BlendShapeTextureInfo.y ;\nivec3 uv = ivec3 ( x , y , blendShapeIndex ) ;\nreturn ( texelFetch ( renderer_BlendShapeTexture , uv , 0 ) ).xyz ; }\n\n"],[5,154],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},144],[0,"\nuniform float renderer_BlendShapeWeights [ 2 ];\n\n"],[5,152],[0,"\n\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},148],[0,"\nuniform float renderer_BlendShapeWeights [ 4 ];\n\n"],[5,150],[0,"\nuniform float renderer_BlendShapeWeights [ 8 ];\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid calculateBlendShape ( inout vec4 position\n"],[1,"RENDERER_HAS_NORMAL",162],[0," , inout vec3 normal \n"],[1,"RENDERER_HAS_TANGENT",160],[0," , inout vec4 tangent \n"],[6],[0," \n"],[6],[0," ) { \n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",174],[0," int vertexOffset = gl_VertexID * renderer_BlendShapeTextureInfo.x ;\nfor ( int i = 0 ; i < RENDERER_BLENDSHAPE_COUNT ; i ++ ) { int vertexElementOffset = vertexOffset ;\nfloat weight = renderer_BlendShapeWeights[i] ;\nif ( weight != 0.0 ) { position.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"}},168],[0," vertexElementOffset += 1 ;\nnormal += getBlendShapeVertexElement(i, vertexElementOffset) * weight ; \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},172],[0," vertexElementOffset += 1 ;\ntangent.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight ; \n"],[6],[0," } } \n"],[5,204],[0," position.xyz += POSITION_BS0 * renderer_BlendShapeWeights[0] ;\nposition.xyz += POSITION_BS1 * renderer_BlendShapeWeights[1] ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},186],[0," \n"],[1,"RENDERER_HAS_NORMAL",180],[0," normal += NORMAL_BS0 * renderer_BlendShapeWeights[0] ;\nnormal += NORMAL_BS1 * renderer_BlendShapeWeights[1] ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_TANGENT",184],[0," tangent.xyz += TANGENT_BS0 * renderer_BlendShapeWeights[0] ;\ntangent.xyz += TANGENT_BS1 * renderer_BlendShapeWeights[1] ; \n"],[6],[0," \n"],[5,202],[0," \n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},198],[0," position.xyz += POSITION_BS2 * renderer_BlendShapeWeights[2] ;\nposition.xyz += POSITION_BS3 * renderer_BlendShapeWeights[3] ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_NORMAL"}},192],[0," normal += NORMAL_BS0 * renderer_BlendShapeWeights[0] ;\nnormal += NORMAL_BS1 * renderer_BlendShapeWeights[1] ;\nnormal += NORMAL_BS2 * renderer_BlendShapeWeights[2] ;\nnormal += NORMAL_BS3 * renderer_BlendShapeWeights[3] ; \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},196],[0," tangent.xyz += TANGENT_BS0 * renderer_BlendShapeWeights[0] ;\ntangent.xyz += TANGENT_BS1 * renderer_BlendShapeWeights[1] ;\ntangent.xyz += TANGENT_BS2 * renderer_BlendShapeWeights[2] ;\ntangent.xyz += TANGENT_BS3 * renderer_BlendShapeWeights[3] ; \n"],[6],[0," \n"],[5,200],[0," position.xyz += POSITION_BS2 * renderer_BlendShapeWeights[2] ;\nposition.xyz += POSITION_BS3 * renderer_BlendShapeWeights[3] ;\nposition.xyz += POSITION_BS4 * renderer_BlendShapeWeights[4] ;\nposition.xyz += POSITION_BS5 * renderer_BlendShapeWeights[5] ;\nposition.xyz += POSITION_BS6 * renderer_BlendShapeWeights[6] ;\nposition.xyz += POSITION_BS7 * renderer_BlendShapeWeights[7] ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"SHADOW_INCLUDED",288],[0,"\n"],[7,"SHADOW_INCLUDED"],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_SHADOW_TYPE"},"r":{"t":"def","m":"RENDERER_IS_RECEIVE_SHADOWS"}},218],[0,"\n"],[7,"NEED_CALCULATE_SHADOWS"],[0,"\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",246],[0,"\nuniform mat4 scene_ShadowMatrices [ SCENE_SHADOW_CASCADED_COUNT + 1 ];\nuniform vec4 scene_ShadowSplitSpheres [ 4 ];\nmediump int computeCascadeIndex ( vec3 positionWS ) { vec3 fromCenter0 = positionWS - scene_ShadowSplitSpheres[0].xyz ;\nvec3 fromCenter1 = positionWS - scene_ShadowSplitSpheres[1].xyz ;\nvec3 fromCenter2 = positionWS - scene_ShadowSplitSpheres[2].xyz ;\nvec3 fromCenter3 = positionWS - scene_ShadowSplitSpheres[3].xyz ;\nmediump vec4 comparison = vec4 ( ( dot ( fromCenter0 , fromCenter0 ) < scene_ShadowSplitSpheres[0].w ) , ( dot ( fromCenter1 , fromCenter1 ) < scene_ShadowSplitSpheres[1].w ) , ( dot ( fromCenter2 , fromCenter2 ) < scene_ShadowSplitSpheres[2].w ) , ( dot ( fromCenter3 , fromCenter3 ) < scene_ShadowSplitSpheres[3].w ) ) ;\ncomparison.yzw = clamp ( comparison.yzw - comparison.xyz , 0.0 , 1.0 ) ;\nmediump vec4 indexCoefficient = vec4 ( 4.0 , 3.0 , 2.0 , 1.0 ) ;\nmediump int index = 4 - int ( dot ( comparison , indexCoefficient ) ) ;\nreturn index ; }\nvec3 getShadowCoord ( vec3 positionWS ) { \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,224],[0," mediump int cascadeIndex = 0 ; \n"],[5,226],[0," mediump int cascadeIndex = computeCascadeIndex(positionWS) ; \n"],[6],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",230],[0," mat4 shadowMatrix = scene_ShadowMatrices[cascadeIndex] ; \n"],[5,244],[0," mat4 shadowMatrix ;\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",4,234],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else if ( cascadeIndex == 2 ) { shadowMatrix = scene_ShadowMatrices[2] ; } else if ( cascadeIndex == 3 ) { shadowMatrix = scene_ShadowMatrices[3] ; } else { shadowMatrix = scene_ShadowMatrices[4] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",2,238],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else { shadowMatrix = scene_ShadowMatrices[2] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,242],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else { shadowMatrix = scene_ShadowMatrices[1] ; } \n"],[6],[0," \n"],[6],[0,"\nvec4 shadowCoord = shadowMatrix * vec4 ( positionWS , 1.0 ) ;\nreturn shadowCoord.xyz ; }\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",286],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",256],[0,"\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureLod(textureName, coord3 , 0.0)"],[0,"\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2DShadow shadowMap"],[0,"\n\n"],[5,270],[0,"\n\n"],[1,"ENGINE_NO_DEPTH_TEXTURE",262],[0,"\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[5,266],[0,"\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[6],[0,"\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2D shadowMap"],[0,"\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",2,274],[0,"\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",3,284],[0,"\n\n"],[2,"SHADOW_SAMPLE_TENT_INCLUDED",282],[0,"\n"],[7,"SHADOW_SAMPLE_TENT_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",318],[0,"\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",296],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",300],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,304],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",312],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",310],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},316],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"varying vec4 positionCS;\n\n\n"],[6],[0,"\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",472],[0,"\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",328],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",334],[0,"\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",340],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",346],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",352],[0,"\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",410],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",366],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",364],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},376],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",380],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",384],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",388],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",392],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",396],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",400],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",404],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",408],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",452],[0,"\n"],[7,"LIGHT_INCLUDED"],[0,"\n\n"],[2,"GRAPHICS_API_WEBGL2",418],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",426],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",424],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",434],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",432],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",442],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",440],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SH",446],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",450],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",458],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",462],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",466],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",470],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",508],[0,"\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",482],[0,"\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",488],[0,"\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",494],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",500],[0,"\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",506],[0,"\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",574],[0,"\n"],[7,"VERTEX_INCLUDE"],[0,"\nstruct VertexInputs { vec4 positionOS ; vec3 positionWS ; \n"],[3,"SCENE_FOG_MODE","!=",0,516],[0," vec3 positionVS ; \n"],[6],[0," \n"],[1,"RENDERER_HAS_NORMAL",524],[0," vec3 normalWS ; \n"],[1,"RENDERER_HAS_TANGENT",522],[0," vec3 tangentWS ; vec3 bitangentWS ; \n"],[6],[0," \n"],[6],[0," } ;\nuniform vec4 material_TilingOffset;\nvec2 getUV0 ( ) { vec2 uv0 = vec2 ( 0 ) ;\n\n"],[1,"RENDERER_HAS_UV",528],[0," uv0 = TEXCOORD_0 ; \n"],[6],[0,"\nreturn uv0 * material_TilingOffset.xy + material_TilingOffset.zw ; }\nVertexInputs getVertexInputs ( ) { VertexInputs inputs ;\nvec4 position = vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",536],[0," vec3 normal = vec3 ( NORMAL ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",534],[0," vec4 tangent = vec4 ( TANGENT ) ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",548],[0," calculateBlendShape(position\n"],[1,"RENDERER_HAS_NORMAL",546],[0," , normal \n"],[1,"RENDERER_HAS_TANGENT",544],[0," , tangent \n"],[6],[0," \n"],[6],[0,") ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",560],[0," mat4 skinMatrix = getSkinMatrix() ;\nposition = skinMatrix * position ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},558],[0," mat3 skinNormalMatrix = INVERSE_MAT(mat3 ( skinMatrix )) ;\nnormal = normal * skinNormalMatrix ;\n\n"],[1,"RENDERER_HAS_TANGENT",556],[0," tangent.xyz = tangent.xyz * skinNormalMatrix ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},568],[0," inputs.normalWS = normalize ( mat3 ( renderer_NormalMat ) * normal ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",566],[0," vec3 tangentWS = normalize ( mat3 ( renderer_NormalMat ) * tangent.xyz ) ;\nvec3 bitangentWS = cross ( inputs.normalWS , tangentWS ) * tangent.w ;\ninputs.tangentWS = tangentWS ;\ninputs.bitangentWS = bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\ninputs.positionOS = position ;\nvec4 positionWS = renderer_ModelMat * position ;\ninputs.positionWS = positionWS.xyz / positionWS.w ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,572],[0," vec4 positionVS = renderer_MVMat * position ;\ninputs.positionVS = positionVS.xyz / positionVS.w ; \n"],[6],[0,"\nreturn inputs ; }\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",682],[0,"\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",584],[0,"\n"],[7,"NORMAL_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",588],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",592],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",608],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",598],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",602],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",606],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",616],[0,"\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",614],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",628],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",622],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",626],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",640],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",634],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",638],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",656],[0,"\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",646],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",654],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",652],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",660],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",664],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",668],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",672],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",676],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",680],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid PBRVertex( ) { \nuv = getUV0() ;\n\n"],[1,"RENDERER_HAS_UV1",686],[0," uv1 = TEXCOORD_1 ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",690],[0," vertexColor = COLOR_0 ; \n"],[6],[0,"\nVertexInputs vertexInputs = getVertexInputs() ;\npositionWS = vertexInputs.positionWS ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,694],[0," positionVS = vertexInputs.positionVS ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",702],[0," normalWS = vertexInputs.normalWS ;\n\n"],[1,"RENDERER_HAS_TANGENT",700],[0," tangentWS = vertexInputs.tangentWS ;\nbitangentWS = vertexInputs.bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},706],[0," shadowCoord = getShadowCoord(vertexInputs.positionWS) ; \n"],[6],[0,"\ngl_Position = renderer_MVPMat * vertexInputs.positionOS ;\npositionCS = gl_Position ;\n }\n\n"],[6],[0,"\n\n"],[1,"LIGHTMAP_TEXTURE",712],[0,"\n\n"],[6],[0,"\nvoid main() { PBRVertex(); }"]],"fragmentShaderInstructions":[[0,"\n"],[2,"FORWARD_PASS_PBR_INCLUDED",868],[0,"\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",38],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\nfloat pow2 ( float x ) { return x * x ; }\nfloat sRGBToLinear ( float value ) { float linearRGBLo = value / 12.92 ;\nfloat linearRGBHi = pow ( ( value + 0.055 ) / 1.055 , 2.4 ) ;\nfloat linearRGB = ( value <= 0.04045 ) ? linearRGBLo : linearRGBHi ;\nreturn linearRGB ; }\nvec4 sRGBToLinear ( vec4 value ) { return vec4 ( sRGBToLinear(value.r) , sRGBToLinear(value.g) , sRGBToLinear(value.b) , value.a ) ; }\nvec4 texture2DSRGB ( sampler2D tex, vec2 uv ) { vec4 color = texture2D ( tex , uv ) ;\n\n"],[1,"ENGINE_NO_SRGB",26],[0," color = sRGBToLinear(color) ; \n"],[6],[0,"\nreturn color ; }\nuniform vec4 camera_ProjectionParams;\n\n"],[1,"GRAPHICS_API_WEBGL2",32],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,36],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",58],[0,"\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,56],[0,"\nuniform vec4 scene_FogColor;\nuniform vec4 scene_FogParams;\nvec4 fog ( vec4 color, vec3 positionVS ) { float fogDepth = length ( positionVS ) ;\n\n"],[3,"SCENE_FOG_MODE","==",1,48],[0," float fogIntensity = clamp ( fogDepth * scene_FogParams.x + scene_FogParams.y , 0.0 , 1.0 ) ; \n"],[5,54],[3,"SCENE_FOG_MODE","==",2,51],[0," float fogIntensity = clamp ( exp2 ( - fogDepth * scene_FogParams.z ) , 0.0 , 1.0 ) ; \n"],[5,54],[3,"SCENE_FOG_MODE","==",3,54],[0," float factor = fogDepth * scene_FogParams.w ;\nfloat fogIntensity = clamp ( exp2 ( - factor * factor ) , 0.0 , 1.0 ) ; \n"],[6],[0,"\ncolor.rgb = mix ( scene_FogColor.rgb , color.rgb , fogIntensity ) ;\nreturn color ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",64],[0,"\n"],[7,"TRANSFORM_INCLUDED"],[0,"\nuniform mat4 camera_ViewMat;\nuniform mat4 camera_ProjMat;\nuniform vec3 camera_Position;\nuniform vec3 camera_Forward;\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",70],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",86],[0,"\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",84],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",80],[0,"\n\n"],[5,82],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"BLENDSHAPE_INCLUDED",114],[0,"\n"],[7,"BLENDSHAPE_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",112],[0,"\n\n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",96],[0,"\n\n"],[5,110],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},100],[0,"\n\n"],[5,108],[0,"\n\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},104],[0,"\n\n"],[5,106],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"SHADOW_INCLUDED",206],[0,"\n"],[7,"SHADOW_INCLUDED"],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_SHADOW_TYPE"},"r":{"t":"def","m":"RENDERER_IS_RECEIVE_SHADOWS"}},124],[0,"\n"],[7,"NEED_CALCULATE_SHADOWS"],[0,"\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",152],[0,"\nuniform mat4 scene_ShadowMatrices [ SCENE_SHADOW_CASCADED_COUNT + 1 ];\nuniform vec4 scene_ShadowSplitSpheres [ 4 ];\nmediump int computeCascadeIndex ( vec3 positionWS ) { vec3 fromCenter0 = positionWS - scene_ShadowSplitSpheres[0].xyz ;\nvec3 fromCenter1 = positionWS - scene_ShadowSplitSpheres[1].xyz ;\nvec3 fromCenter2 = positionWS - scene_ShadowSplitSpheres[2].xyz ;\nvec3 fromCenter3 = positionWS - scene_ShadowSplitSpheres[3].xyz ;\nmediump vec4 comparison = vec4 ( ( dot ( fromCenter0 , fromCenter0 ) < scene_ShadowSplitSpheres[0].w ) , ( dot ( fromCenter1 , fromCenter1 ) < scene_ShadowSplitSpheres[1].w ) , ( dot ( fromCenter2 , fromCenter2 ) < scene_ShadowSplitSpheres[2].w ) , ( dot ( fromCenter3 , fromCenter3 ) < scene_ShadowSplitSpheres[3].w ) ) ;\ncomparison.yzw = clamp ( comparison.yzw - comparison.xyz , 0.0 , 1.0 ) ;\nmediump vec4 indexCoefficient = vec4 ( 4.0 , 3.0 , 2.0 , 1.0 ) ;\nmediump int index = 4 - int ( dot ( comparison , indexCoefficient ) ) ;\nreturn index ; }\nvec3 getShadowCoord ( vec3 positionWS ) { \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,130],[0," mediump int cascadeIndex = 0 ; \n"],[5,132],[0," mediump int cascadeIndex = computeCascadeIndex(positionWS) ; \n"],[6],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",136],[0," mat4 shadowMatrix = scene_ShadowMatrices[cascadeIndex] ; \n"],[5,150],[0," mat4 shadowMatrix ;\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",4,140],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else if ( cascadeIndex == 2 ) { shadowMatrix = scene_ShadowMatrices[2] ; } else if ( cascadeIndex == 3 ) { shadowMatrix = scene_ShadowMatrices[3] ; } else { shadowMatrix = scene_ShadowMatrices[4] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",2,144],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else { shadowMatrix = scene_ShadowMatrices[2] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,148],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else { shadowMatrix = scene_ShadowMatrices[1] ; } \n"],[6],[0," \n"],[6],[0,"\nvec4 shadowCoord = shadowMatrix * vec4 ( positionWS , 1.0 ) ;\nreturn shadowCoord.xyz ; }\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",204],[0,"\nuniform vec4 scene_ShadowInfo;\nuniform vec4 scene_ShadowMapSize;\n\n"],[1,"GRAPHICS_API_WEBGL2",162],[0,"\nuniform mediump sampler2DShadow scene_ShadowMap;\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureLod(textureName, coord3 , 0.0)"],[0,"\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2DShadow shadowMap"],[0,"\n\n"],[5,176],[0,"\nuniform sampler2D scene_ShadowMap;\n\n"],[1,"ENGINE_NO_DEPTH_TEXTURE",168],[0,"\nconst vec4 bitShift = vec4 ( 1.0 , 1.0 / 256.0 , 1.0 / ( 256.0 * 256.0 ) , 1.0 / ( 256.0 * 256.0 * 256.0 ) );\nfloat textureShadowMapDowngrade ( sampler2D scene_ShadowMap, vec3 shadowCoord ) { vec4 rgbaDepth = texture2D ( scene_ShadowMap , shadowCoord.xy ) ;\nfloat unpackDepth = dot ( rgbaDepth , bitShift ) ;\nreturn unpackDepth < shadowCoord.z ? 0.0 : 1.0 ; }\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[5,172],[0,"\nfloat textureShadowMapDowngrade ( sampler2D scene_ShadowMap, vec3 shadowCoord ) { float depth = texture2D ( scene_ShadowMap , shadowCoord.xy ).r ;\nreturn depth < shadowCoord.z ? 0.0 : 1.0 ; }\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[6],[0,"\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2D shadowMap"],[0,"\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",2,180],[0,"\nfloat sampleShadowMapFiltered4 ( TEXTURE2D_SHADOW_PARAM(shadowMap), vec3 shadowCoord, vec4 shadowMapSize ) { float attenuation ;\nvec4 attenuation4 ;\nvec2 offset = shadowMapSize.xy / 2.0 ;\nvec3 shadowCoord0 = shadowCoord + vec3 ( - offset , 0.0 ) ;\nvec3 shadowCoord1 = shadowCoord + vec3 ( offset.x , - offset.y , 0.0 ) ;\nvec3 shadowCoord2 = shadowCoord + vec3 ( - offset.x , offset.y , 0.0 ) ;\nvec3 shadowCoord3 = shadowCoord + vec3 ( offset , 0.0 ) ;\nattenuation4.x = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord0) ;\nattenuation4.y = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord1) ;\nattenuation4.z = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord2) ;\nattenuation4.w = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord3) ;\nattenuation = dot ( attenuation4 , vec4 ( 0.25 ) ) ;\nreturn attenuation ; }\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",3,190],[0,"\n\n"],[2,"SHADOW_SAMPLE_TENT_INCLUDED",188],[0,"\n"],[7,"SHADOW_SAMPLE_TENT_INCLUDED"],[0,"\nfloat sampleShadowGetIRTriangleTexelArea ( float triangleHeight ) { return triangleHeight - 0.5 ; }\nvoid sampleShadowGetTexelAreasTent3x3 ( float offset, out vec4 computedArea, out vec4 computedAreaUncut ) { float a = offset + 0.5 ;\nfloat offsetSquaredHalved = a * a * 0.5 ;\ncomputedAreaUncut.x = computedArea.x = offsetSquaredHalved - offset ;\ncomputedAreaUncut.w = computedArea.w = offsetSquaredHalved ;\ncomputedAreaUncut.y = sampleShadowGetIRTriangleTexelArea(1.5 - offset) ;\nfloat clampedOffsetLeft = min ( offset , 0.0 ) ;\nfloat areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft ;\ncomputedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle ;\ncomputedAreaUncut.z = sampleShadowGetIRTriangleTexelArea(1.5 + offset) ;\nfloat clampedOffsetRight = max ( offset , 0.0 ) ;\nfloat areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight ;\ncomputedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle ; }\nvoid sampleShadowGetTexelWeightsTent5x5 ( float offset, out vec3 texelsWeightsA, out vec3 texelsWeightsB ) { vec4 areaFrom3texelTriangle ;\nvec4 areaUncutFrom3texelTriangle ;\nsampleShadowGetTexelAreasTent3x3(offset, areaFrom3texelTriangle, areaUncutFrom3texelTriangle) ;\ntexelsWeightsA.x = 0.16 * ( areaFrom3texelTriangle.x ) ;\ntexelsWeightsA.y = 0.16 * ( areaUncutFrom3texelTriangle.y ) ;\ntexelsWeightsA.z = 0.16 * ( areaFrom3texelTriangle.y + 1.0 ) ;\ntexelsWeightsB.x = 0.16 * ( areaFrom3texelTriangle.z + 1.0 ) ;\ntexelsWeightsB.y = 0.16 * ( areaUncutFrom3texelTriangle.z ) ;\ntexelsWeightsB.z = 0.16 * ( areaFrom3texelTriangle.w ) ; }\nvoid sampleShadowComputeSamplesTent5x5 ( vec4 shadowMapTextureTexelSize, vec2 coord, out float fetchesWeights [ 9 ], out vec2 fetchesUV [ 9 ] ) { vec2 tentCenterInTexelSpace = coord.xy * shadowMapTextureTexelSize.zw ;\nvec2 centerOfFetchesInTexelSpace = floor ( tentCenterInTexelSpace + 0.5 ) ;\nvec2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace ;\nvec3 texelsWeightsUA , texelsWeightsUB ;\nvec3 texelsWeightsVA , texelsWeightsVB ;\nsampleShadowGetTexelWeightsTent5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsUA, texelsWeightsUB) ;\nsampleShadowGetTexelWeightsTent5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsVA, texelsWeightsVB) ;\nvec3 fetchesWeightsU = vec3 ( texelsWeightsUA.xz , texelsWeightsUB.y ) + vec3 ( texelsWeightsUA.y , texelsWeightsUB.xz ) ;\nvec3 fetchesWeightsV = vec3 ( texelsWeightsVA.xz , texelsWeightsVB.y ) + vec3 ( texelsWeightsVA.y , texelsWeightsVB.xz ) ;\nvec3 fetchesOffsetsU = vec3 ( texelsWeightsUA.y , texelsWeightsUB.xz ) / fetchesWeightsU.xyz + vec3 ( - 2.5 , - 0.5 , 1.5 ) ;\nvec3 fetchesOffsetsV = vec3 ( texelsWeightsVA.y , texelsWeightsVB.xz ) / fetchesWeightsV.xyz + vec3 ( - 2.5 , - 0.5 , 1.5 ) ;\nfetchesOffsetsU *= shadowMapTextureTexelSize.xxx ;\nfetchesOffsetsV *= shadowMapTextureTexelSize.yyy ;\nvec2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTextureTexelSize.xy ;\nfetchesUV[0] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.x , fetchesOffsetsV.x ) ;\nfetchesUV[1] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.y , fetchesOffsetsV.x ) ;\nfetchesUV[2] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.z , fetchesOffsetsV.x ) ;\nfetchesUV[3] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.x , fetchesOffsetsV.y ) ;\nfetchesUV[4] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.y , fetchesOffsetsV.y ) ;\nfetchesUV[5] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.z , fetchesOffsetsV.y ) ;\nfetchesUV[6] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.x , fetchesOffsetsV.z ) ;\nfetchesUV[7] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.y , fetchesOffsetsV.z ) ;\nfetchesUV[8] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.z , fetchesOffsetsV.z ) ;\nfetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x ;\nfetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x ;\nfetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x ;\nfetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y ;\nfetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y ;\nfetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y ;\nfetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z ;\nfetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z ;\nfetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z ; }\n\n"],[6],[0,"\nfloat sampleShadowMapFiltered9 ( TEXTURE2D_SHADOW_PARAM(shadowMap), vec3 shadowCoord, vec4 shadowmapSize ) { float attenuation ;\nfloat fetchesWeights [ 9 ] ;\nvec2 fetchesUV [ 9 ] ;\nsampleShadowComputeSamplesTent5x5(shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV) ;\nattenuation = fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[0].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[1].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[2].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[3].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[4].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[5].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[6].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[7].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[8].xy , shadowCoord.z )) ;\nreturn attenuation ; }\n\n"],[6],[0,"\nfloat getShadowFade ( vec3 positionWS ) { vec3 camToPixel = positionWS - camera_Position ;\nfloat distanceCamToPixel2 = dot ( camToPixel , camToPixel ) ;\nreturn saturate(distanceCamToPixel2 * scene_ShadowInfo.z + scene_ShadowInfo.w) ; }\nfloat sampleShadowMap ( vec3 positionWS, vec3 shadowCoord ) { float attenuation = 1.0 ;\nif ( shadowCoord.z > 0.0 && shadowCoord.z < 1.0 ) { \n"],[3,"SCENE_SHADOW_TYPE","==",1,194],[0," attenuation = SAMPLE_TEXTURE2D_SHADOW(scene_ShadowMap, shadowCoord) ; \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",2,198],[0," attenuation = sampleShadowMapFiltered4(scene_ShadowMap, shadowCoord, scene_ShadowMapSize) ; \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",3,202],[0," attenuation = sampleShadowMapFiltered9(scene_ShadowMap, shadowCoord, scene_ShadowMapSize) ; \n"],[6],[0,"\nfloat shadowFade = getShadowFade(positionWS) ;\nattenuation = mix ( 1.0 , mix ( attenuation , 1.0 , shadowFade ) , scene_ShadowInfo.x ) ; }\nreturn attenuation ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",236],[0,"\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",214],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",218],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,222],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",230],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",228],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},234],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"varying vec4 positionCS;\n\n\n"],[6],[0,"\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",533],[0,"\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",246],[0,"\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",252],[0,"\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",258],[0,"\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",264],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",270],[0,"\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",423],[0,"\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",284],[0,"\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",282],[0,"\nstruct RefractionModelResult { float transmissionLength ; vec3 positionExit ; } ;\nvoid refractionModelSphere ( vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModelResult ray ) { vec3 R1 = refract ( V , normalWS , 1.0 / ior ) ;\nfloat dist = dot ( - normalWS , R1 ) * thickness ;\nvec3 P1 = positionWS + R1 * dist ;\nray.transmissionLength = dist ;\nray.positionExit = P1 ; }\nvoid refractionModelPlanar ( vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModelResult ray ) { vec3 R = refract ( V , normalWS , 1.0 / ior ) ;\nfloat dist = thickness / max ( dot ( - normalWS , R ) , 1e-5f ) ;\nray.transmissionLength = dist ;\nray.positionExit = vec3 ( positionWS + R * dist ) ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},294],[0,"\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",298],[0,"\nuniform sampler2D scene_PrefilteredDFG;\n\n"],[6],[0,"\nstruct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; \n"],[1,"NEED_TANGENT",302],[0," vec3 tangent ; vec3 bitangent ; \n"],[6],[0," vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",306],[0," float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",310],[0," float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",314],[0," float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",318],[0," float sheenRoughness ; vec3 sheenColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_TRANSMISSION",322],[0," vec3 absorptionCoefficient ; float transmission ; float thickness ; \n"],[6],[0," } ;\nstruct BSDFData { vec3 diffuseColor ; float roughness ; vec3 envSpecularDFG ; float diffuseAO ; vec3 specularF0 ; vec3 resolvedSpecularF0 ; float specularF90 ; vec3 energyCompensation ; \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",326],[0," vec3 clearCoatSpecularColor ; float clearCoatRoughness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",330],[0," vec3 iridescenceSpecularColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",334],[0," float sheenRoughness ; float sheenScaling ; float approxIBLSheenDG ; \n"],[6],[0," } ;\nfloat getAARoughnessFactor ( vec3 normal ) { \n"],[1,"HAS_DERIVATIVES",338],[0," vec3 dxy = max ( abs ( dFdx ( normal ) ) , abs ( dFdy ( normal ) ) ) ;\nreturn max ( max ( dxy.x , dxy.y ) , dxy.z ) ; \n"],[5,340],[0," return 0.0 ; \n"],[6],[0," }\nfloat F_Schlick ( float f0, float f90, float dotLH ) { return f0 + ( f90 - f0 ) * ( pow ( 1.0 - dotLH , 5.0 ) ) ; }\nvec3 F_Schlick ( vec3 f0, float f90, float dotLH ) { float fresnel = exp2 ( ( - 5.55473 * dotLH - 6.98316 ) * dotLH ) ;\nreturn ( f90 - f0 ) * fresnel + f0 ; }\nfloat G_GGX_SmithCorrelated ( float alpha, float dotNL, float dotNV ) { float a2 = pow2(alpha) ;\nfloat gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNV) ) ;\nfloat gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNL) ) ;\nreturn 0.5 / max ( gv + gl , EPSILON ) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",344],[0,"\nfloat G_GGX_SmithCorrelated_Anisotropic ( float at, float ab, float ToV, float BoV, float ToL, float BoL, float NoV, float NoL ) { float lambdaV = NoL * length ( vec3 ( at * ToV , ab * BoV , NoV ) ) ;\nfloat lambdaL = NoV * length ( vec3 ( at * ToL , ab * BoL , NoL ) ) ;\nreturn 0.5 / max ( lambdaV + lambdaL , EPSILON ) ; }\n\n"],[6],[0,"\nfloat D_GGX ( float alpha, float dotNH ) { float a2 = pow2(alpha) ;\nfloat denom = pow2(dotNH) * ( a2 - 1.0 ) + 1.0 ;\nreturn RECIPROCAL_PI * a2 / pow2(denom) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",348],[0,"\nfloat D_GGX_Anisotropic ( float at, float ab, float ToH, float BoH, float NoH ) { float a2 = at * ab ;\nhighp vec3 d = vec3 ( ab * ToH , at * BoH , a2 * NoH ) ;\nhighp float d2 = dot ( d , d ) ;\nfloat b2 = a2 / d2 ;\nreturn a2 * b2 * b2 * RECIPROCAL_PI ; }\n\n"],[6],[0,"\nfloat DG_GGX ( float alpha, float dotNV, float dotNL, float dotNH ) { float D = D_GGX(alpha, dotNH) ;\nfloat G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV) ;\nreturn G * D ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",352],[0,"\nfloat DG_GGX_anisotropic ( vec3 h, vec3 l, SurfaceData surfaceData, float alpha, float dotNV, float dotNL, float dotNH ) { vec3 t = surfaceData.anisotropicT ;\nvec3 b = surfaceData.anisotropicB ;\nvec3 v = surfaceData.viewDir ;\nfloat dotTV = dot ( t , v ) ;\nfloat dotBV = dot ( b , v ) ;\nfloat dotTL = dot ( t , l ) ;\nfloat dotBL = dot ( b , l ) ;\nfloat dotTH = dot ( t , h ) ;\nfloat dotBH = dot ( b , h ) ;\nfloat at = max ( alpha * ( 1.0 + surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat ab = max ( alpha * ( 1.0 - surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat D = D_GGX_Anisotropic(at, ab, dotTH, dotBH, dotNH) ;\nfloat G = G_GGX_SmithCorrelated_Anisotropic(at, ab, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL) ;\nreturn G * D ; }\n\n"],[6],[0,"\nvec3 BRDF_Specular_GGX ( vec3 incidentDirection, SurfaceData surfaceData, BSDFData bsdfData, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2(roughness) ;\nvec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( normal , incidentDirection )) ;\nfloat dotNV = saturate(dot ( normal , surfaceData.viewDir )) ;\nfloat dotNH = saturate(dot ( normal , halfDir )) ;\nfloat dotLH = saturate(dot ( incidentDirection , halfDir )) ;\nvec3 F = F_Schlick(specularColor, bsdfData.specularF90, dotLH) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",356],[0," F = mix ( F , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",360],[0," float GD = DG_GGX_anisotropic(halfDir, incidentDirection, surfaceData, alpha, dotNV, dotNL, dotNH) ; \n"],[5,362],[0," float GD = DG_GGX(alpha, dotNV, dotNL, dotNH) ; \n"],[6],[0,"\nreturn F * GD ; }\nvec3 BRDF_Diffuse_Lambert ( vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor ; }\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",366],[0,"\nvec3 iorToFresnel0 ( vec3 transmittedIOR, float incidentIOR ) { return pow ( ( transmittedIOR - incidentIOR ) / ( transmittedIOR + incidentIOR ) , vec3 ( 2.0 ) ) ; }\nfloat iorToFresnel0 ( float transmittedIOR, float incidentIOR ) { return pow ( ( transmittedIOR - incidentIOR ) / ( transmittedIOR + incidentIOR ) , 2.0 ) ; }\nvec3 fresnelToIOR ( vec3 f0 ) { vec3 sqrtF0 = sqrt ( f0 ) ;\nreturn ( vec3 ( 1.0 ) + sqrtF0 ) / ( vec3 ( 1.0 ) - sqrtF0 ) ; }\nvec3 evalSensitivity ( float opd, vec3 shift ) { float phase = 2.0 * PI * opd * 1.0e-9 ;\nconst vec3 val = vec3 ( 5.4856e-13 , 4.4201e-13 , 5.2481e-13 ) ;\nconst vec3 pos = vec3 ( 1.6810e+06 , 1.7953e+06 , 2.2084e+06 ) ;\nconst vec3 var = vec3 ( 4.3278e+09 , 9.3046e+09 , 6.6121e+09 ) ;\nvec3 xyz = val * sqrt ( 2.0 * PI * var ) * cos ( pos * phase + shift ) * exp ( - var * pow2(phase) ) ;\nxyz.x += 9.7470e-14 * sqrt ( 2.0 * PI * 4.5282e+09 ) * cos ( 2.2399e+06 * phase + shift[0] ) * exp ( - 4.5282e+09 * pow2(phase) ) ;\nxyz /= 1.0685e-7 ;\nconst mat3 XYZ_TO_RGB = mat3 ( 3.2404542 , - 0.9692660 , 0.0556434 , - 1.5371385 , 1.8760108 , - 0.2040259 , - 0.4985314 , 0.0415560 , 1.0572252 ) ;\nvec3 rgb = XYZ_TO_RGB * xyz ;\nreturn rgb ; }\nvec3 evalIridescenceSpecular ( float outsideIOR, float dotNV, float thinIOR, vec3 baseF0, float baseF90, float iridescenceThickness ) { vec3 iridescence = vec3 ( 1.0 ) ;\nfloat iridescenceIOR = mix ( outsideIOR , thinIOR , smoothstep ( 0.0 , 0.03 , iridescenceThickness ) ) ;\nfloat sinTheta2Sq = pow ( outsideIOR / iridescenceIOR , 2.0 ) * ( 1.0 - pow ( dotNV , 2.0 ) ) ;\nfloat cosTheta2Sq = 1.0 - sinTheta2Sq ;\nif ( cosTheta2Sq < 0.0 ) { return iridescence ; }\nfloat cosTheta2 = sqrt ( cosTheta2Sq ) ;\nfloat f0 = iorToFresnel0(iridescenceIOR, outsideIOR) ;\nfloat reflectance = F_Schlick(f0, baseF90, dotNV) ;\nfloat t121 = 1.0 - reflectance ;\nfloat phi12 = 0.0 ;\nfloat phi21 = PI - phi12 ;\nvec3 baseIOR = fresnelToIOR(clamp ( baseF0 , 0.0 , 0.9999 )) ;\nvec3 r1 = iorToFresnel0(baseIOR, iridescenceIOR) ;\nvec3 r23 = F_Schlick(r1, baseF90, cosTheta2) ;\nvec3 phi23 = vec3 ( 0.0 ) ;\nif ( baseIOR[0] < iridescenceIOR ) { phi23[0] = PI ; }\nif ( baseIOR[1] < iridescenceIOR ) { phi23[1] = PI ; }\nif ( baseIOR[2] < iridescenceIOR ) { phi23[2] = PI ; }\nfloat opd = 2.0 * iridescenceIOR * iridescenceThickness * cosTheta2 ;\nvec3 phi = vec3 ( phi21 ) + phi23 ;\nvec3 r123 = clamp ( reflectance * r23 , 1e-5 , 0.9999 ) ;\nvec3 sr123 = sqrt ( r123 ) ;\nvec3 rs = pow2(t121) * r23 / ( vec3 ( 1.0 ) - r123 ) ;\nvec3 c0 = reflectance + rs ;\niridescence = c0 ;\nvec3 cm = rs - t121 ;\nfor ( int m = 1 ; m <= 2 ; ++ m ) { cm *= sr123 ;\nvec3 sm = 2.0 * evalSensitivity(float ( m ) * opd, float ( m ) * phi) ;\niridescence += cm * sm ; }\nreturn iridescence = max ( iridescence , vec3 ( 0.0 ) ) ; }\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",376],[0,"\nfloat D_Charlie ( float roughness, float dotNH ) { float invAlpha = 1.0 / roughness ;\nfloat cos2h = dotNH * dotNH ;\nfloat sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;\nreturn ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ; }\nfloat V_Neubelt ( float NoV, float NoL ) { return saturate(1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) )) ; }\nvec3 sheenBRDF ( vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness ) { vec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nfloat dotNH = saturate(dot ( surfaceData.normal , halfDir )) ;\nfloat D = D_Charlie(sheenRoughness, dotNH) ;\nfloat V = V_Neubelt(surfaceData.dotNV, dotNL) ;\nvec3 F = sheenColor ;\nreturn D * V * F ; }\nfloat prefilteredSheenDFG ( float dotNV, float sheenRoughness ) { \n"],[1,"HAS_TEX_LOD",372],[0," return texture2DLodEXT ( scene_PrefilteredDFG , vec2 ( dotNV , sheenRoughness ) , 0.0 ).b ; \n"],[5,374],[0," return texture2D ( scene_PrefilteredDFG , vec2 ( dotNV , sheenRoughness ) , 0.0 ).b ; \n"],[6],[0," }\n\n"],[6],[0,"\nvec2 envDFGApprox ( float roughness, float dotNV ) { const vec4 c0 = vec4 ( - 1 , - 0.0275 , - 0.572 , 0.022 ) ;\nconst vec4 c1 = vec4 ( 1 , 0.0425 , 1.04 , - 0.04 ) ;\nvec4 r = roughness * c0 + c1 ;\nfloat a004 = min ( r.x * r.x , exp2 ( - 9.28 * dotNV ) ) * r.x + r.y ;\nreturn vec2 ( - 1.04 , 1.04 ) * a004 + r.zw ; }\nvec3 envBRDFApprox ( vec3 f0, float f90, float roughness, float dotNV ) { vec2 AB = envDFGApprox(roughness, dotNV) ;\nreturn f0 * AB.x + f90 * AB.y ; }\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",391],[0,"\nuniform sampler2D camera_OpaqueTexture;\nvec3 evaluateTransmission ( SurfaceData surfaceData, BSDFData bsdfData ) { RefractionModelResult ray ;\n\n"],[3,"REFRACTION_MODE","==",0,382],[0," refractionModelSphere(- surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, surfaceData.thickness, ray) ; \n"],[5,385],[3,"REFRACTION_MODE","==",1,385],[0," refractionModelPlanar(- surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, surfaceData.thickness, ray) ; \n"],[6],[0,"\nvec3 refractedRayExit = ray.positionExit ;\nvec4 samplingPositionNDC = camera_ProjMat * camera_ViewMat * vec4 ( refractedRayExit , 1.0 ) ;\nvec2 refractionCoords = ( samplingPositionNDC.xy / samplingPositionNDC.w ) * 0.5 + 0.5 ;\nvec3 refractionTransmitted = texture2DSRGB(camera_OpaqueTexture, refractionCoords).rgb ;\nrefractionTransmitted *= bsdfData.diffuseColor ;\nrefractionTransmitted *= ( 1.0 - max ( max ( bsdfData.envSpecularDFG.r , bsdfData.envSpecularDFG.g ) , bsdfData.envSpecularDFG.b ) ) ;\n\n"],[1,"MATERIAL_HAS_THICKNESS",389],[0," vec3 transmittance = min ( vec3 ( 1.0 ) , exp ( - surfaceData.absorptionCoefficient * ray.transmissionLength ) ) ;\nrefractionTransmitted *= transmittance ; \n"],[6],[0,"\nreturn refractionTransmitted ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",401],[0,"\nuniform sampler2D camera_AOTexture;\nfloat evaluateAmbientOcclusion ( vec2 uv ) { \n"],[1,"MATERIAL_IS_TRANSPARENT",397],[0," return 1.0 ; \n"],[5,399],[0," return texture2D ( camera_AOTexture , uv ).r ; \n"],[6],[0," }\n\n"],[6],[0,"\nvoid initBSDFData ( SurfaceData surfaceData, out BSDFData bsdfData ) { vec3 albedoColor = surfaceData.albedoColor ;\nfloat metallic = surfaceData.metallic ;\nfloat roughness = surfaceData.roughness ;\nvec3 dielectricBaseF0 = vec3 ( pow2(( surfaceData.IOR - 1.0 ) / ( surfaceData.IOR + 1.0 )) ) ;\nvec3 dielectricF0 = min ( dielectricBaseF0 * surfaceData.specularColor , vec3 ( 1.0 ) ) * surfaceData.specularIntensity ;\nfloat dielectricF90 = surfaceData.specularIntensity ;\nbsdfData.specularF0 = mix ( dielectricF0 , albedoColor , metallic ) ;\nbsdfData.specularF90 = mix ( dielectricF90 , 1.0 , metallic ) ;\nbsdfData.diffuseColor = albedoColor * ( 1.0 - metallic ) * ( 1.0 - max ( max ( dielectricF0.r , dielectricF0.g ) , dielectricF0.b ) ) ;\nbsdfData.roughness = max ( MIN_PERCEPTUAL_ROUGHNESS , min ( roughness + getAARoughnessFactor(surfaceData.normal) , 1.0 ) ) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",405],[0," float topIOR = 1.0 ;\nbsdfData.iridescenceSpecularColor = evalIridescenceSpecular(topIOR, surfaceData.dotNV, surfaceData.iridescenceIOR, bsdfData.specularF0, bsdfData.specularF90, surfaceData.iridescenceThickness) ; \n"],[6],[0,"\nbsdfData.resolvedSpecularF0 = bsdfData.specularF0 ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",409],[0," bsdfData.resolvedSpecularF0 = mix ( bsdfData.resolvedSpecularF0 , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\nvec2 dfg = envDFGApprox(bsdfData.roughness, surfaceData.dotNV) ;\nbsdfData.envSpecularDFG = bsdfData.resolvedSpecularF0 * dfg.x + bsdfData.specularF90 * dfg.y ;\nbsdfData.energyCompensation = 1.0 + bsdfData.resolvedSpecularF0 * ( 1.0 / max ( dfg.x + dfg.y , EPSILON ) - 1.0 ) ;\nbsdfData.diffuseAO = surfaceData.ambientOcclusion ;\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",413],[0," float ambientAO = evaluateAmbientOcclusion(( surfaceData.positionCS.xy / surfaceData.positionCS.w ) * 0.5 + 0.5) ;\nbsdfData.diffuseAO = min ( bsdfData.diffuseAO , ambientAO ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",417],[0," bsdfData.clearCoatRoughness = max ( MIN_PERCEPTUAL_ROUGHNESS , min ( surfaceData.clearCoatRoughness + getAARoughnessFactor(surfaceData.clearCoatNormal) , 1.0 ) ) ;\nbsdfData.clearCoatSpecularColor = vec3 ( 0.04 ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",421],[0," bsdfData.sheenRoughness = max ( MIN_PERCEPTUAL_ROUGHNESS , min ( surfaceData.sheenRoughness + getAARoughnessFactor(surfaceData.normal) , 1.0 ) ) ;\nbsdfData.approxIBLSheenDG = prefilteredSheenDFG(surfaceData.dotNV, bsdfData.sheenRoughness) ;\nbsdfData.sheenScaling = 1.0 - bsdfData.approxIBLSheenDG * max ( max ( surfaceData.sheenColor.r , surfaceData.sheenColor.g ) , surfaceData.sheenColor.b ) ; \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",471],[0,"\n"],[7,"LIGHT_INCLUDED"],[0,"\nuniform ivec4 renderer_Layer;\n\n"],[2,"GRAPHICS_API_WEBGL2",431],[0,"\nbool isBitSet ( float value, float mask, float bitIndex ) { return mod ( floor ( value / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 && mod ( floor ( mask / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 ; }\n\n"],[6],[0,"\nbool isRendererCulledByLight ( ivec2 rendererLayer, ivec2 lightCullingMask ) { \n"],[1,"GRAPHICS_API_WEBGL2",435],[0," return ! ( ( rendererLayer.x & lightCullingMask.x ) != 0 || ( rendererLayer.y & lightCullingMask.y ) != 0 ) ; \n"],[5,437],[0," for ( int i = 0 ; i < 16 ; i ++ ) { if ( isBitSet(float ( rendererLayer.x ), float ( lightCullingMask.x ), float ( i )) || isBitSet(float ( rendererLayer.y ), float ( lightCullingMask.y ), float ( i )) ) { return false ; } }\nreturn true ; \n"],[6],[0," }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",445],[0,"\nstruct DirectLight { vec3 color ; vec3 direction ; } ;\nuniform ivec2 scene_DirectLightCullingMask [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightColor [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightDirection [ SCENE_DIRECT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",443],[0,"\nDirectLight getDirectLight ( int index ) { DirectLight light ;\nlight.color = scene_DirectLightColor[index] ;\nlight.direction = scene_DirectLightDirection[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",453],[0,"\nstruct PointLight { vec3 color ; vec3 position ; float distance ; } ;\nuniform ivec2 scene_PointLightCullingMask [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightColor [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightPosition [ SCENE_POINT_LIGHT_COUNT ];\nuniform float scene_PointLightDistance [ SCENE_POINT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",451],[0,"\nPointLight getPointLight ( int index ) { PointLight light ;\nlight.color = scene_PointLightColor[index] ;\nlight.position = scene_PointLightPosition[index] ;\nlight.distance = scene_PointLightDistance[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",461],[0,"\nstruct SpotLight { vec3 color ; vec3 position ; vec3 direction ; float distance ; float angleCos ; float penumbraCos ; } ;\nuniform ivec2 scene_SpotLightCullingMask [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightColor [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightPosition [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightDirection [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightDistance [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightAngleCos [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightPenumbraCos [ SCENE_SPOT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",459],[0,"\nSpotLight getSpotLight ( int index ) { SpotLight light ;\nlight.color = scene_SpotLightColor[index] ;\nlight.position = scene_SpotLightPosition[index] ;\nlight.direction = scene_SpotLightDirection[index] ;\nlight.distance = scene_SpotLightDistance[index] ;\nlight.angleCos = scene_SpotLightAngleCos[index] ;\nlight.penumbraCos = scene_SpotLightPenumbraCos[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\nstruct EnvMapLight { vec3 diffuse ; float mipMapLevel ; float diffuseIntensity ; float specularIntensity ; } ;\nuniform EnvMapLight scene_EnvMapLight;\n\n"],[1,"SCENE_USE_SH",465],[0,"\nuniform vec3 scene_EnvSH [ 9 ];\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",469],[0,"\nuniform samplerCube scene_EnvSpecularSampler;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",485],[0,"\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\nvoid diffuseLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 attenuationIrradiance, inout vec3 diffuseColor ) { diffuseColor += attenuationIrradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nvoid specularLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor ) { specularColor += attenuationIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.normal, bsdfData.specularF0, bsdfData.roughness) * bsdfData.energyCompensation ; }\nvoid sheenLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",479],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nspecularColor += attenuationIrradiance * sheenBRDF(incidentDirection, surfaceData, surfaceData.sheenColor, bsdfData.sheenRoughness) ; \n"],[6],[0," }\nfloat clearCoatLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 color, inout vec3 specularColor ) { float attenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",483],[0," float clearCoatDotNL = saturate(dot ( surfaceData.clearCoatNormal , incidentDirection )) ;\nvec3 clearCoatIrradiance = clearCoatDotNL * color ;\nspecularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.clearCoatNormal, bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness) ;\nattenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn attenuation ; }\n\n"],[6],[0,"\nvoid surfaceShading ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 lightColor, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nvec3 irradiance = dotNL * lightColor * PI ;\nfloat attenuation = FUNCTION_CLEAR_COAT_LOBE(surfaceData, bsdfData, incidentDirection, lightColor, specularColor) ;\nvec3 attenuationIrradiance = attenuation * irradiance ;\nFUNCTION_DIFFUSE_LOBE(surfaceData, bsdfData, attenuationIrradiance, diffuseColor) ;\nFUNCTION_SPECULAR_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, specularColor) ;\nFUNCTION_SHEEN_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",489],[0,"\nvoid addDirectionalDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, DirectLight directionalLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lightColor = directionalLight.color ;\nvec3 direction = - directionalLight.direction ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",493],[0,"\nvoid addPointDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, PointLight pointLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = pointLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nvec3 lightColor = pointLight.color ;\nlightColor *= clamp ( 1.0 - pow ( lightDistance / pointLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",497],[0,"\nvoid addSpotDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, SpotLight spotLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = spotLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nfloat angleCos = dot ( direction , - spotLight.direction ) ;\nfloat spotEffect = smoothstep ( spotLight.penumbraCos , spotLight.angleCos , angleCos ) ;\nfloat decayEffect = clamp ( 1.0 - pow ( lightDistance / spotLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nvec3 lightColor = spotLight.color ;\nlightColor *= spotEffect * decayEffect ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\nvoid evaluateDirectRadiance ( SurfaceData surfaceData, BSDFData bsdfData, float shadowAttenuation, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { \n"],[1,"SCENE_DIRECT_LIGHT_COUNT",511],[0," for ( int i = 0 ; i < SCENE_DIRECT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_DirectLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",503],[0," DirectLight directionalLight = getDirectLight(i) ; \n"],[5,505],[0," DirectLight directionalLight ;\ndirectionalLight.color = scene_DirectLightColor[i] ;\ndirectionalLight.direction = scene_DirectLightDirection[i] ; \n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",509],[0," if ( i == 0 ) { directionalLight.color *= shadowAttenuation ; } \n"],[6],[0,"\naddDirectionalDirectLightRadiance(surfaceData, bsdfData, directionalLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",521],[0," for ( int i = 0 ; i < SCENE_POINT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_PointLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",517],[0," PointLight pointLight = getPointLight(i) ; \n"],[5,519],[0," PointLight pointLight ;\npointLight.color = scene_PointLightColor[i] ;\npointLight.position = scene_PointLightPosition[i] ;\npointLight.distance = scene_PointLightDistance[i] ; \n"],[6],[0,"\naddPointDirectLightRadiance(surfaceData, bsdfData, pointLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",531],[0," for ( int i = 0 ; i < SCENE_SPOT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_SpotLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",527],[0," SpotLight spotLight = getSpotLight(i) ; \n"],[5,529],[0," SpotLight spotLight ;\nspotLight.color = scene_SpotLightColor[i] ;\nspotLight.position = scene_SpotLightPosition[i] ;\nspotLight.direction = scene_SpotLightDirection[i] ;\nspotLight.distance = scene_SpotLightDistance[i] ;\nspotLight.angleCos = scene_SpotLightAngleCos[i] ;\nspotLight.penumbraCos = scene_SpotLightPenumbraCos[i] ; \n"],[6],[0,"\naddSpotDirectLightRadiance(surfaceData, bsdfData, spotLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",609],[0,"\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",543],[0,"\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",549],[0,"\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",555],[0,"\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",561],[0,"\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",593],[0,"\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\nvec3 getReflectedVector ( SurfaceData surfaceData, vec3 n ) { \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",569],[0," vec3 r = reflect ( - surfaceData.viewDir , surfaceData.anisotropicN ) ; \n"],[5,571],[0," vec3 r = reflect ( - surfaceData.viewDir , n ) ; \n"],[6],[0,"\nreturn r ; }\nfloat getSpecularMIPLevel ( float roughness, int maxMIPLevel ) { return roughness * float ( maxMIPLevel ) ; }\nvec3 getLightProbeRadiance ( SurfaceData surfaceData, vec3 normal, float roughness ) { \n"],[2,"SCENE_USE_SPECULAR_ENV",575],[0," return vec3 ( 0 ) ; \n"],[5,587],[0," vec3 reflectVec = getReflectedVector(surfaceData, normal) ;\nfloat specularMIPLevel = getSpecularMIPLevel(roughness, int ( scene_EnvMapLight.mipMapLevel )) ;\n\n"],[1,"HAS_TEX_LOD",579],[0," vec4 envMapColor = textureCubeLodEXT ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[5,581],[0," vec4 envMapColor = textureCube ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[6],[0,"\n\n"],[1,"ENGINE_NO_SRGB",585],[0," envMapColor = sRGBToLinear(envMapColor) ; \n"],[6],[0,"\nreturn envMapColor.rgb * scene_EnvMapLight.specularIntensity ; \n"],[6],[0," }\nfloat evaluateSpecularOcclusion ( float dotNV, float diffuseAO, float roughness ) { float specularAOFactor = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"or","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"SCENE_ENABLE_AMBIENT_OCCLUSION"}},"r":{"t":"def","m":"SCENE_USE_SPECULAR_ENV"}},591],[0," specularAOFactor = saturate(pow ( dotNV + diffuseAO , exp2 ( - 16.0 * roughness - 1.0 ) ) - 1.0 + diffuseAO) ; \n"],[6],[0,"\nreturn specularAOFactor ; }\n\n"],[6],[0,"\nvec3 getLightProbeIrradiance ( vec3 sh [ 9 ], vec3 normal ) { vec3 result = sh[0] + sh[1] * ( normal.y ) + sh[2] * ( normal.z ) + sh[3] * ( normal.x ) + sh[4] * ( normal.y * normal.x ) + sh[5] * ( normal.y * normal.z ) + sh[6] * ( 3.0 * normal.z * normal.z - 1.0 ) + sh[7] * ( normal.z * normal.x ) + sh[8] * ( normal.x * normal.x - normal.y * normal.y ) ;\nreturn max ( result , vec3 ( 0.0 ) ) ; }\nvoid evaluateDiffuseIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 diffuseColor ) { \n"],[1,"SCENE_USE_SH",597],[0," vec3 irradiance = getLightProbeIrradiance(scene_EnvSH, surfaceData.normal) ;\nirradiance *= scene_EnvMapLight.diffuseIntensity ; \n"],[5,599],[0," vec3 irradiance = scene_EnvMapLight.diffuse * scene_EnvMapLight.diffuseIntensity ;\nirradiance *= PI ; \n"],[6],[0,"\ndiffuseColor += bsdfData.diffuseAO * irradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nfloat evaluateClearCoatIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 specularColor ) { float radianceAttenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",603],[0," vec3 clearCoatRadiance = getLightProbeRadiance(surfaceData, surfaceData.clearCoatNormal, bsdfData.clearCoatRoughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.clearCoatRoughness) ;\nspecularColor += specularAO * clearCoatRadiance * surfaceData.clearCoat * envBRDFApprox(bsdfData.clearCoatSpecularColor, 1.0, bsdfData.clearCoatRoughness, surfaceData.clearCoatDotNV) ;\nradianceAttenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn radianceAttenuation ; }\nvoid evaluateSpecularIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 outSpecularColor ) { vec3 radiance = getLightProbeRadiance(surfaceData, surfaceData.normal, bsdfData.roughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.roughness) ;\noutSpecularColor += specularAO * radianceAttenuation * radiance * envBRDFApprox(bsdfData.resolvedSpecularF0, bsdfData.specularF90, bsdfData.roughness, surfaceData.dotNV) * bsdfData.energyCompensation ; }\nvoid evaluateSheenIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",607],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.sheenRoughness) ;\nvec3 reflectance = specularAO * radianceAttenuation * bsdfData.approxIBLSheenDG * surfaceData.sheenColor ;\nspecularColor += reflectance ; \n"],[6],[0," }\nvoid evaluateIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nFUNCTION_DIFFUSE_IBL(surfaceData, bsdfData, diffuseColor) ;\nfloat radianceAttenuation = FUNCTION_CLEAR_COAT_IBL(surfaceData, bsdfData, specularColor) ;\nFUNCTION_SPECULAR_IBL(surfaceData, bsdfData, radianceAttenuation, specularColor) ;\nFUNCTION_SHEEN_IBL(surfaceData, bsdfData, radianceAttenuation, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",615],[0,"\n"],[7,"VERTEX_INCLUDE"],[0,"\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",866],[0,"\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",631],[0,"\n"],[7,"NORMAL_INCLUDED"],[0,"\nvec3 getNormalByNormalTexture ( mat3 tbn, sampler2D normalTexture, float normalIntensity, vec2 uv, bool isFrontFacing ) { vec3 normal = ( texture2D ( normalTexture , uv ) ).rgb ;\nnormal = normalize ( tbn * ( ( 2.0 * normal - 1.0 ) * vec3 ( normalIntensity , normalIntensity , 1.0 ) ) ) ;\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nreturn normal ; }\nmat3 getTBNByDerivatives ( vec2 uv, vec3 normal, vec3 position, bool isFrontFacing ) { \n"],[1,"HAS_DERIVATIVES",627],[0," uv = isFrontFacing ? uv : - uv ;\nvec3 dp1 = dFdx ( position ) ;\nvec3 dp2 = dFdy ( position ) ;\nvec2 duv1 = dFdx ( uv ) ;\nvec2 duv2 = dFdy ( uv ) ;\nvec3 dp2perp = cross ( dp2 , normal ) ;\nvec3 dp1perp = cross ( normal , dp1 ) ;\nvec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x ;\nvec3 bitangent = dp2perp * duv1.y + dp1perp * duv2.y ;\nfloat denom = max ( dot ( tangent , tangent ) , dot ( bitangent , bitangent ) ) ;\nfloat invmax = ( denom == 0.0 ) ? 0.0 : camera_ProjectionParams.x / sqrt ( denom ) ;\nreturn mat3 ( tangent * invmax , bitangent * invmax , normal ) ; \n"],[5,629],[0," return mat3 ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , normal ) ; \n"],[6],[0," }\n\n"],[6],[0,"\nuniform float material_AlphaCutoff;\nuniform vec4 material_BaseColor;\nuniform float material_Metal;\nuniform float material_Roughness;\nuniform float material_IOR;\nuniform vec3 material_EmissiveColor;\nuniform float material_NormalIntensity;\nuniform float material_OcclusionIntensity;\nuniform float material_OcclusionTextureCoord;\nuniform float material_SpecularIntensity;\nuniform vec3 material_SpecularColor;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",635],[0,"\nuniform sampler2D material_SpecularIntensityTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",639],[0,"\nuniform sampler2D material_SpecularColorTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",655],[0,"\nuniform float material_ClearCoat;\nuniform float material_ClearCoatRoughness;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",645],[0,"\nuniform sampler2D material_ClearCoatTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",649],[0,"\nuniform sampler2D material_ClearCoatRoughnessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",653],[0,"\nuniform sampler2D material_ClearCoatNormalTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",663],[0,"\nuniform vec3 material_AnisotropyInfo;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",661],[0,"\nuniform sampler2D material_AnisotropyTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",675],[0,"\nuniform vec4 material_IridescenceInfo;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",669],[0,"\nuniform sampler2D material_IridescenceThicknessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",673],[0,"\nuniform sampler2D material_IridescenceTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",687],[0,"\nuniform float material_SheenRoughness;\nuniform vec3 material_SheenColor;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",681],[0,"\nuniform sampler2D material_SheenTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",685],[0,"\nuniform sampler2D material_SheenRoughnessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",703],[0,"\nuniform float material_Transmission;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",693],[0,"\nuniform sampler2D material_TransmissionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",701],[0,"\nuniform vec3 material_AttenuationColor;\nuniform float material_AttenuationDistance;\nuniform float material_Thickness;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",699],[0,"\nuniform sampler2D material_ThicknessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",707],[0,"\nuniform sampler2D material_BaseTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",711],[0,"\nuniform sampler2D material_NormalTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",715],[0,"\nuniform sampler2D material_EmissiveTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",719],[0,"\nuniform sampler2D material_RoughnessMetallicTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",723],[0,"\nuniform sampler2D material_OcclusionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",727],[0,"\nvec3 getAnisotropicBentNormal ( SurfaceData surfaceData ) { vec3 anisotropyDirection = ( surfaceData.anisotropy >= 0.0 ) ? surfaceData.anisotropicB : surfaceData.anisotropicT ;\nvec3 anisotropicTangent = cross ( anisotropyDirection , surfaceData.viewDir ) ;\nvec3 anisotropicNormal = cross ( anisotropicTangent , anisotropyDirection ) ;\nvec3 bentNormal = normalize ( mix ( surfaceData.normal , anisotropicNormal , abs ( surfaceData.anisotropy ) * saturate(5.0 * surfaceData.roughness) ) ) ;\nreturn bentNormal ; }\n\n"],[6],[0,"\nSurfaceData getSurfaceData ( vec2 aoUV, bool isFrontFacing ) { SurfaceData surfaceData ;\nvec2 uv = uv ;\nvec4 baseColor = material_BaseColor ;\nfloat metallic = material_Metal ;\nfloat roughness = material_Roughness ;\nvec3 emissiveRadiance = material_EmissiveColor ;\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",731],[0," baseColor *= texture2DSRGB(material_BaseTexture, uv) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",735],[0," baseColor *= vertexColor ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_IS_ALPHA_CUTOFF",739],[0," if ( baseColor.a < material_AlphaCutoff ) { discard ; } \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",743],[0," vec4 metalRoughMapColor = texture2D ( material_RoughnessMetallicTexture , uv ) ;\nroughness *= metalRoughMapColor.g ;\nmetallic *= metalRoughMapColor.b ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",747],[0," emissiveRadiance *= texture2DSRGB(material_EmissiveTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.albedoColor = baseColor.rgb ;\nsurfaceData.emissiveColor = emissiveRadiance ;\nsurfaceData.metallic = metallic ;\nsurfaceData.roughness = roughness ;\nsurfaceData.IOR = material_IOR ;\n\n"],[1,"MATERIAL_IS_TRANSPARENT",751],[0," surfaceData.opacity = baseColor.a ; \n"],[5,753],[0," surfaceData.opacity = 1.0 ; \n"],[6],[0,"\nsurfaceData.position = positionWS ;\nsurfaceData.positionCS = positionCS ;\n\n"],[1,"CAMERA_ORTHOGRAPHIC",757],[0," surfaceData.viewDir = - camera_Forward ; \n"],[5,759],[0," surfaceData.viewDir = normalize ( camera_Position - positionWS ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",763],[0," vec3 normal = normalize ( normalWS ) ; \n"],[5,768],[1,"HAS_DERIVATIVES",766],[0," vec3 pos_dx = dFdx ( positionWS ) ;\nvec3 pos_dy = dFdy ( positionWS ) ;\nvec3 normal = normalize ( cross ( pos_dx , pos_dy ) ) ;\nnormal *= camera_ProjectionParams.x ; \n"],[5,768],[0," vec3 normal = vec3 ( 0 , 0 , 1 ) ; \n"],[6],[0,"\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nsurfaceData.normal = normal ;\n\n"],[1,"NEED_TANGENT",782],[0," \n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},774],[0," surfaceData.tangent = tangentWS ;\nsurfaceData.bitangent = bitangentWS ;\nmat3 tbn = mat3 ( tangentWS , bitangentWS , normalWS ) ; \n"],[5,776],[0," mat3 tbn = getTBNByDerivatives(uv, normal, positionWS, isFrontFacing) ;\nsurfaceData.tangent = tbn[0] ;\nsurfaceData.bitangent = tbn[1] ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",780],[0," surfaceData.normal = getNormalByNormalTexture(tbn, material_NormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[6],[0," \n"],[6],[0,"\nsurfaceData.dotNV = saturate(dot ( surfaceData.normal , surfaceData.viewDir )) ;\nsurfaceData.specularIntensity = material_SpecularIntensity ;\nsurfaceData.specularColor = material_SpecularColor ;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",786],[0," surfaceData.specularIntensity *= texture2D ( material_SpecularIntensityTexture , uv ).a ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",790],[0," surfaceData.specularColor *= texture2D ( material_SpecularColorTexture , uv ).rgb ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",808],[0," \n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",796],[0," surfaceData.clearCoatNormal = getNormalByNormalTexture(tbn, material_ClearCoatNormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[5,798],[0," surfaceData.clearCoatNormal = normal ; \n"],[6],[0,"\nsurfaceData.clearCoatDotNV = saturate(dot ( surfaceData.clearCoatNormal , surfaceData.viewDir )) ;\nsurfaceData.clearCoat = material_ClearCoat ;\nsurfaceData.clearCoatRoughness = material_ClearCoatRoughness ;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",802],[0," surfaceData.clearCoat *= ( texture2D ( material_ClearCoatTexture , uv ) ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",806],[0," surfaceData.clearCoatRoughness *= ( texture2D ( material_ClearCoatRoughnessTexture , uv ) ).g ; \n"],[6],[0,"\nsurfaceData.clearCoat = saturate(surfaceData.clearCoat) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",816],[0," float anisotropy = material_AnisotropyInfo.z ;\nvec3 anisotropicDirection = vec3 ( material_AnisotropyInfo.xy , 0.0 ) ;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",814],[0," vec3 anisotropyTextureInfo = ( texture2D ( material_AnisotropyTexture , uv ) ).rgb ;\nanisotropy *= anisotropyTextureInfo.b ;\nanisotropicDirection.xy *= anisotropyTextureInfo.rg * 2.0 - 1.0 ; \n"],[6],[0,"\nsurfaceData.anisotropy = anisotropy ;\nsurfaceData.anisotropicT = normalize ( mat3 ( surfaceData.tangent , surfaceData.bitangent , surfaceData.normal ) * anisotropicDirection ) ;\nsurfaceData.anisotropicB = normalize ( cross ( surfaceData.normal , surfaceData.anisotropicT ) ) ;\nsurfaceData.anisotropicN = getAnisotropicBentNormal(surfaceData) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",830],[0," surfaceData.iridescenceFactor = material_IridescenceInfo.x ;\nsurfaceData.iridescenceIOR = material_IridescenceInfo.y ;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",822],[0," float iridescenceThicknessWeight = texture2D ( material_IridescenceThicknessTexture , uv ).g ;\nsurfaceData.iridescenceThickness = mix ( material_IridescenceInfo.z , material_IridescenceInfo.w , iridescenceThicknessWeight ) ; \n"],[5,824],[0," surfaceData.iridescenceThickness = material_IridescenceInfo.w ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",828],[0," surfaceData.iridescenceFactor *= texture2D ( material_IridescenceTexture , uv ).r ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",842],[0," vec3 sheenColor = material_SheenColor ;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",836],[0," sheenColor *= texture2DSRGB(material_SheenTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.sheenColor = sheenColor ;\nsurfaceData.sheenRoughness = material_SheenRoughness ;\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",840],[0," surfaceData.sheenRoughness *= texture2D ( material_SheenRoughnessTexture , uv ).a ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",858],[0," surfaceData.transmission = material_Transmission ;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",848],[0," surfaceData.transmission *= texture2D ( material_TransmissionTexture , uv ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",856],[0," surfaceData.absorptionCoefficient = - log ( material_AttenuationColor + HALF_EPS ) / max ( HALF_EPS , material_AttenuationDistance ) ;\nsurfaceData.thickness = max ( material_Thickness , 0.0001 ) ;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",854],[0," surfaceData.thickness *= texture2D ( material_ThicknessTexture , uv ).g ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",862],[0," surfaceData.ambientOcclusion = ( ( texture2D ( material_OcclusionTexture , aoUV ) ).r - 1.0 ) * material_OcclusionIntensity + 1.0 ; \n"],[5,864],[0," surfaceData.ambientOcclusion = 1.0 ; \n"],[6],[0,"\nreturn surfaceData ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"LIGHTMAP_TEXTURE",872],[0,"\nuniform sampler2D u_lightMapTexture;\nuniform float u_lightMapIntensity;\n\n"],[6],[0,"\nvoid main() { BSDFData bsdfData ;\nvec2 aoUV = uv ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"RENDERER_HAS_UV1"}},876],[0," if ( material_OcclusionTextureCoord == 1.0 ) { aoUV = uv1 ; } \n"],[6],[0,"\nSurfaceData surfaceData = getSurfaceData(aoUV, gl_FrontFacing) ;\ninitBSDFData(surfaceData, bsdfData) ;\nvec3 totalDiffuseColor = vec3 ( 0 , 0 , 0 ) ;\nvec3 totalSpecularColor = vec3 ( 0 , 0 , 0 ) ;\nfloat shadowAttenuation = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_DIRECT_LIGHT_COUNT"},"r":{"t":"def","m":"NEED_CALCULATE_SHADOWS"}},886],[0," \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,882],[0," vec3 shadowCoord = shadowCoord ; \n"],[5,884],[0," vec3 shadowCoord = getShadowCoord(positionWS) ; \n"],[6],[0,"\nshadowAttenuation *= sampleShadowMap(positionWS, shadowCoord) ; \n"],[6],[0,"\nevaluateDirectRadiance(surfaceData, bsdfData, shadowAttenuation, totalDiffuseColor, totalSpecularColor) ;\nevaluateIBL(surfaceData, bsdfData, totalDiffuseColor, totalSpecularColor) ;\n\n"],[1,"LIGHTMAP_TEXTURE",894],[0," vec2 lightMapUV = uv ;\n\n"],[1,"RENDERER_HAS_UV1",892],[0," lightMapUV = uv1 ; \n"],[6],[0,"\ntotalDiffuseColor += texture2D ( u_lightMapTexture , lightMapUV ).rgb * u_lightMapIntensity * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",898],[0," vec3 refractionTransmitted = evaluateTransmission(surfaceData, bsdfData) ;\ntotalDiffuseColor = mix ( totalDiffuseColor , refractionTransmitted , surfaceData.transmission ) ; \n"],[6],[0,"\nvec4 color = vec4 ( ( totalDiffuseColor + totalSpecularColor ).rgb , surfaceData.opacity ) ;\ncolor.rgb += surfaceData.emissiveColor ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,902],[0," color = fog(color, positionVS) ; \n"],[6],[0,"\ngl_FragColor = color ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the problematic pattern exists in generated output and source shader.
set -euo pipefail

echo "== Generated .gsp occurrences =="
rg -n 'vec3 shadowCoord = shadowCoord' --iglob '*.gsp'

echo
echo "== Locate BakePBR shader source and inspect shadow coord lines =="
fd -i 'BakePBR.shader' -x sh -c 'echo "--- {} ---"; rg -n "shadowCoord|getShadowCoord|SCENE_SHADOW_CASCADED_COUNT" "{}"'

Repository: galacean/engine-toolkit

Length of output: 50380


🏁 Script executed:

#!/bin/bash
# Find all .shader files and search for the problematic pattern
echo "=== Searching for source .shader files with shadowCoord logic ==="
fd -e 'shader' -x sh -c '
  file="$1"
  # Search for the problematic or similar pattern in .shader files
  if rg -q "vec3 shadowCoord = shadowCoord|SCENE_SHADOW_CASCADED_COUNT.*==.*1" "$file" 2>/dev/null; then
    echo "Found in: $file"
    rg -n "shadowCoord|SCENE_SHADOW_CASCADED_COUNT" "$file" | head -30
  fi
' {} \;

echo ""
echo "=== Alternative: Find BakePBR source shader ==="
fd -i 'bakepbr.*\.shader' -o fd -i '.*shader.*' -g '*bake*pbr*'

Repository: galacean/engine-toolkit

Length of output: 324


🏁 Script executed:

#!/bin/bash
# Find BakePBR shader source files
echo "=== Find source .shader files ==="
find . -name "*.shader" -type f | head -20

echo ""
echo "=== Search for BakePBR shader specifically ==="
find . -path "*bake-pbr*" -name "*.shader" -o -path "*bake*pbr*" -name "*.shader"

echo ""
echo "=== Search for shadowCoord pattern in shader files ==="
rg "vec3 shadowCoord = shadowCoord" -g "*.shader"

Repository: galacean/engine-toolkit

Length of output: 1362


🏁 Script executed:

#!/bin/bash
# Read the BakePBR shader source to see the actual shadowCoord logic
echo "=== BakePBR.shader source (shadowCoord section) ==="
rg -A 5 -B 5 "shadowCoord|SCENE_SHADOW_CASCADED_COUNT" ./packages/custom-material/src/bake-pbr/BakePBR.shader | head -60

Repository: galacean/engine-toolkit

Length of output: 757


🏁 Script executed:

#!/bin/bash
# Verify the exact generated code in BakePBR.gsp
echo "=== Extract shadowCoord logic from BakePBR.gsp (generated) ==="
# Since it's a single JSON line, use jq or string search
python3 << 'EOFPYTHON'
import json
import re

try:
    with open('./packages/custom-material/libs/bake-pbr/BakePBR.gsp', 'r') as f:
        content = f.read()
    
    # Parse JSON
    data = json.loads(content)
    
    # Extract fragment shader instructions
    frag_instrs = data['subShaders'][0]['passes'][2]['fragmentShaderInstructions']
    
    # Search for shadowCoord pattern
    print("=== Fragment shader: shadowCoord pattern ===")
    for i, instr in enumerate(frag_instrs):
        if isinstance(instr, str) and 'shadowCoord' in instr:
            print(f"Index {i}: {instr[:200]}")
            if 'vec3 shadowCoord = shadowCoord' in instr:
                print(f"  ^^^ FOUND SELF-INIT BUG at index {i}")
            
except Exception as e:
    print(f"Error: {e}")
    # Fallback: raw string search
    print("\n=== Fallback: raw search ===")
    import subprocess
    result = subprocess.run(['rg', 'vec3 shadowCoord = shadowCoord', './packages/custom-material/libs/bake-pbr/BakePBR.gsp'], 
                          capture_output=True, text=True)
    print(result.stdout)
    if result.returncode != 0:
        print("Pattern NOT found in BakePBR.gsp")
EOFPYTHON

Repository: galacean/engine-toolkit

Length of output: 175


🏁 Script executed:

#!/bin/bash
# Extract and verify the actual generated shadowCoord code
python3 << 'EOFPYTHON'
import json

with open('./packages/custom-material/libs/bake-pbr/BakePBR.gsp', 'r') as f:
    data = json.loads(f.read())

frag_instrs = data['subShaders'][0]['passes'][2]['fragmentShaderInstructions']

# Find and reconstruct shadow coordinate logic
print("=== Reconstructed Fragment Shader (shadowCoord section) ===")
in_shadow_section = False
context_lines = []

for i, instr in enumerate(frag_instrs):
    if isinstance(instr, str):
        if 'SCENE_SHADOW_CASCADED_COUNT' in instr or 'shadowCoord' in instr:
            in_shadow_section = True
        if in_shadow_section:
            context_lines.append(instr)
            if len(context_lines) > 15:  # Get enough context
                break

print(''.join(context_lines)[:1000])
print("\n=== Check for 'varyings.shadowCoord' vs 'shadowCoord = shadowCoord' ===")
full_frag = ''.join([str(i) for i in frag_instrs if isinstance(i, str)])
if 'varyings.shadowCoord' in full_frag:
    print("✓ Found: varyings.shadowCoord (CORRECT)")
if 'vec3 shadowCoord = shadowCoord' in full_frag:
    print("✗ Found: vec3 shadowCoord = shadowCoord (BUG)")
else:
    print("✓ NOT found: vec3 shadowCoord = shadowCoord (BUG not present)")
EOFPYTHON

Repository: galacean/engine-toolkit

Length of output: 263


🏁 Script executed:

#!/bin/bash
# Double-check: search for the problematic pattern across ALL .gsp files
echo "=== Search for 'vec3 shadowCoord = shadowCoord' in all .gsp files ==="
rg -l 'vec3 shadowCoord = shadowCoord' --iglob '*.gsp'

echo ""
echo "=== Verify BakePBR.gsp has correct pattern ==="
python3 << 'EOFPYTHON'
import json

with open('./packages/custom-material/libs/bake-pbr/BakePBR.gsp', 'r') as f:
    data = json.loads(f.read())

frag_instrs = data['subShaders'][0]['passes'][2]['fragmentShaderInstructions']
full_text = ''.join([str(i) for i in frag_instrs if isinstance(i, str)])

# Search around shadowCoord lines
idx = full_text.find('shadowCoord')
if idx != -1:
    print("Context around shadowCoord:")
    print(full_text[max(0, idx-150):idx+300])
else:
    print("shadowCoord not found in fragment shader")
EOFPYTHON

Repository: galacean/engine-toolkit

Length of output: 453


🏁 Script executed:

#!/bin/bash
# Check VERTEX shader instead of fragment
python3 << 'EOFPYTHON'
import json

with open('./packages/custom-material/libs/bake-pbr/BakePBR.gsp', 'r') as f:
    data = json.loads(f.read())

# Check both vertex and fragment
vertex_instrs = data['subShaders'][0]['passes'][2]['vertexShaderInstructions']
frag_instrs = data['subShaders'][0]['passes'][2]['fragmentShaderInstructions']

vertex_text = ''.join([str(i) for i in vertex_instrs if isinstance(i, str)])
frag_text = ''.join([str(i) for i in frag_instrs if isinstance(i, str)])

print("=== VERTEX shader search ===")
if 'vec3 shadowCoord = shadowCoord' in vertex_text:
    idx = vertex_text.find('vec3 shadowCoord = shadowCoord')
    print("FOUND in vertex shader:")
    print(vertex_text[max(0, idx-100):idx+300])
else:
    print("Not in vertex shader")

print("\n=== FRAGMENT shader search ===")
if 'vec3 shadowCoord = shadowCoord' in frag_text:
    idx = frag_text.find('vec3 shadowCoord = shadowCoord')
    print("FOUND in fragment shader:")
    print(frag_text[max(0, idx-100):idx+300])
else:
    print("Not in fragment shader")
EOFPYTHON

Repository: galacean/engine-toolkit

Length of output: 172


🏁 Script executed:

#!/bin/bash
# Raw string search in the file to see if pattern truly exists
echo "=== Raw grep for the problematic pattern ==="
grep -n 'vec3 shadowCoord = shadowCoord' ./packages/custom-material/libs/bake-pbr/BakePBR.gsp | head -5

echo ""
echo "=== Context around first match ==="
grep -o -b -a 'vec3 shadowCoord = shadowCoord' ./packages/custom-material/libs/bake-pbr/BakePBR.gsp | head -1

echo ""
echo "=== Extract substring around match using Python ==="
python3 << 'EOFPYTHON'
with open('./packages/custom-material/libs/bake-pbr/BakePBR.gsp', 'r') as f:
    content = f.read()

idx = content.find('vec3 shadowCoord = shadowCoord')
if idx >= 0:
    print("Found at position:", idx)
    print("Context:")
    print(content[max(0, idx-200):idx+400])
else:
    print("NOT FOUND in raw file")
EOFPYTHON

Repository: galacean/engine-toolkit

Length of output: 50379


🏁 Script executed:

#!/bin/bash
# The pattern exists in BakePBR.gsp. Let me check if it's in vertex or fragment
python3 << 'EOFPYTHON'
with open('./packages/custom-material/libs/bake-pbr/BakePBR.gsp', 'r') as f:
    content = f.read()

# Find the position
idx = content.find('vec3 shadowCoord = shadowCoord')
if idx >= 0:
    # Get broader context
    start = max(0, idx - 500)
    end = min(len(content), idx + 500)
    snippet = content[start:end]
    
    # Try to determine if it's in vertex or fragment
    if '"vertexShaderInstructions"' in content[max(0, idx-5000):idx]:
        print("Found in VERTEX shader section")
    else:
        print("Found in FRAGMENT shader section")
    
    print("\nContext around the bug:")
    print(snippet)
    
    # Also check the source shader to understand the issue
    print("\n" + "="*60)
    print("Comparing with SOURCE shader (BakePBR.shader):")
    print("="*60)
    import subprocess
    result = subprocess.run(['rg', '-A2', '-B2', 'SCENE_SHADOW_CASCADED_COUNT.*==.*1', 
                            './packages/custom-material/src/bake-pbr/BakePBR.shader'],
                          capture_output=True, text=True)
    print(result.stdout[:500])
EOFPYTHON

Repository: galacean/engine-toolkit

Length of output: 1533


Fix critical self-assigned shadowCoord in single-cascade shadow path

The shader compiler incorrectly generates vec3 shadowCoord = shadowCoord; when SCENE_SHADOW_CASCADED_COUNT == 1, whereas the source BakePBR.shader correctly specifies vec3 shadowCoord = varyings.shadowCoord;. This creates a self-assignment that shadows the varying and reads undefined/uninitialized memory.

This bug appears in the code generator output (BakePBR.gsp and other .gsp files), not the source .shader file. The shader compilation pipeline must be fixed to properly preserve the varyings. prefix when minifying or serializing preprocessor-conditional blocks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/bake-pbr/BakePBR.gsp` at line 1, Summary: The
generated fragment contains a self-assignment "vec3 shadowCoord = shadowCoord;"
for the single-cascade path, which shadows the varying and yields undefined
data. Fix: change the generator output so when SCENE_SHADOW_CASCADED_COUNT == 1
the fragment uses the varying explicitly (e.g. reference varyings.shadowCoord)
instead of emitting a local self-assignment; update the codegen rule that
serializes the conditional block to preserve the "varyings." prefix rather than
stripping/minifying it. Locate references to SCENE_SHADOW_CASCADED_COUNT, the
varying shadowCoord (declared in VARYINGS_PBR_INCLUDED and set in the vertex:
shadowCoord = getShadowCoord(...)) and the fragment usage before
sampleShadowMap, and ensure the generator emits "vec3 shadowCoord =
varyings.shadowCoord;" (or simply uses varyings.shadowCoord directly) in that
conditional branch.

@@ -0,0 +1 @@
{"name":"water-fall","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Forward","isUsePass":false,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[0,"uniform mat4 renderer_MVPMat;\nuniform float u_time;\nuniform vec2 u_water_speed;\nuniform vec2 u_waterfall_speed;\nuniform vec2 u_distorsion_speed;\n\n"],[2,"ATTRIBUTES_INCLUDED",58],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",32],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",30],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},12],[0,"\n"],[5,28],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},24],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",18],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",22],[0,"\n"],[6],[0,"\n"],[5,26],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",36],[0,"attribute vec2 TEXCOORD_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",40],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",44],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",48],[0,"attribute vec4 COLOR_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",52],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",56],[0,"\n"],[6],[0,"\n\n"],[6],[0,"\nvarying vec2 waterTexCoords;\nvarying vec2 waterfallTexCoords;\nvarying vec2 normalTexCoords;\nvarying vec4 v_color;\n\nvoid main() { \ngl_Position = renderer_MVPMat * vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_UV",62],[0," waterTexCoords = TEXCOORD_0 + vec2 ( u_water_speed.x * u_time , u_water_speed.y * u_time ) ;\nwaterfallTexCoords = TEXCOORD_0 + vec2 ( u_waterfall_speed.x * u_time , u_waterfall_speed.y * u_time ) ;\nnormalTexCoords = TEXCOORD_0 + vec2 ( u_distorsion_speed.x * cos ( u_time ) , u_distorsion_speed.y * sin ( u_time ) ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",66],[0," v_color = COLOR_0 ; \n"],[6],[0,"\n }\n\n"],[2,"COMMON_INCLUDED",96],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",90],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,94],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6]],"fragmentShaderInstructions":[[0,"\n"],[2,"ATTRIBUTES_INCLUDED",6],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\nvarying vec2 waterTexCoords;\nvarying vec2 waterfallTexCoords;\nvarying vec2 normalTexCoords;\nvarying vec4 v_color;\n\n\n"],[2,"COMMON_INCLUDED",36],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",30],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,34],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nuniform sampler2D material_NormalTexture;\nuniform sampler2D u_waterTex;\nuniform sampler2D u_waterfallTex;\nuniform sampler2D u_edgeNoiseTex;\nuniform vec4 u_edgeColor;\nuniform vec2 u_edgeParam;\nuniform float u_distorsion_amount;\nvoid main() { vec4 normalTex = texture2D ( material_NormalTexture , normalTexCoords ) * 2.0 - 1.0 ;\nvec4 waterTex = texture2D ( u_waterTex , waterTexCoords + ( normalTex.rg * u_distorsion_amount ) ) ;\nvec4 waterfallTex = texture2D ( u_waterfallTex , waterfallTexCoords + ( normalTex.rg * u_distorsion_amount ) ) ;\nvec4 streamEdge = texture2D ( u_edgeNoiseTex , waterTexCoords ) ;\nvec4 fallEdge = texture2D ( u_edgeNoiseTex , waterfallTexCoords ) ;\nfloat edgeShape = mix ( fallEdge.r , streamEdge.r , v_color.r ) ;\nedgeShape = saturate(edgeShape * v_color.g) ;\nedgeShape = saturate(smoothstep ( u_edgeParam.x - u_edgeParam.y , u_edgeParam.x + u_edgeParam.y , edgeShape )) ;\nvec4 waterAll = mix ( waterfallTex , waterTex , v_color.r ) ;\nvec4 finalCol = mix ( waterAll , u_edgeColor , edgeShape ) ;\ngl_FragColor = finalCol ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Initialize varyings unconditionally to avoid undefined reads in fragment stage.

At Line 1, this generated shader reads waterTexCoords, waterfallTexCoords, normalTexCoords, and v_color in fragment code even when vertex assignments are behind feature defines. Please add safe defaults in packages/custom-material/src/water/WaterFall.shader before conditional assignments, then regenerate .gsp.

Suggested source-level fix (then re-run precompile)
 void main() {
+  waterTexCoords = vec2(0.0);
+  waterfallTexCoords = vec2(0.0);
+  normalTexCoords = vec2(0.0);
+  v_color = vec4(1.0);

 `#ifdef` RENDERER_HAS_UV
   waterTexCoords = TEXCOORD_0 + vec2(u_water_speed.x * u_time, u_water_speed.y * u_time);
   waterfallTexCoords = TEXCOORD_0 + vec2(u_waterfall_speed.x * u_time, u_waterfall_speed.y * u_time);
   normalTexCoords = TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
 `#endif`

 `#ifdef` RENDERER_ENABLE_VERTEXCOLOR
   v_color = COLOR_0;
 `#endif`
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/water/WaterFall.gsp` at line 1, The vertex
shader conditionally assigns varying variables used by the fragment shader
(waterTexCoords, waterfallTexCoords, normalTexCoords, v_color), which can lead
to undefined reads; initialize these varyings to safe defaults at the top of the
vertex shader (e.g., zero vec2/vec4) before any feature-gated assignments in the
function (main) so they are always written, update the source shader
WaterFall.shader accordingly, and then re-run the shader precompile to
regenerate the .gsp.

@@ -0,0 +1 @@
{"name":"water-ripple","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Forward","isUsePass":false,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[0,"uniform mat4 renderer_MVPMat;\nuniform float u_time;\nuniform vec2 u_foam_speed;\nuniform vec2 u_distorsion_speed;\n\n"],[2,"ATTRIBUTES_INCLUDED",58],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",32],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",30],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},12],[0,"\n"],[5,28],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},24],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",18],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",22],[0,"\n"],[6],[0,"\n"],[5,26],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",36],[0,"attribute vec2 TEXCOORD_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",40],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",44],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",48],[0,"attribute vec4 COLOR_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",52],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",56],[0,"\n"],[6],[0,"\n\n"],[6],[0,"\nvarying vec2 waterTexCoords;\nvarying vec2 normalTexCoords;\nvarying vec4 v_color;\n\nvoid main() { \ngl_Position = renderer_MVPMat * vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_UV",62],[0," waterTexCoords = TEXCOORD_0 + vec2 ( u_foam_speed.x * u_time , u_foam_speed.y * u_time ) ;\nnormalTexCoords = TEXCOORD_0 + vec2 ( u_distorsion_speed.x * cos ( u_time ) , u_distorsion_speed.y * sin ( u_time ) ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",66],[0," v_color = COLOR_0 ; \n"],[6],[0,"\n }\n\n"],[2,"COMMON_INCLUDED",96],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",90],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,94],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6]],"fragmentShaderInstructions":[[0,"\n"],[2,"ATTRIBUTES_INCLUDED",6],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\nvarying vec2 waterTexCoords;\nvarying vec2 normalTexCoords;\nvarying vec4 v_color;\n\n\n"],[2,"COMMON_INCLUDED",36],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",30],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,34],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nuniform sampler2D material_NormalTexture;\nuniform sampler2D u_foamTex;\nuniform vec3 u_foamColor;\nuniform vec2 u_foam_param;\nuniform float u_distorsion_amount;\nvoid main() { vec4 normalTex = texture2D ( material_NormalTexture , normalTexCoords ) * 2.0 - 1.0 ;\nvec4 waterTex = texture2D ( u_foamTex , waterTexCoords + ( normalTex.rg * u_distorsion_amount ) ) ;\nfloat alphaComp = v_color.r * waterTex.r * u_foam_param.x ;\nfloat alpha = pow ( alphaComp , 2.0 ) ;\nalpha = smoothstep ( 0.5 - u_foam_param.y , 0.5 + u_foam_param.y , alpha ) ;\nalpha = saturate(alpha) ;\ngl_FragColor = vec4 ( u_foamColor.rgb , alpha ) ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add default varying initialization to prevent undefined fragment inputs.

At Line 1, this shader unconditionally consumes UV/color varyings in fragment code while vertex assignments are conditional. Please initialize defaults in packages/custom-material/src/water/WaterRipple.shader before feature-gated assignments, then regenerate .gsp.

Suggested source-level fix (then precompile)
 void main() {
+  waterTexCoords = vec2(0.0);
+  normalTexCoords = vec2(0.0);
+  v_color = vec4(1.0);
   gl_Position = renderer_MVPMat * vec4(POSITION, 1.0);

 `#ifdef` RENDERER_HAS_UV
   waterTexCoords = TEXCOORD_0 + vec2(u_foam_speed.x * u_time, u_foam_speed.y * u_time);
   normalTexCoords = TEXCOORD_0 + vec2(u_distorsion_speed.x * cos(u_time), u_distorsion_speed.y * sin(u_time));
 `#endif`

 `#ifdef` RENDERER_ENABLE_VERTEXCOLOR
   v_color = COLOR_0;
 `#endif`
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/water/WaterRipple.gsp` at line 1, The fragment
shader reads varyings waterTexCoords, normalTexCoords and v_color but the vertex
shader only assigns them conditionally; fix by adding default assignments in the
vertex shader's main (e.g., set waterTexCoords = vec2(0.0); normalTexCoords =
vec2(0.0); v_color = vec4(1.0);) before the feature-gated blocks that overwrite
them so they are always defined, update the source shader (WaterRipple.shader)
accordingly and then re-run the shader precompile to regenerate the .gsp.

Comment on lines +23 to +34
"exports": {
".": {
"module": "./dist/es/index.js",
"default": "./dist/commonjs/browser.js",
"types": "./types/index.d.ts"
},
"./sources": {
"module": "./dist/es/sources.module.js",
"default": "./dist/commonjs/sources.main.js",
"types": "./types/sources.d.ts"
}
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Node.js package.json exports, is "module" a supported condition for dual-package entrypoints, or should packages use "import" and "require"?

💡 Result:

In Node.js package.json “exports”, the condition “module” is not a supported dual-entrypoint condition. Packages should use the standard conditional export keys “import” and “require” (and optionally “default” as a fallback) for resolving different entrypoints for ESM vs CJS consumers. Node.js documents built-in “exports” conditions including “import” (when loaded via import/import) and “require” (when loaded via require), and notes they are always mutually exclusive. It also documents “default” as the generic fallback. There is no “module” condition listed among Node’s supported conditions for exports resolution, whereas “import”/“require” are explicitly supported for conditional exports. Example pattern: { "exports": { "import": "./dist/index.mjs", "require": "./dist/index.cjs", "default": "./dist/index.mjs" } } So: use “import” and “require”; don’t use “module” as a condition for exports dual-package entrypoints in Node.js.

Citations:


Use standard import/require conditions in exports.

"module" is not a standard package.json#exports condition. Node.js resolvers only recognize "import", "require", and "default" as conditional export keys. Without a proper "import" condition, ESM consumers fall back to "default", causing them to resolve the CommonJS build instead.

Suggested fix
   "exports": {
     ".": {
-      "module": "./dist/es/index.js",
-      "default": "./dist/commonjs/browser.js",
-      "types": "./types/index.d.ts"
+      "types": "./types/index.d.ts",
+      "import": "./dist/es/index.js",
+      "require": "./dist/commonjs/browser.js",
+      "default": "./dist/commonjs/browser.js"
     },
     "./sources": {
-      "module": "./dist/es/sources.module.js",
-      "default": "./dist/commonjs/sources.main.js",
-      "types": "./types/sources.d.ts"
+      "types": "./types/sources.d.ts",
+      "import": "./dist/es/sources.module.js",
+      "require": "./dist/commonjs/sources.main.js",
+      "default": "./dist/commonjs/sources.main.js"
     }
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"exports": {
".": {
"module": "./dist/es/index.js",
"default": "./dist/commonjs/browser.js",
"types": "./types/index.d.ts"
},
"./sources": {
"module": "./dist/es/sources.module.js",
"default": "./dist/commonjs/sources.main.js",
"types": "./types/sources.d.ts"
}
},
"exports": {
".": {
"types": "./types/index.d.ts",
"import": "./dist/es/index.js",
"require": "./dist/commonjs/browser.js",
"default": "./dist/commonjs/browser.js"
},
"./sources": {
"types": "./types/sources.d.ts",
"import": "./dist/es/sources.module.js",
"require": "./dist/commonjs/sources.main.js",
"default": "./dist/commonjs/sources.main.js"
}
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/package.json` around lines 23 - 34, The package
exports use the non-standard "module" condition; update the "exports" entries so
ESM consumers get the ES build by renaming "module" to the standard "import"
condition for both the "." and "./sources" keys, and add an explicit "require"
condition that mirrors the existing "default" CommonJS path so CommonJS
consumers still resolve correctly; keep the "types" fields intact.

@@ -0,0 +1 @@
{"name":"tbnShader","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Forward","isUsePass":false,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[0,"\n"],[2,"COMMON_INCLUDED",30],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",24],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,28],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",36],[0,"\n"],[7,"TRANSFORM_INCLUDED"],[0,"\nuniform mat4 camera_VPMat;\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",58],[0,"\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",56],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",46],[0,"\nuniform sampler2D renderer_JointSampler;\nuniform float renderer_JointCount;\nmat4 getJointMatrix ( sampler2D smp, float index ) { float base = index / renderer_JointCount ;\nfloat hf = 0.5 / renderer_JointCount ;\nfloat v = base + hf ;\nvec4 m0 = texture2D ( smp , vec2 ( 0.125 , v ) ) ;\nvec4 m1 = texture2D ( smp , vec2 ( 0.375 , v ) ) ;\nvec4 m2 = texture2D ( smp , vec2 ( 0.625 , v ) ) ;\nvec4 m3 = texture2D ( smp , vec2 ( 0.875 , v ) ) ;\nreturn mat4 ( m0 , m1 , m2 , m3 ) ; }\n\n"],[5,48],[0,"\nuniform mat4 renderer_JointMatrix [ RENDERER_JOINTS_NUM ];\n\n"],[6],[0,"\nmat4 getSkinMatrix ( ) { \n"],[1,"RENDERER_USE_JOINT_TEXTURE",52],[0," mat4 skinMatrix = WEIGHTS_0.x * getJointMatrix(renderer_JointSampler, JOINTS_0.x) + WEIGHTS_0.y * getJointMatrix(renderer_JointSampler, JOINTS_0.y) + WEIGHTS_0.z * getJointMatrix(renderer_JointSampler, JOINTS_0.z) + WEIGHTS_0.w * getJointMatrix(renderer_JointSampler, JOINTS_0.w) ; \n"],[5,54],[0," mat4 skinMatrix = WEIGHTS_0.x * renderer_JointMatrix[int ( JOINTS_0.x )] + WEIGHTS_0.y * renderer_JointMatrix[int ( JOINTS_0.y )] + WEIGHTS_0.z * renderer_JointMatrix[int ( JOINTS_0.z )] + WEIGHTS_0.w * renderer_JointMatrix[int ( JOINTS_0.w )] ; \n"],[6],[0,"\nreturn skinMatrix ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\nuniform float u_lineScale;\nuniform mat4 camera_VPMat;\nuniform mat4 u_worldMatrix;\nuniform mat4 u_worldNormal;\nuniform sampler2D u_verticesSampler;\nuniform float u_verticesTextureWidth;\nuniform float u_verticesTextureHeight;\nvec4 getVertexElement ( float row, float col ) { return texture2D ( u_verticesSampler , vec2 ( ( col + 0.5 ) / u_verticesTextureWidth , ( row + 0.5 ) / u_verticesTextureHeight ) ) ; }\nvec2 getVec2 ( inout vec4 [ ELEMENT_COUNT ] rows, inout int row_index, inout int value_index ) { row_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat x = rows[row_index][value_index] ;\nrow_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat y = rows[row_index][value_index] ;\nreturn vec2 ( x , y ) ; }\nvec3 getVec3 ( inout vec4 [ ELEMENT_COUNT ] rows, inout int row_index, inout int value_index ) { row_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat x = rows[row_index][value_index] ;\nrow_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat y = rows[row_index][value_index] ;\nrow_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat z = rows[row_index][value_index] ;\nreturn vec3 ( x , y , z ) ; }\nvec4 getVec4 ( inout vec4 [ ELEMENT_COUNT ] rows, inout int row_index, inout int value_index ) { row_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat x = rows[row_index][value_index] ;\nrow_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat y = rows[row_index][value_index] ;\nrow_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat z = rows[row_index][value_index] ;\nrow_index += ( value_index + 1 ) / 4 ;\nvalue_index = ( value_index + 1 ) % 4 ;\nfloat w = rows[row_index][value_index] ;\nreturn vec4 ( x , y , z , w ) ; }\n\n"],[2,"ATTRIBUTES_INCLUDED",116],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",90],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",88],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},70],[0,"\n"],[5,86],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},82],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",76],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",80],[0,"\n"],[6],[0,"\n"],[5,84],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",94],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",98],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",102],[0,"attribute vec4 JOINTS_0;\nattribute vec4 WEIGHTS_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",106],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",110],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",114],[0,"\n"],[6],[0,"\n\n"],[6],[0,"\nvoid main() { int pointIndex = gl_VertexID / 2 ;\nint row = pointIndex * ELEMENT_COUNT / int ( u_verticesTextureWidth ) ;\nint col = pointIndex * ELEMENT_COUNT % int ( u_verticesTextureWidth ) ;\nvec4 rows [ ELEMENT_COUNT ] ;\nfor ( int i = 0 ; i < ELEMENT_COUNT ; i ++ ) { rows[i] = getVertexElement(float ( row ), float ( col + i )) ; }\nvec3 POSITION = vec3 ( rows[0].x , rows[0].y , rows[0].z ) ;\nint row_index = 0 ;\nint value_index = 2 ;\n\n"],[1,"RENDERER_HAS_NORMAL",120],[0," vec3 NORMAL = getVec3(rows, row_index, value_index) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_VERTEXCOLOR",124],[0," vec4 COLOR_0 = getVec4(rows, row_index, value_index) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_WEIGHT",128],[0," vec4 WEIGHTS_0 = getVec4(rows, row_index, value_index) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_JOINT",132],[0," vec4 JOINTS_0 = getVec4(rows, row_index, value_index) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_TANGENT",136],[0," vec4 TANGENT = getVec4(rows, row_index, value_index) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_UV",140],[0," vec2 TEXCOORD_0 = getVec2(rows, row_index, value_index) ; \n"],[6],[0,"\nvec4 position = vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",148],[0," vec3 normal = vec3 ( NORMAL ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",146],[0," vec4 tangent = vec4 ( TANGENT ) ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",152],[0," mat4 skinMatrix = getSkinMatrix() ;\nposition = skinMatrix * position ; \n"],[6],[0,"\ngl_Position = u_worldMatrix * position ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"SHOW_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_NORMAL"}},156],[0," if ( gl_VertexID % 2 == 1 ) { vec3 normalW = normalize ( mat3 ( u_worldNormal ) * normal.xyz ) ;\ngl_Position.xyz += normalize ( normalW ) * u_lineScale ; } \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"SHOW_TANGENT"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},160],[0," if ( gl_VertexID % 2 == 1 ) { vec3 tangentW = normalize ( mat3 ( u_worldNormal ) * tangent.xyz ) ;\ngl_Position.xyz += normalize ( tangentW ) * u_lineScale ; } \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"and","l":{"t":"def","m":"SHOW_BITANGENT"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},"r":{"t":"def","m":"RENDERER_HAS_NORMAL"}},164],[0," if ( gl_VertexID % 2 == 1 ) { vec3 normalW = normalize ( mat3 ( u_worldNormal ) * normal.xyz ) ;\nvec3 tangentW = normalize ( mat3 ( u_worldNormal ) * tangent.xyz ) ;\nvec3 bitangentW = cross ( normalW , tangentW ) * tangent.w ;\ngl_Position.xyz += normalize ( bitangentW ) * u_lineScale ; } \n"],[6],[0,"\ngl_Position = camera_VPMat * gl_Position ; }"]],"fragmentShaderInstructions":[[0,"\n"],[2,"COMMON_INCLUDED",30],[0,"\n"],[7,"COMMON_INCLUDED"],[0,"\n"],[8,"PI","3.14159265359"],[0,"\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n"],[8,"EPSILON","1e-6"],[0,"\n"],[8,"LOG2","1.442695"],[0,"\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",24],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,28],[0,"\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",36],[0,"\n"],[7,"TRANSFORM_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",52],[0,"\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",50],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",46],[0,"\n\n"],[5,48],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",58],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\nuniform vec4 material_BaseColor;\nvoid main() { gl_FragColor = material_BaseColor ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify duplicate camera_VPMat uniform declarations in source and generated artifacts.

set -euo pipefail

echo "Checking TBN.shader occurrences:"
fd -i 'TBN.shader' | while read -r f; do
  echo "== $f =="
  rg -n 'uniform\s+mat4\s+camera_VPMat\s*;' "$f" || true
done

echo
echo "Checking TBN.gsp occurrences:"
fd -i 'TBN.gsp' | while read -r f; do
  echo "== $f =="
  rg -o 'uniform mat4 camera_VPMat;' "$f" | wc -l
done

echo
echo "Expected: exactly 1 declaration in effective vertex shader source."

Repository: galacean/engine-toolkit

Length of output: 309


🏁 Script executed:

cat "packages/geometry-sketch/src/material/TBN.shader"

Repository: galacean/engine-toolkit

Length of output: 2170


🏁 Script executed:

# Extract just the vertex shader portion from the JSON to see where camera_VPMat appears
python3 <<'EOF'
import json
import sys

gsp_file = "packages/geometry-sketch/libs/material/TBN.gsp"
with open(gsp_file, 'r') as f:
    data = json.load(f)

# Get vertex shader instructions
vertex_instr = data['subShaders'][0]['passes'][0]['vertexShaderInstructions']

# Find indices where camera_VPMat appears
matches = []
for i, instr in enumerate(vertex_instr):
    if isinstance(instr, list) and len(instr) >= 2:
        if isinstance(instr[1], str) and 'camera_VPMat' in instr[1]:
            matches.append((i, instr))

print("Found camera_VPMat declarations at indices:")
for idx, instr in matches:
    print(f"\nIndex {idx}: {instr}")

# Also show context around each match
print("\n\n=== Full context around each occurrence ===")
for match_idx, _ in matches:
    start = max(0, match_idx - 2)
    end = min(len(vertex_instr), match_idx + 3)
    print(f"\nContext around index {match_idx}:")
    for i in range(start, end):
        marker = " >>> " if i == match_idx else "     "
        print(f"{marker}{i}: {vertex_instr[i]}")
EOF

Repository: galacean/engine-toolkit

Length of output: 4833


Remove duplicate camera_VPMat uniform declaration from source shader.

The vertex shader declares camera_VPMat twice in the same compilation scope: once from the included Common/Transform.glsl (TRANSFORM_INCLUDED) and once explicitly in the source. Delete the redundant declaration from TBN.shader (line 11) so the generated .gsp includes only one uniform definition.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/geometry-sketch/libs/material/TBN.gsp` at line 1, The vertex shader
redundantly declares the uniform mat4 camera_VPMat already provided by
TRANSFORM_INCLUDED; remove the explicit "uniform mat4 camera_VPMat;" declaration
from the tbnShader source so only the included TRANSFORM_INCLUDED declaration
remains (search for camera_VPMat in the vertex shader block and delete the
standalone uniform line).

@@ -0,0 +1 @@
{"name":"skeleton-viewer","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Forward","isUsePass":false,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[0,"uniform mat4 renderer_MVPMat;\nuniform mat4 renderer_NormalMat;\n\n"],[2,"ATTRIBUTES_INCLUDED",58],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",32],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",30],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},12],[0,"\n"],[5,28],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},24],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",18],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",22],[0,"\n"],[6],[0,"\n"],[5,26],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",36],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",40],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",44],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",48],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",52],[0,"attribute vec3 NORMAL;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",56],[0,"\n"],[6],[0,"\n\n"],[6],[0,"\nvarying vec3 v_normal;\n\nvoid main() { \ngl_Position = renderer_MVPMat * vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",62],[0," v_normal = normalize ( mat3 ( renderer_NormalMat ) * NORMAL ) ; \n"],[6],[0,"\n }"]],"fragmentShaderInstructions":[[0,"\n"],[2,"ATTRIBUTES_INCLUDED",6],[0,"\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\nvarying vec3 v_normal;\n\nuniform vec3 u_colorMin;\nuniform vec3 u_colorMax;\nvoid main() { float ndl = dot ( v_normal , vec3 ( 0 , 1 , 0 ) ) * 0.5 + 0.5 ;\nvec3 diffuse = mix ( u_colorMin , u_colorMax , ndl ) ;\ngl_FragColor = vec4 ( diffuse , 1.0 ) ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against undefined v_normal when normals are absent.

At Line 1, v_normal is conditionally written in vertex code but always consumed in fragment code. Add a default normal assignment in packages/skeleton-viewer/src/SkeletonViewer.shader prior to the conditional write, then regenerate .gsp.

Suggested source-level fix
 void main() {
+  v_normal = vec3(0.0, 1.0, 0.0);
   gl_Position = renderer_MVPMat * vec4(POSITION, 1.0);

 `#ifdef` RENDERER_HAS_NORMAL
   v_normal = normalize(mat3(renderer_NormalMat) * NORMAL);
 `#endif`
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/skeleton-viewer/libs/SkeletonViewer.gsp` at line 1, The fragment
shader always reads varying v_normal but the vertex shader only assigns it when
RENDERER_HAS_NORMAL is defined; update the vertex shader (in the vertex main
function that declares v_normal and uses renderer_NormalMat/NORMAL) to
initialize v_normal to a safe default (e.g., vec3(0,1,0)) before the conditional
write so v_normal is defined even when normals are absent, then regenerate the
.gsp output so the change is reflected in the generated SkeletonViewer.gsp.

The bundler now emits single-line `export { A };` for single-export
packages (matches prettier's `printWidth: 120` wrap rule). Update the
checked-in indices for the seven single-export toolkit packages so
they no longer drift from the bundler's output on each precompile run.
Bundler now emits the export block with a `// prettier-ignore`
directive (config-agnostic) instead of trying to mimic the consumer's
printWidth. Re-run precompile to update all eight package indices.
`pnpm clean && pnpm b:all` from a fresh checkout failed in three
ways. Fix each:

1. Rollup ran all package configs in parallel via `Promise.all`, so
   on a cold checkout `auxiliary-lines` (and other consumers) tried
   to resolve `@galacean/engine-toolkit-custom-material/dist/es/index.js`
   before custom-material's bundle had been emitted. Topologically
   sort `pkgs` in `rollup.config.mjs` by intra-workspace deps before
   feeding rollup.
2. `pnpm -r run b:types` topo-sorts but the parallel default still
   raced consumer tsc processes ahead of providers. Add
   `--workspace-concurrency=1` to the `b:types` script so each
   package's `tsc` finishes before the next dependent one starts.
3. Adding `libs/**/*` to each package's `tsconfig.json` `include`
   shifted tsc's emitted declaration tree under `types/src/...`,
   stranding the package.json `"types": "types/index.d.ts"` pointer.
   Revert the include addition; keep the same IDE benefit by
   shipping a tiny `libs/global.d.ts` per package that declares the
   `*.gsp` module shape locally — sibling to `libs/index.ts`, so the
   language server picks it up when editing libs files directly. Drop
   the now-redundant `*.gsp` declaration from each `src/global.d.ts`.

Verified: `pnpm clean && pnpm b:all` succeeds end-to-end on a fresh
workspace, including 21 .gsp products precompiled and all package
types emitted at the package.json-advertised paths.
`fix(shader-compiler): emit triple-slash reference in libs/index.ts`
adds `/// <reference path="./global.d.ts" />` to auto-generated
indices when a sibling `libs/global.d.ts` exists, so opening these
loose files in the IDE no longer squiggles `*.gsp` imports as missing
type declarations. Re-run precompile to refresh the eight package
indices accordingly.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (4)
packages/custom-material/libs/advanced-shader/eye/Eye.gsp (1)

1-1: ⚠️ Potential issue | 🔴 Critical

SurfaceData still misses f0, so this shader will not compile.

The fragment shader assigns surfaceData.f0 = 0.04, but the generated SurfaceData struct has no f0 field. Please add float f0; in the upstream Eye forward-pass template/include and regenerate packages/custom-material/libs/advanced-shader/eye/Eye.gsp.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/advanced-shader/eye/Eye.gsp` at line 1, The
SurfaceData struct used in the fragment shader is missing the float f0 field
referenced by the fragment code (surfaceData.f0 = 0.04), causing compilation
errors; update the upstream Eye forward-pass template/include to add "float f0;"
to the SurfaceData definition (the struct named SurfaceData in the forward-pass
include) and then regenerate
packages/custom-material/libs/advanced-shader/eye/Eye.gsp so the generated
shader contains the new f0 member.
packages/custom-material/libs/advanced-shader/hair/Hair.gsp (1)

1-1: ⚠️ Potential issue | 🔴 Critical

Add f0 to SurfaceData in the source shader and regenerate this asset.

This generated fragment shader still writes surfaceData.f0 = 0.04, but the emitted SurfaceData struct does not declare float f0;. That is a hard compile failure for the Hair forward pass. Please fix the upstream advanced-shader template/include and regenerate packages/custom-material/libs/advanced-shader/hair/Hair.gsp rather than patching the generated file manually.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/advanced-shader/hair/Hair.gsp` at line 1, The
generated fragment shader assigns surfaceData.f0 but the SurfaceData struct in
the shader include/template is missing float f0; update the advanced-shader
source (the Material/BSDF include that defines the SurfaceData struct used by
getSurfaceData and surfaceShading) to add "float f0;" to the SurfaceData
declaration, then regenerate the Hair.gsp asset so the emitted fragment shader
and struct stay consistent (do not edit the generated Hair.gsp directly).
packages/geometry-sketch/libs/material/TBN.gsp (1)

1-1: ⚠️ Potential issue | 🔴 Critical

Remove duplicated camera_VPMat uniform in the vertex shader payload.

Line 1 still embeds two uniform mat4 camera_VPMat; declarations in the same vertex shader scope, which can fail shader compilation. Fix this in packages/geometry-sketch/src/material/TBN.shader (source-of-truth), then regenerate packages/geometry-sketch/libs/material/TBN.gsp.

Suggested fix (source shader)
- uniform mat4 camera_VPMat;
  uniform float u_lineScale;
  uniform mat4 u_worldMatrix;
#!/bin/bash
set -euo pipefail

echo "1) Count camera_VPMat declarations in generated GSP vertex instructions"
python3 <<'PY'
import json
from pathlib import Path

gsp = Path("packages/geometry-sketch/libs/material/TBN.gsp")
data = json.loads(gsp.read_text())
instr = data["subShaders"][0]["passes"][0]["vertexShaderInstructions"]

count = 0
for op in instr:
    if isinstance(op, list) and len(op) >= 2 and isinstance(op[1], str):
        count += op[1].count("uniform mat4 camera_VPMat;")

print("camera_VPMat declarations in vertex shader instructions:", count)
print("EXPECTED: 1")
PY

echo
echo "2) Locate declarations in source shader (if present)"
if [ -f packages/geometry-sketch/src/material/TBN.shader ]; then
  rg -n "uniform\\s+mat4\\s+camera_VPMat\\s*;" packages/geometry-sketch/src/material/TBN.shader || true
else
  echo "Source shader file not found at packages/geometry-sketch/src/material/TBN.shader"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/geometry-sketch/libs/material/TBN.gsp` at line 1, There are two
identical uniform declarations for camera_VPMat in the generated vertex shader;
remove the duplicate from the source shader so only one "uniform mat4
camera_VPMat;" is emitted. Edit the TBN.shader source to keep a single
camera_VPMat uniform (or guard it with a single-definition macro), then re-run
the shader generation to update the vertexShaderInstructions in TBN.gsp so the
final JSON contains exactly one camera_VPMat declaration.
rollup.config.mjs (1)

71-76: ⚠️ Potential issue | 🟠 Major

Stop sharing a mutable plugin array across packages.

plugins is a singleton here, but makeRollupConfig() later does plugins.push(replace(...)). That means the ES/CJS/./sources configs for earlier packages keep picking up later packages’ replace plugins, so __buildVersion resolution becomes order-dependent and can end up using the wrong package version. Build from a per-package copy instead.

Suggested change
-const plugins = [
+const basePlugins = [
   resolve({ extensions, preferBuiltins: true, mainFields }),
   // Transform-only — `.shader`/`.glsl`/`.gsp` files become string/JSON modules.
   // Each package owns its own `precompile` npm script that drives the CLI to
   // emit `.gsp` artifacts under `<pkg>/libs/`; rollup never runs precompile.
   shaderCompiler(),
   swc(
     defineRollupSwcOption({
       include: /\.[mc]?[jt]sx?$/,
@@
 function makeRollupConfig(pkg) {
+  const plugins = [
+    ...basePlugins,
+    replace({
+      preventAssignment: true,
+      __buildVersion: pkg.pkgJson.version
+    })
+  ];
+
   const externals = Object.keys(
     Object.assign({}, pkg.pkgJson.dependencies, pkg.pkgJson.peerDependencies, pkg.pkgJson.devDependencies)
   );
@@
-  plugins.push(
-    replace({
-      preventAssignment: true,
-      __buildVersion: pkg.pkgJson.version
-    })
-  );
-
   const umdConfig = pkg.pkgJson.umd;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup.config.mjs` around lines 71 - 76, The shared mutable plugins array
causes later calls to makeRollupConfig() to mutate the single `plugins` and leak
`replace(...)` into previously created configs; fix by creating a per-package
copy inside makeRollupConfig() (e.g., clone `plugins` to a local variable before
calling .push) so each config gets its own plugin list, and ensure
`replace(...)` (the `__buildVersion` resolution plugin) is only appended to that
local copy rather than the module-level `plugins` array.
🧹 Nitpick comments (1)
rollup.config.mjs (1)

46-60: Fail fast on workspace dependency cycles.

Line 48 silently returns on a cycle, which turns an invalid dependency graph into an arbitrary partial order. Since this sort is now the safeguard against cold-start build races, a future cycle will degrade back into opaque resolution failures instead of a clear error.

Suggested change
-  function visit(p) {
+  function visit(p, stack = []) {
     if (visited.has(p)) return;
-    if (visiting.has(p)) return; // skip cycles (shouldn't exist, but safe)
+    if (visiting.has(p)) {
+      throw new Error(`Workspace dependency cycle detected: ${[...stack, p.pkgJson.name].join(" -> ")}`);
+    }
     visiting.add(p);
     const allDeps = { ...(p.pkgJson.dependencies ?? {}), ...(p.pkgJson.peerDependencies ?? {}) };
     for (const dep of Object.keys(allDeps)) {
       const depPkg = byName.get(dep);
-      if (depPkg) visit(depPkg);
+      if (depPkg) visit(depPkg, [...stack, p.pkgJson.name]);
     }
     visiting.delete(p);
     visited.add(p);
     sorted.push(p);
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup.config.mjs` around lines 46 - 60, The visit function currently
silently returns when encountering a cycle (visiting.has(p)), which hides
workspace dependency cycles; instead detect the cycle in visit (when
visiting.has(p)) and throw a clear error describing the cycle and the involved
package (use p.name or p.pkgJson.name) so the caller fails fast; update visit
and any callers (rawPkgs.forEach(visit)) to let the thrown error propagate
rather than continuing, and include the visiting/visited sets or build a short
cycle path in the error message to aid debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/custom-material/libs/bake-pbr/BakePBR.gsp`:
- Line 1: The fragment generator produced a self-initializing local "vec2 uv =
uv;" inside getSurfaceData, shadowing the varying uv and leaving it undefined;
fix the generator so getSurfaceData uses the varying uv (or a properly passed-in
parameter) instead of declaring a local with the same name (inspect the code
path that emits getSurfaceData and the varying-to-local mapping), remove the
erroneous local declaration or rename it (e.g., use "vec2 uv_in" or reference
the existing varying "uv"), regenerate BakePBR.gsp so all texture lookups in
getSurfaceData use the correct UVs.

In `@packages/outline/libs/OutlineReplace.gsp`:
- Line 1: The vertex shader's void main() incorrectly uses "return v;" which
returns a value from a void function (see the main() function and the Varyings v
declaration); remove the returned expression so the function either ends without
a return or uses a bare "return;" for early exit. Update the shader template
that generates the vertex main (look for the sequence "void main() { Varyings v
;" and the trailing "return v;") to drop the value from the return, then
regenerate the .gsp output.

---

Duplicate comments:
In `@packages/custom-material/libs/advanced-shader/eye/Eye.gsp`:
- Line 1: The SurfaceData struct used in the fragment shader is missing the
float f0 field referenced by the fragment code (surfaceData.f0 = 0.04), causing
compilation errors; update the upstream Eye forward-pass template/include to add
"float f0;" to the SurfaceData definition (the struct named SurfaceData in the
forward-pass include) and then regenerate
packages/custom-material/libs/advanced-shader/eye/Eye.gsp so the generated
shader contains the new f0 member.

In `@packages/custom-material/libs/advanced-shader/hair/Hair.gsp`:
- Line 1: The generated fragment shader assigns surfaceData.f0 but the
SurfaceData struct in the shader include/template is missing float f0; update
the advanced-shader source (the Material/BSDF include that defines the
SurfaceData struct used by getSurfaceData and surfaceShading) to add "float f0;"
to the SurfaceData declaration, then regenerate the Hair.gsp asset so the
emitted fragment shader and struct stay consistent (do not edit the generated
Hair.gsp directly).

In `@packages/geometry-sketch/libs/material/TBN.gsp`:
- Line 1: There are two identical uniform declarations for camera_VPMat in the
generated vertex shader; remove the duplicate from the source shader so only one
"uniform mat4 camera_VPMat;" is emitted. Edit the TBN.shader source to keep a
single camera_VPMat uniform (or guard it with a single-definition macro), then
re-run the shader generation to update the vertexShaderInstructions in TBN.gsp
so the final JSON contains exactly one camera_VPMat declaration.

In `@rollup.config.mjs`:
- Around line 71-76: The shared mutable plugins array causes later calls to
makeRollupConfig() to mutate the single `plugins` and leak `replace(...)` into
previously created configs; fix by creating a per-package copy inside
makeRollupConfig() (e.g., clone `plugins` to a local variable before calling
.push) so each config gets its own plugin list, and ensure `replace(...)` (the
`__buildVersion` resolution plugin) is only appended to that local copy rather
than the module-level `plugins` array.

---

Nitpick comments:
In `@rollup.config.mjs`:
- Around line 46-60: The visit function currently silently returns when
encountering a cycle (visiting.has(p)), which hides workspace dependency cycles;
instead detect the cycle in visit (when visiting.has(p)) and throw a clear error
describing the cycle and the involved package (use p.name or p.pkgJson.name) so
the caller fails fast; update visit and any callers (rawPkgs.forEach(visit)) to
let the thrown error propagate rather than continuing, and include the
visiting/visited sets or build a short cycle path in the error message to aid
debugging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: abf61b10-cccf-4e49-a106-412ab02b9e3d

📥 Commits

Reviewing files that changed from the base of the PR and between 2aecdce and ed4c032.

📒 Files selected for processing (46)
  • package.json
  • packages/controls/libs/box-selection/BoxSelection.gsp
  • packages/controls/libs/global.d.ts
  • packages/controls/libs/index.ts
  • packages/controls/src/global.d.ts
  • packages/custom-material/libs/advanced-shader/eye/Eye.gsp
  • packages/custom-material/libs/advanced-shader/hair/Hair.gsp
  • packages/custom-material/libs/advanced-shader/sss/SSS.gsp
  • packages/custom-material/libs/bake-pbr/BakePBR.gsp
  • packages/custom-material/libs/global.d.ts
  • packages/custom-material/libs/grid/Grid.gsp
  • packages/custom-material/libs/index.ts
  • packages/custom-material/libs/plain-color/PlainColor.gsp
  • packages/custom-material/libs/water/Water.gsp
  • packages/custom-material/libs/water/WaterFall.gsp
  • packages/custom-material/libs/water/WaterRipple.gsp
  • packages/framebuffer-picker/libs/FramebufferPickerColor.gsp
  • packages/framebuffer-picker/libs/global.d.ts
  • packages/framebuffer-picker/libs/index.ts
  • packages/framebuffer-picker/src/global.d.ts
  • packages/framebuffer-picker/tsconfig.json
  • packages/geometry-sketch/libs/global.d.ts
  • packages/geometry-sketch/libs/index.ts
  • packages/geometry-sketch/libs/material/TBN.gsp
  • packages/geometry-sketch/libs/material/Wireframe.gsp
  • packages/geometry-sketch/src/global.d.ts
  • packages/gizmo/libs/global.d.ts
  • packages/gizmo/libs/icon/Icon.gsp
  • packages/gizmo/libs/index.ts
  • packages/gizmo/src/global.d.ts
  • packages/gizmo/tsconfig.json
  • packages/lines/libs/global.d.ts
  • packages/lines/libs/index.ts
  • packages/lines/src/global.d.ts
  • packages/outline/libs/OutlinePostprocess.gsp
  • packages/outline/libs/OutlineReplace.gsp
  • packages/outline/libs/global.d.ts
  • packages/outline/libs/index.ts
  • packages/outline/src/global.d.ts
  • packages/outline/tsconfig.json
  • packages/skeleton-viewer/libs/SkeletonViewer.gsp
  • packages/skeleton-viewer/libs/global.d.ts
  • packages/skeleton-viewer/libs/index.ts
  • packages/skeleton-viewer/src/global.d.ts
  • packages/skeleton-viewer/tsconfig.json
  • rollup.config.mjs
✅ Files skipped from review due to trivial changes (24)
  • packages/geometry-sketch/src/global.d.ts
  • packages/skeleton-viewer/libs/global.d.ts
  • packages/custom-material/libs/global.d.ts
  • packages/outline/tsconfig.json
  • packages/skeleton-viewer/tsconfig.json
  • packages/gizmo/tsconfig.json
  • packages/framebuffer-picker/libs/global.d.ts
  • packages/controls/libs/global.d.ts
  • packages/framebuffer-picker/tsconfig.json
  • packages/lines/src/global.d.ts
  • packages/geometry-sketch/libs/global.d.ts
  • packages/gizmo/libs/global.d.ts
  • packages/gizmo/libs/index.ts
  • packages/controls/libs/index.ts
  • packages/lines/libs/index.ts
  • packages/outline/src/global.d.ts
  • packages/outline/libs/global.d.ts
  • packages/skeleton-viewer/libs/index.ts
  • packages/framebuffer-picker/libs/index.ts
  • packages/outline/libs/index.ts
  • packages/custom-material/libs/water/Water.gsp
  • packages/custom-material/libs/index.ts
  • packages/lines/libs/global.d.ts
  • packages/geometry-sketch/libs/index.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/skeleton-viewer/src/global.d.ts
  • packages/geometry-sketch/libs/material/Wireframe.gsp
  • packages/controls/libs/box-selection/BoxSelection.gsp
  • packages/gizmo/libs/icon/Icon.gsp
  • packages/framebuffer-picker/libs/FramebufferPickerColor.gsp
  • packages/skeleton-viewer/libs/SkeletonViewer.gsp
  • packages/outline/libs/OutlinePostprocess.gsp
  • packages/custom-material/libs/grid/Grid.gsp
  • packages/custom-material/libs/water/WaterFall.gsp
  • packages/framebuffer-picker/src/global.d.ts
  • packages/custom-material/libs/advanced-shader/sss/SSS.gsp
  • packages/custom-material/libs/water/WaterRipple.gsp
  • package.json

@@ -0,0 +1 @@
{"name":"bake-pbr","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Utility/ShadowMap/Default/ShadowCaster","isUsePass":true,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}}},{"name":"Utility/DepthOnly/Default/DepthOnly","isUsePass":true,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}}},{"name":"Forward Pass","isUsePass":false,"tags":{"pipelineStage":"Forward"},"renderStates":{"constantMap":{},"variableMap":{"0":"blendEnabled","3":"sourceColorBlendFactor","4":"sourceAlphaBlendFactor","5":"destinationColorBlendFactor","6":"destinationAlphaBlendFactor","11":"depthWriteEnabled","25":"rasterStateCullMode","28":"renderQueueType"}},"vertexShaderInstructions":[[0,"\n"],[2,"FORWARD_PASS_PBR_INCLUDED",708],[0,"\n\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",34],[0,"\n\n"],[7,"COMMON_INCLUDED"],[0,"\n\n"],[8,"PI","3.14159265359"],[0,"\n\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n\n"],[8,"EPSILON","1e-6"],[0,"\n\n"],[8,"LOG2","1.442695"],[0,"\n\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",28],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,32],[0,"\nmat2 inverseMat ( mat2 m ) { return mat2 ( m[1][1] , - m[0][1] , - m[1][0] , m[0][0] ) / ( m[0][0] * m[1][1] - m[0][1] * m[1][0] ) ; }\nmat3 inverseMat ( mat3 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] ;\nfloat a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] ;\nfloat a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] ;\nfloat b01 = a22 * a11 - a12 * a21 ;\nfloat b11 = - a22 * a10 + a12 * a20 ;\nfloat b21 = a21 * a10 - a11 * a20 ;\nfloat det = a00 * b01 + a01 * b11 + a02 * b21 ;\nreturn mat3 ( b01 , ( - a22 * a01 + a02 * a21 ) , ( a12 * a01 - a02 * a11 ) , b11 , ( a22 * a00 - a02 * a20 ) , ( - a12 * a00 + a02 * a10 ) , b21 , ( - a21 * a00 + a01 * a20 ) , ( a11 * a00 - a01 * a10 ) ) / det ; }\nmat4 inverseMat ( mat4 m ) { float a00 = m[0][0] , a01 = m[0][1] , a02 = m[0][2] , a03 = m[0][3] , a10 = m[1][0] , a11 = m[1][1] , a12 = m[1][2] , a13 = m[1][3] , a20 = m[2][0] , a21 = m[2][1] , a22 = m[2][2] , a23 = m[2][3] , a30 = m[3][0] , a31 = m[3][1] , a32 = m[3][2] , a33 = m[3][3] , b00 = a00 * a11 - a01 * a10 , b01 = a00 * a12 - a02 * a10 , b02 = a00 * a13 - a03 * a10 , b03 = a01 * a12 - a02 * a11 , b04 = a01 * a13 - a03 * a11 , b05 = a02 * a13 - a03 * a12 , b06 = a20 * a31 - a21 * a30 , b07 = a20 * a32 - a22 * a30 , b08 = a20 * a33 - a23 * a30 , b09 = a21 * a32 - a22 * a31 , b10 = a21 * a33 - a23 * a31 , b11 = a22 * a33 - a23 * a32 , det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06 ;\nreturn mat4 ( a11 * b11 - a12 * b10 + a13 * b09 , a02 * b10 - a01 * b11 - a03 * b09 , a31 * b05 - a32 * b04 + a33 * b03 , a22 * b04 - a21 * b05 - a23 * b03 , a12 * b08 - a10 * b11 - a13 * b07 , a00 * b11 - a02 * b08 + a03 * b07 , a32 * b02 - a30 * b05 - a33 * b01 , a20 * b05 - a22 * b02 + a23 * b01 , a10 * b10 - a11 * b08 + a13 * b06 , a01 * b08 - a00 * b10 - a03 * b06 , a30 * b04 - a31 * b02 + a33 * b00 , a21 * b02 - a20 * b04 - a23 * b00 , a11 * b07 - a10 * b09 - a12 * b06 , a00 * b09 - a01 * b07 + a02 * b06 , a31 * b01 - a30 * b03 - a32 * b00 , a20 * b03 - a21 * b01 + a22 * b00 ) / det ; }\n\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",44],[0,"\n\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,42],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",50],[0,"\n\n"],[7,"TRANSFORM_INCLUDED"],[0,"\nuniform mat4 renderer_ModelMat;\nuniform mat4 renderer_MVMat;\nuniform mat4 renderer_MVPMat;\nuniform mat4 renderer_NormalMat;\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",108],[0,"\n\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",82],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",80],[0,"attribute vec3 POSITION_BS0;\nattribute vec3 POSITION_BS1;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},62],[0,"attribute vec3 NORMAL_BS0;\nattribute vec3 NORMAL_BS1;\nattribute vec3 TANGENT_BS0;\nattribute vec3 TANGENT_BS1;\n\n"],[5,78],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},74],[0,"attribute vec3 POSITION_BS2;\nattribute vec3 POSITION_BS3;\n\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",68],[0,"attribute vec3 NORMAL_BS0;\nattribute vec3 NORMAL_BS1;\nattribute vec3 NORMAL_BS2;\nattribute vec3 NORMAL_BS3;\n\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",72],[0,"attribute vec3 TANGENT_BS0;\nattribute vec3 TANGENT_BS1;\nattribute vec3 TANGENT_BS2;\nattribute vec3 TANGENT_BS3;\n\n"],[6],[0,"\n"],[5,76],[0,"attribute vec3 POSITION_BS2;\nattribute vec3 POSITION_BS3;\nattribute vec3 POSITION_BS4;\nattribute vec3 POSITION_BS5;\nattribute vec3 POSITION_BS6;\nattribute vec3 POSITION_BS7;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",86],[0,"attribute vec2 TEXCOORD_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",90],[0,"attribute vec2 TEXCOORD_1;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",94],[0,"attribute vec4 JOINTS_0;\nattribute vec4 WEIGHTS_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",98],[0,"attribute vec4 COLOR_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",102],[0,"attribute vec3 NORMAL;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",106],[0,"attribute vec4 TANGENT;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",130],[0,"\n\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",128],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",118],[0,"\nuniform sampler2D renderer_JointSampler;\nuniform float renderer_JointCount;\nmat4 getJointMatrix ( sampler2D smp, float index ) { float base = index / renderer_JointCount ;\nfloat hf = 0.5 / renderer_JointCount ;\nfloat v = base + hf ;\nvec4 m0 = texture2D ( smp , vec2 ( 0.125 , v ) ) ;\nvec4 m1 = texture2D ( smp , vec2 ( 0.375 , v ) ) ;\nvec4 m2 = texture2D ( smp , vec2 ( 0.625 , v ) ) ;\nvec4 m3 = texture2D ( smp , vec2 ( 0.875 , v ) ) ;\nreturn mat4 ( m0 , m1 , m2 , m3 ) ; }\n\n"],[5,120],[0,"\nuniform mat4 renderer_JointMatrix [ RENDERER_JOINTS_NUM ];\n\n"],[6],[0,"\nmat4 getSkinMatrix ( ) { \n"],[1,"RENDERER_USE_JOINT_TEXTURE",124],[0," mat4 skinMatrix = WEIGHTS_0.x * getJointMatrix(renderer_JointSampler, JOINTS_0.x) + WEIGHTS_0.y * getJointMatrix(renderer_JointSampler, JOINTS_0.y) + WEIGHTS_0.z * getJointMatrix(renderer_JointSampler, JOINTS_0.z) + WEIGHTS_0.w * getJointMatrix(renderer_JointSampler, JOINTS_0.w) ; \n"],[5,126],[0," mat4 skinMatrix = WEIGHTS_0.x * renderer_JointMatrix[int ( JOINTS_0.x )] + WEIGHTS_0.y * renderer_JointMatrix[int ( JOINTS_0.y )] + WEIGHTS_0.z * renderer_JointMatrix[int ( JOINTS_0.z )] + WEIGHTS_0.w * renderer_JointMatrix[int ( JOINTS_0.w )] ; \n"],[6],[0,"\nreturn skinMatrix ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"BLENDSHAPE_INCLUDED",208],[0,"\n\n"],[7,"BLENDSHAPE_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",206],[0,"\n\n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",140],[0,"\nuniform mediump sampler2DArray renderer_BlendShapeTexture;\nuniform ivec3 renderer_BlendShapeTextureInfo;\nuniform float renderer_BlendShapeWeights [ RENDERER_BLENDSHAPE_COUNT ];\nvec3 getBlendShapeVertexElement ( int blendShapeIndex, int vertexElementIndex ) { int y = vertexElementIndex / renderer_BlendShapeTextureInfo.y ;\nint x = vertexElementIndex - y * renderer_BlendShapeTextureInfo.y ;\nivec3 uv = ivec3 ( x , y , blendShapeIndex ) ;\nreturn ( texelFetch ( renderer_BlendShapeTexture , uv , 0 ) ).xyz ; }\n\n"],[5,154],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},144],[0,"\nuniform float renderer_BlendShapeWeights [ 2 ];\n\n"],[5,152],[0,"\n\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},148],[0,"\nuniform float renderer_BlendShapeWeights [ 4 ];\n\n"],[5,150],[0,"\nuniform float renderer_BlendShapeWeights [ 8 ];\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid calculateBlendShape ( inout vec4 position\n"],[1,"RENDERER_HAS_NORMAL",162],[0," , inout vec3 normal \n"],[1,"RENDERER_HAS_TANGENT",160],[0," , inout vec4 tangent \n"],[6],[0," \n"],[6],[0," ) { \n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",174],[0," int vertexOffset = gl_VertexID * renderer_BlendShapeTextureInfo.x ;\nfor ( int i = 0 ; i < RENDERER_BLENDSHAPE_COUNT ; i ++ ) { int vertexElementOffset = vertexOffset ;\nfloat weight = renderer_BlendShapeWeights[i] ;\nif ( weight != 0.0 ) { position.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"}},168],[0," vertexElementOffset += 1 ;\nnormal += getBlendShapeVertexElement(i, vertexElementOffset) * weight ; \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},172],[0," vertexElementOffset += 1 ;\ntangent.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight ; \n"],[6],[0," } } \n"],[5,204],[0," position.xyz += POSITION_BS0 * renderer_BlendShapeWeights[0] ;\nposition.xyz += POSITION_BS1 * renderer_BlendShapeWeights[1] ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},186],[0," \n"],[1,"RENDERER_HAS_NORMAL",180],[0," normal += NORMAL_BS0 * renderer_BlendShapeWeights[0] ;\nnormal += NORMAL_BS1 * renderer_BlendShapeWeights[1] ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_TANGENT",184],[0," tangent.xyz += TANGENT_BS0 * renderer_BlendShapeWeights[0] ;\ntangent.xyz += TANGENT_BS1 * renderer_BlendShapeWeights[1] ; \n"],[6],[0," \n"],[5,202],[0," \n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},198],[0," position.xyz += POSITION_BS2 * renderer_BlendShapeWeights[2] ;\nposition.xyz += POSITION_BS3 * renderer_BlendShapeWeights[3] ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_NORMAL"}},192],[0," normal += NORMAL_BS0 * renderer_BlendShapeWeights[0] ;\nnormal += NORMAL_BS1 * renderer_BlendShapeWeights[1] ;\nnormal += NORMAL_BS2 * renderer_BlendShapeWeights[2] ;\nnormal += NORMAL_BS3 * renderer_BlendShapeWeights[3] ; \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},196],[0," tangent.xyz += TANGENT_BS0 * renderer_BlendShapeWeights[0] ;\ntangent.xyz += TANGENT_BS1 * renderer_BlendShapeWeights[1] ;\ntangent.xyz += TANGENT_BS2 * renderer_BlendShapeWeights[2] ;\ntangent.xyz += TANGENT_BS3 * renderer_BlendShapeWeights[3] ; \n"],[6],[0," \n"],[5,200],[0," position.xyz += POSITION_BS2 * renderer_BlendShapeWeights[2] ;\nposition.xyz += POSITION_BS3 * renderer_BlendShapeWeights[3] ;\nposition.xyz += POSITION_BS4 * renderer_BlendShapeWeights[4] ;\nposition.xyz += POSITION_BS5 * renderer_BlendShapeWeights[5] ;\nposition.xyz += POSITION_BS6 * renderer_BlendShapeWeights[6] ;\nposition.xyz += POSITION_BS7 * renderer_BlendShapeWeights[7] ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"SHADOW_INCLUDED",288],[0,"\n\n"],[7,"SHADOW_INCLUDED"],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_SHADOW_TYPE"},"r":{"t":"def","m":"RENDERER_IS_RECEIVE_SHADOWS"}},218],[0,"\n\n"],[7,"NEED_CALCULATE_SHADOWS"],[0,"\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",246],[0,"\nuniform mat4 scene_ShadowMatrices [ SCENE_SHADOW_CASCADED_COUNT + 1 ];\nuniform vec4 scene_ShadowSplitSpheres [ 4 ];\nmediump int computeCascadeIndex ( vec3 positionWS ) { vec3 fromCenter0 = positionWS - scene_ShadowSplitSpheres[0].xyz ;\nvec3 fromCenter1 = positionWS - scene_ShadowSplitSpheres[1].xyz ;\nvec3 fromCenter2 = positionWS - scene_ShadowSplitSpheres[2].xyz ;\nvec3 fromCenter3 = positionWS - scene_ShadowSplitSpheres[3].xyz ;\nmediump vec4 comparison = vec4 ( ( dot ( fromCenter0 , fromCenter0 ) < scene_ShadowSplitSpheres[0].w ) , ( dot ( fromCenter1 , fromCenter1 ) < scene_ShadowSplitSpheres[1].w ) , ( dot ( fromCenter2 , fromCenter2 ) < scene_ShadowSplitSpheres[2].w ) , ( dot ( fromCenter3 , fromCenter3 ) < scene_ShadowSplitSpheres[3].w ) ) ;\ncomparison.yzw = clamp ( comparison.yzw - comparison.xyz , 0.0 , 1.0 ) ;\nmediump vec4 indexCoefficient = vec4 ( 4.0 , 3.0 , 2.0 , 1.0 ) ;\nmediump int index = 4 - int ( dot ( comparison , indexCoefficient ) ) ;\nreturn index ; }\nvec3 getShadowCoord ( vec3 positionWS ) { \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,224],[0," mediump int cascadeIndex = 0 ; \n"],[5,226],[0," mediump int cascadeIndex = computeCascadeIndex(positionWS) ; \n"],[6],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",230],[0," mat4 shadowMatrix = scene_ShadowMatrices[cascadeIndex] ; \n"],[5,244],[0," mat4 shadowMatrix ;\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",4,234],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else if ( cascadeIndex == 2 ) { shadowMatrix = scene_ShadowMatrices[2] ; } else if ( cascadeIndex == 3 ) { shadowMatrix = scene_ShadowMatrices[3] ; } else { shadowMatrix = scene_ShadowMatrices[4] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",2,238],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else { shadowMatrix = scene_ShadowMatrices[2] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,242],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else { shadowMatrix = scene_ShadowMatrices[1] ; } \n"],[6],[0," \n"],[6],[0,"\nvec4 shadowCoord = shadowMatrix * vec4 ( positionWS , 1.0 ) ;\nreturn shadowCoord.xyz ; }\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",286],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",256],[0,"\n\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureLod(textureName, coord3 , 0.0)"],[0,"\n\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2DShadow shadowMap"],[0,"\n\n"],[5,270],[0,"\n\n"],[1,"ENGINE_NO_DEPTH_TEXTURE",262],[0,"\n\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[5,266],[0,"\n\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[6],[0,"\n\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2D shadowMap"],[0,"\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",2,274],[0,"\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",3,284],[0,"\n\n"],[2,"SHADOW_SAMPLE_TENT_INCLUDED",282],[0,"\n\n"],[7,"SHADOW_SAMPLE_TENT_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",318],[0,"\n\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",296],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",300],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,304],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",312],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",310],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},316],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"varying vec4 positionCS;\n\n\n"],[6],[0,"\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",472],[0,"\n\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",328],[0,"\n\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",334],[0,"\n\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",340],[0,"\n\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",346],[0,"\n\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",352],[0,"\n\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",410],[0,"\n\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",366],[0,"\n\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",364],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},376],[0,"\n\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",380],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",384],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",388],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",392],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",396],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",400],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",404],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",408],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",452],[0,"\n\n"],[7,"LIGHT_INCLUDED"],[0,"\n\n"],[2,"GRAPHICS_API_WEBGL2",418],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",426],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",424],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",434],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",432],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",442],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",440],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SH",446],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",450],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",458],[0,"\n\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",462],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",466],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",470],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",508],[0,"\n\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",482],[0,"\n\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",488],[0,"\n\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",494],[0,"\n\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",500],[0,"\n\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",506],[0,"\n\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",574],[0,"\n\n"],[7,"VERTEX_INCLUDE"],[0,"\nstruct VertexInputs { vec4 positionOS ; vec3 positionWS ; \n"],[3,"SCENE_FOG_MODE","!=",0,516],[0," vec3 positionVS ; \n"],[6],[0," \n"],[1,"RENDERER_HAS_NORMAL",524],[0," vec3 normalWS ; \n"],[1,"RENDERER_HAS_TANGENT",522],[0," vec3 tangentWS ; vec3 bitangentWS ; \n"],[6],[0," \n"],[6],[0," } ;\nuniform vec4 material_TilingOffset;\nvec2 getUV0 ( ) { vec2 uv0 = vec2 ( 0 ) ;\n\n"],[1,"RENDERER_HAS_UV",528],[0," uv0 = TEXCOORD_0 ; \n"],[6],[0,"\nreturn uv0 * material_TilingOffset.xy + material_TilingOffset.zw ; }\nVertexInputs getVertexInputs ( ) { VertexInputs inputs ;\nvec4 position = vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",536],[0," vec3 normal = vec3 ( NORMAL ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",534],[0," vec4 tangent = vec4 ( TANGENT ) ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",548],[0," calculateBlendShape(position\n"],[1,"RENDERER_HAS_NORMAL",546],[0," , normal \n"],[1,"RENDERER_HAS_TANGENT",544],[0," , tangent \n"],[6],[0," \n"],[6],[0,") ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",560],[0," mat4 skinMatrix = getSkinMatrix() ;\nposition = skinMatrix * position ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},558],[0," mat3 skinNormalMatrix = INVERSE_MAT(mat3 ( skinMatrix )) ;\nnormal = normal * skinNormalMatrix ;\n\n"],[1,"RENDERER_HAS_TANGENT",556],[0," tangent.xyz = tangent.xyz * skinNormalMatrix ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"not","c":{"t":"def","m":"MATERIAL_OMIT_NORMAL"}}},568],[0," inputs.normalWS = normalize ( mat3 ( renderer_NormalMat ) * normal ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",566],[0," vec3 tangentWS = normalize ( mat3 ( renderer_NormalMat ) * tangent.xyz ) ;\nvec3 bitangentWS = cross ( inputs.normalWS , tangentWS ) * tangent.w ;\ninputs.tangentWS = tangentWS ;\ninputs.bitangentWS = bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\ninputs.positionOS = position ;\nvec4 positionWS = renderer_ModelMat * position ;\ninputs.positionWS = positionWS.xyz / positionWS.w ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,572],[0," vec4 positionVS = renderer_MVMat * position ;\ninputs.positionVS = positionVS.xyz / positionVS.w ; \n"],[6],[0,"\nreturn inputs ; }\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",682],[0,"\n\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",584],[0,"\n\n"],[7,"NORMAL_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",588],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",592],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",608],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",598],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",602],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",606],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",616],[0,"\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",614],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",628],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",622],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",626],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",640],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",634],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",638],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",656],[0,"\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",646],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",654],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",652],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",660],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",664],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",668],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",672],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",676],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",680],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid PBRVertex( ) { \nuv = getUV0() ;\n\n"],[1,"RENDERER_HAS_UV1",686],[0," uv1 = TEXCOORD_1 ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",690],[0," vertexColor = COLOR_0 ; \n"],[6],[0,"\nVertexInputs vertexInputs = getVertexInputs() ;\npositionWS = vertexInputs.positionWS ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,694],[0," positionVS = vertexInputs.positionVS ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",702],[0," normalWS = vertexInputs.normalWS ;\n\n"],[1,"RENDERER_HAS_TANGENT",700],[0," tangentWS = vertexInputs.tangentWS ;\nbitangentWS = vertexInputs.bitangentWS ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},706],[0," shadowCoord = getShadowCoord(vertexInputs.positionWS) ; \n"],[6],[0,"\ngl_Position = renderer_MVPMat * vertexInputs.positionOS ;\npositionCS = gl_Position ;\n }\n\n"],[6],[0,"\n\n"],[1,"LIGHTMAP_TEXTURE",712],[0,"\n\n"],[6],[0,"\nvoid main() { PBRVertex(); }"]],"fragmentShaderInstructions":[[0,"\n"],[2,"FORWARD_PASS_PBR_INCLUDED",868],[0,"\n\n"],[7,"FORWARD_PASS_PBR_INCLUDED"],[0,"\n\n"],[2,"COMMON_INCLUDED",38],[0,"\n\n"],[7,"COMMON_INCLUDED"],[0,"\n\n"],[8,"PI","3.14159265359"],[0,"\n\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n\n"],[8,"EPSILON","1e-6"],[0,"\n\n"],[8,"LOG2","1.442695"],[0,"\n\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\nfloat pow2 ( float x ) { return x * x ; }\nfloat sRGBToLinear ( float value ) { float linearRGBLo = value / 12.92 ;\nfloat linearRGBHi = pow ( ( value + 0.055 ) / 1.055 , 2.4 ) ;\nfloat linearRGB = ( value <= 0.04045 ) ? linearRGBLo : linearRGBHi ;\nreturn linearRGB ; }\nvec4 sRGBToLinear ( vec4 value ) { return vec4 ( sRGBToLinear(value.r) , sRGBToLinear(value.g) , sRGBToLinear(value.b) , value.a ) ; }\nvec4 texture2DSRGB ( sampler2D tex, vec2 uv ) { vec4 color = texture2D ( tex , uv ) ;\n\n"],[1,"ENGINE_NO_SRGB",26],[0," color = sRGBToLinear(color) ; \n"],[6],[0,"\nreturn color ; }\nuniform vec4 camera_ProjectionParams;\n\n"],[1,"GRAPHICS_API_WEBGL2",32],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,36],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"FOG_INCLUDED",58],[0,"\n\n"],[7,"FOG_INCLUDED"],[0,"\n\n"],[3,"SCENE_FOG_MODE","!=",0,56],[0,"\nuniform vec4 scene_FogColor;\nuniform vec4 scene_FogParams;\nvec4 fog ( vec4 color, vec3 positionVS ) { float fogDepth = length ( positionVS ) ;\n\n"],[3,"SCENE_FOG_MODE","==",1,48],[0," float fogIntensity = clamp ( fogDepth * scene_FogParams.x + scene_FogParams.y , 0.0 , 1.0 ) ; \n"],[5,54],[3,"SCENE_FOG_MODE","==",2,51],[0," float fogIntensity = clamp ( exp2 ( - fogDepth * scene_FogParams.z ) , 0.0 , 1.0 ) ; \n"],[5,54],[3,"SCENE_FOG_MODE","==",3,54],[0," float factor = fogDepth * scene_FogParams.w ;\nfloat fogIntensity = clamp ( exp2 ( - factor * factor ) , 0.0 , 1.0 ) ; \n"],[6],[0,"\ncolor.rgb = mix ( scene_FogColor.rgb , color.rgb , fogIntensity ) ;\nreturn color ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",64],[0,"\n\n"],[7,"TRANSFORM_INCLUDED"],[0,"\nuniform mat4 camera_ViewMat;\nuniform mat4 camera_ProjMat;\nuniform vec3 camera_Position;\nuniform vec3 camera_Forward;\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",70],[0,"\n\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",86],[0,"\n\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",84],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",80],[0,"\n\n"],[5,82],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"BLENDSHAPE_INCLUDED",114],[0,"\n\n"],[7,"BLENDSHAPE_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",112],[0,"\n\n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",96],[0,"\n\n"],[5,110],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},100],[0,"\n\n"],[5,108],[0,"\n\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},104],[0,"\n\n"],[5,106],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"SHADOW_INCLUDED",206],[0,"\n\n"],[7,"SHADOW_INCLUDED"],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_SHADOW_TYPE"},"r":{"t":"def","m":"RENDERER_IS_RECEIVE_SHADOWS"}},124],[0,"\n\n"],[7,"NEED_CALCULATE_SHADOWS"],[0,"\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",152],[0,"\nuniform mat4 scene_ShadowMatrices [ SCENE_SHADOW_CASCADED_COUNT + 1 ];\nuniform vec4 scene_ShadowSplitSpheres [ 4 ];\nmediump int computeCascadeIndex ( vec3 positionWS ) { vec3 fromCenter0 = positionWS - scene_ShadowSplitSpheres[0].xyz ;\nvec3 fromCenter1 = positionWS - scene_ShadowSplitSpheres[1].xyz ;\nvec3 fromCenter2 = positionWS - scene_ShadowSplitSpheres[2].xyz ;\nvec3 fromCenter3 = positionWS - scene_ShadowSplitSpheres[3].xyz ;\nmediump vec4 comparison = vec4 ( ( dot ( fromCenter0 , fromCenter0 ) < scene_ShadowSplitSpheres[0].w ) , ( dot ( fromCenter1 , fromCenter1 ) < scene_ShadowSplitSpheres[1].w ) , ( dot ( fromCenter2 , fromCenter2 ) < scene_ShadowSplitSpheres[2].w ) , ( dot ( fromCenter3 , fromCenter3 ) < scene_ShadowSplitSpheres[3].w ) ) ;\ncomparison.yzw = clamp ( comparison.yzw - comparison.xyz , 0.0 , 1.0 ) ;\nmediump vec4 indexCoefficient = vec4 ( 4.0 , 3.0 , 2.0 , 1.0 ) ;\nmediump int index = 4 - int ( dot ( comparison , indexCoefficient ) ) ;\nreturn index ; }\nvec3 getShadowCoord ( vec3 positionWS ) { \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,130],[0," mediump int cascadeIndex = 0 ; \n"],[5,132],[0," mediump int cascadeIndex = computeCascadeIndex(positionWS) ; \n"],[6],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",136],[0," mat4 shadowMatrix = scene_ShadowMatrices[cascadeIndex] ; \n"],[5,150],[0," mat4 shadowMatrix ;\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",4,140],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else if ( cascadeIndex == 2 ) { shadowMatrix = scene_ShadowMatrices[2] ; } else if ( cascadeIndex == 3 ) { shadowMatrix = scene_ShadowMatrices[3] ; } else { shadowMatrix = scene_ShadowMatrices[4] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",2,144],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else if ( cascadeIndex == 1 ) { shadowMatrix = scene_ShadowMatrices[1] ; } else { shadowMatrix = scene_ShadowMatrices[2] ; } \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,148],[0," if ( cascadeIndex == 0 ) { shadowMatrix = scene_ShadowMatrices[0] ; } else { shadowMatrix = scene_ShadowMatrices[1] ; } \n"],[6],[0," \n"],[6],[0,"\nvec4 shadowCoord = shadowMatrix * vec4 ( positionWS , 1.0 ) ;\nreturn shadowCoord.xyz ; }\n\n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",204],[0,"\nuniform vec4 scene_ShadowInfo;\nuniform vec4 scene_ShadowMapSize;\n\n"],[1,"GRAPHICS_API_WEBGL2",162],[0,"\nuniform mediump sampler2DShadow scene_ShadowMap;\n\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureLod(textureName, coord3 , 0.0)"],[0,"\n\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2DShadow shadowMap"],[0,"\n\n"],[5,176],[0,"\nuniform sampler2D scene_ShadowMap;\n\n"],[1,"ENGINE_NO_DEPTH_TEXTURE",168],[0,"\nconst vec4 bitShift = vec4 ( 1.0 , 1.0 / 256.0 , 1.0 / ( 256.0 * 256.0 ) , 1.0 / ( 256.0 * 256.0 * 256.0 ) );\nfloat textureShadowMapDowngrade ( sampler2D scene_ShadowMap, vec3 shadowCoord ) { vec4 rgbaDepth = texture2D ( scene_ShadowMap , shadowCoord.xy ) ;\nfloat unpackDepth = dot ( rgbaDepth , bitShift ) ;\nreturn unpackDepth < shadowCoord.z ? 0.0 : 1.0 ; }\n\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[5,172],[0,"\nfloat textureShadowMapDowngrade ( sampler2D scene_ShadowMap, vec3 shadowCoord ) { float depth = texture2D ( scene_ShadowMap , shadowCoord.xy ).r ;\nreturn depth < shadowCoord.z ? 0.0 : 1.0 ; }\n\n"],[9,"SAMPLE_TEXTURE2D_SHADOW",["textureName","coord3"],"textureShadowMapDowngrade(textureName, coord3)"],[0,"\n\n"],[6],[0,"\n\n"],[9,"TEXTURE2D_SHADOW_PARAM",["shadowMap"],"mediump sampler2D shadowMap"],[0,"\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",2,180],[0,"\nfloat sampleShadowMapFiltered4 ( TEXTURE2D_SHADOW_PARAM(shadowMap), vec3 shadowCoord, vec4 shadowMapSize ) { float attenuation ;\nvec4 attenuation4 ;\nvec2 offset = shadowMapSize.xy / 2.0 ;\nvec3 shadowCoord0 = shadowCoord + vec3 ( - offset , 0.0 ) ;\nvec3 shadowCoord1 = shadowCoord + vec3 ( offset.x , - offset.y , 0.0 ) ;\nvec3 shadowCoord2 = shadowCoord + vec3 ( - offset.x , offset.y , 0.0 ) ;\nvec3 shadowCoord3 = shadowCoord + vec3 ( offset , 0.0 ) ;\nattenuation4.x = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord0) ;\nattenuation4.y = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord1) ;\nattenuation4.z = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord2) ;\nattenuation4.w = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord3) ;\nattenuation = dot ( attenuation4 , vec4 ( 0.25 ) ) ;\nreturn attenuation ; }\n\n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",3,190],[0,"\n\n"],[2,"SHADOW_SAMPLE_TENT_INCLUDED",188],[0,"\n\n"],[7,"SHADOW_SAMPLE_TENT_INCLUDED"],[0,"\nfloat sampleShadowGetIRTriangleTexelArea ( float triangleHeight ) { return triangleHeight - 0.5 ; }\nvoid sampleShadowGetTexelAreasTent3x3 ( float offset, out vec4 computedArea, out vec4 computedAreaUncut ) { float a = offset + 0.5 ;\nfloat offsetSquaredHalved = a * a * 0.5 ;\ncomputedAreaUncut.x = computedArea.x = offsetSquaredHalved - offset ;\ncomputedAreaUncut.w = computedArea.w = offsetSquaredHalved ;\ncomputedAreaUncut.y = sampleShadowGetIRTriangleTexelArea(1.5 - offset) ;\nfloat clampedOffsetLeft = min ( offset , 0.0 ) ;\nfloat areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft ;\ncomputedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle ;\ncomputedAreaUncut.z = sampleShadowGetIRTriangleTexelArea(1.5 + offset) ;\nfloat clampedOffsetRight = max ( offset , 0.0 ) ;\nfloat areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight ;\ncomputedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle ; }\nvoid sampleShadowGetTexelWeightsTent5x5 ( float offset, out vec3 texelsWeightsA, out vec3 texelsWeightsB ) { vec4 areaFrom3texelTriangle ;\nvec4 areaUncutFrom3texelTriangle ;\nsampleShadowGetTexelAreasTent3x3(offset, areaFrom3texelTriangle, areaUncutFrom3texelTriangle) ;\ntexelsWeightsA.x = 0.16 * ( areaFrom3texelTriangle.x ) ;\ntexelsWeightsA.y = 0.16 * ( areaUncutFrom3texelTriangle.y ) ;\ntexelsWeightsA.z = 0.16 * ( areaFrom3texelTriangle.y + 1.0 ) ;\ntexelsWeightsB.x = 0.16 * ( areaFrom3texelTriangle.z + 1.0 ) ;\ntexelsWeightsB.y = 0.16 * ( areaUncutFrom3texelTriangle.z ) ;\ntexelsWeightsB.z = 0.16 * ( areaFrom3texelTriangle.w ) ; }\nvoid sampleShadowComputeSamplesTent5x5 ( vec4 shadowMapTextureTexelSize, vec2 coord, out float fetchesWeights [ 9 ], out vec2 fetchesUV [ 9 ] ) { vec2 tentCenterInTexelSpace = coord.xy * shadowMapTextureTexelSize.zw ;\nvec2 centerOfFetchesInTexelSpace = floor ( tentCenterInTexelSpace + 0.5 ) ;\nvec2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace ;\nvec3 texelsWeightsUA , texelsWeightsUB ;\nvec3 texelsWeightsVA , texelsWeightsVB ;\nsampleShadowGetTexelWeightsTent5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsUA, texelsWeightsUB) ;\nsampleShadowGetTexelWeightsTent5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsVA, texelsWeightsVB) ;\nvec3 fetchesWeightsU = vec3 ( texelsWeightsUA.xz , texelsWeightsUB.y ) + vec3 ( texelsWeightsUA.y , texelsWeightsUB.xz ) ;\nvec3 fetchesWeightsV = vec3 ( texelsWeightsVA.xz , texelsWeightsVB.y ) + vec3 ( texelsWeightsVA.y , texelsWeightsVB.xz ) ;\nvec3 fetchesOffsetsU = vec3 ( texelsWeightsUA.y , texelsWeightsUB.xz ) / fetchesWeightsU.xyz + vec3 ( - 2.5 , - 0.5 , 1.5 ) ;\nvec3 fetchesOffsetsV = vec3 ( texelsWeightsVA.y , texelsWeightsVB.xz ) / fetchesWeightsV.xyz + vec3 ( - 2.5 , - 0.5 , 1.5 ) ;\nfetchesOffsetsU *= shadowMapTextureTexelSize.xxx ;\nfetchesOffsetsV *= shadowMapTextureTexelSize.yyy ;\nvec2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTextureTexelSize.xy ;\nfetchesUV[0] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.x , fetchesOffsetsV.x ) ;\nfetchesUV[1] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.y , fetchesOffsetsV.x ) ;\nfetchesUV[2] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.z , fetchesOffsetsV.x ) ;\nfetchesUV[3] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.x , fetchesOffsetsV.y ) ;\nfetchesUV[4] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.y , fetchesOffsetsV.y ) ;\nfetchesUV[5] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.z , fetchesOffsetsV.y ) ;\nfetchesUV[6] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.x , fetchesOffsetsV.z ) ;\nfetchesUV[7] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.y , fetchesOffsetsV.z ) ;\nfetchesUV[8] = bilinearFetchOrigin + vec2 ( fetchesOffsetsU.z , fetchesOffsetsV.z ) ;\nfetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x ;\nfetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x ;\nfetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x ;\nfetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y ;\nfetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y ;\nfetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y ;\nfetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z ;\nfetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z ;\nfetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z ; }\n\n"],[6],[0,"\nfloat sampleShadowMapFiltered9 ( TEXTURE2D_SHADOW_PARAM(shadowMap), vec3 shadowCoord, vec4 shadowmapSize ) { float attenuation ;\nfloat fetchesWeights [ 9 ] ;\nvec2 fetchesUV [ 9 ] ;\nsampleShadowComputeSamplesTent5x5(shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV) ;\nattenuation = fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[0].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[1].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[2].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[3].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[4].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[5].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[6].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[7].xy , shadowCoord.z )) ;\nattenuation += fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3 ( fetchesUV[8].xy , shadowCoord.z )) ;\nreturn attenuation ; }\n\n"],[6],[0,"\nfloat getShadowFade ( vec3 positionWS ) { vec3 camToPixel = positionWS - camera_Position ;\nfloat distanceCamToPixel2 = dot ( camToPixel , camToPixel ) ;\nreturn saturate(distanceCamToPixel2 * scene_ShadowInfo.z + scene_ShadowInfo.w) ; }\nfloat sampleShadowMap ( vec3 positionWS, vec3 shadowCoord ) { float attenuation = 1.0 ;\nif ( shadowCoord.z > 0.0 && shadowCoord.z < 1.0 ) { \n"],[3,"SCENE_SHADOW_TYPE","==",1,194],[0," attenuation = SAMPLE_TEXTURE2D_SHADOW(scene_ShadowMap, shadowCoord) ; \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",2,198],[0," attenuation = sampleShadowMapFiltered4(scene_ShadowMap, shadowCoord, scene_ShadowMapSize) ; \n"],[6],[0,"\n\n"],[3,"SCENE_SHADOW_TYPE","==",3,202],[0," attenuation = sampleShadowMapFiltered9(scene_ShadowMap, shadowCoord, scene_ShadowMapSize) ; \n"],[6],[0,"\nfloat shadowFade = getShadowFade(positionWS) ;\nattenuation = mix ( 1.0 , mix ( attenuation , 1.0 , shadowFade ) , scene_ShadowInfo.x ) ; }\nreturn attenuation ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"VARYINGS_PBR_INCLUDED",236],[0,"\n\n"],[7,"VARYINGS_PBR_INCLUDED"],[0,"\nvarying vec2 uv;\n\n"],[1,"RENDERER_HAS_UV1",214],[0,"varying vec2 uv1;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",218],[0,"varying vec4 vertexColor;\n\n"],[6],[0,"varying vec3 positionWS;\n\n"],[3,"SCENE_FOG_MODE","!=",0,222],[0,"varying vec3 positionVS;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",230],[0,"varying vec3 normalWS;\n\n"],[1,"RENDERER_HAS_TANGENT",228],[0,"varying vec3 tangentWS;\nvarying vec3 bitangentWS;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[4,{"t":"and","l":{"t":"def","m":"NEED_CALCULATE_SHADOWS"},"r":{"t":"cmp","m":"SCENE_SHADOW_CASCADED_COUNT","op":"==","v":1}},234],[0,"varying vec3 shadowCoord;\n\n"],[6],[0,"varying vec4 positionCS;\n\n\n"],[6],[0,"\n\n"],[2,"LIGHT_DIRECT_PBR_INCLUDED",533],[0,"\n\n"],[7,"LIGHT_DIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_SURFACE_SHADING",246],[0,"\n\n"],[8,"FUNCTION_SURFACE_SHADING","surfaceShading"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_LOBE",252],[0,"\n\n"],[8,"FUNCTION_DIFFUSE_LOBE","diffuseLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_LOBE",258],[0,"\n\n"],[8,"FUNCTION_SPECULAR_LOBE","specularLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_LOBE",264],[0,"\n\n"],[8,"FUNCTION_CLEAR_COAT_LOBE","clearCoatLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_LOBE",270],[0,"\n\n"],[8,"FUNCTION_SHEEN_LOBE","sheenLobe"],[0,"\n\n"],[6],[0,"\n\n"],[2,"BSDF_INCLUDED",423],[0,"\n\n"],[7,"BSDF_INCLUDED"],[0,"\n\n"],[2,"REFRACTION_INCLUDED",284],[0,"\n\n"],[7,"REFRACTION_INCLUDED"],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",282],[0,"\nstruct RefractionModelResult { float transmissionLength ; vec3 positionExit ; } ;\nvoid refractionModelSphere ( vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModelResult ray ) { vec3 R1 = refract ( V , normalWS , 1.0 / ior ) ;\nfloat dist = dot ( - normalWS , R1 ) * thickness ;\nvec3 P1 = positionWS + R1 * dist ;\nray.transmissionLength = dist ;\nray.positionExit = P1 ; }\nvoid refractionModelPlanar ( vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModelResult ray ) { vec3 R = refract ( V , normalWS , 1.0 / ior ) ;\nfloat dist = thickness / max ( dot ( - normalWS , R ) , 1e-5f ) ;\nray.transmissionLength = dist ;\nray.positionExit = vec3 ( positionWS + R * dist ) ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[8,"MIN_PERCEPTUAL_ROUGHNESS","0.045"],[0,"\n\n"],[8,"MIN_ROUGHNESS","0.002025"],[0,"\n\n"],[4,{"t":"or","l":{"t":"or","l":{"t":"or","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"MATERIAL_ENABLE_ANISOTROPY"}},"r":{"t":"def","m":"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE"}},"r":{"t":"def","m":"MATERIAL_HAS_NORMALTEXTURE"}},294],[0,"\n\n"],[7,"NEED_TANGENT"],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",298],[0,"\nuniform sampler2D scene_PrefilteredDFG;\n\n"],[6],[0,"\nstruct SurfaceData { vec3 albedoColor ; vec3 emissiveColor ; float metallic ; float roughness ; float ambientOcclusion ; float opacity ; float IOR ; vec3 position ; vec4 positionCS ; vec3 normal ; \n"],[1,"NEED_TANGENT",302],[0," vec3 tangent ; vec3 bitangent ; \n"],[6],[0," vec3 viewDir ; float dotNV ; float specularIntensity ; vec3 specularColor ; \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",306],[0," float anisotropy ; vec3 anisotropicT ; vec3 anisotropicB ; vec3 anisotropicN ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",310],[0," float clearCoat ; float clearCoatRoughness ; vec3 clearCoatNormal ; float clearCoatDotNV ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",314],[0," float iridescenceIOR ; float iridescenceFactor ; float iridescenceThickness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",318],[0," float sheenRoughness ; vec3 sheenColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_TRANSMISSION",322],[0," vec3 absorptionCoefficient ; float transmission ; float thickness ; \n"],[6],[0," } ;\nstruct BSDFData { vec3 diffuseColor ; float roughness ; vec3 envSpecularDFG ; float diffuseAO ; vec3 specularF0 ; vec3 resolvedSpecularF0 ; float specularF90 ; vec3 energyCompensation ; \n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",326],[0," vec3 clearCoatSpecularColor ; float clearCoatRoughness ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",330],[0," vec3 iridescenceSpecularColor ; \n"],[6],[0," \n"],[1,"MATERIAL_ENABLE_SHEEN",334],[0," float sheenRoughness ; float sheenScaling ; float approxIBLSheenDG ; \n"],[6],[0," } ;\nfloat getAARoughnessFactor ( vec3 normal ) { \n"],[1,"HAS_DERIVATIVES",338],[0," vec3 dxy = max ( abs ( dFdx ( normal ) ) , abs ( dFdy ( normal ) ) ) ;\nreturn max ( max ( dxy.x , dxy.y ) , dxy.z ) ; \n"],[5,340],[0," return 0.0 ; \n"],[6],[0," }\nfloat F_Schlick ( float f0, float f90, float dotLH ) { return f0 + ( f90 - f0 ) * ( pow ( 1.0 - dotLH , 5.0 ) ) ; }\nvec3 F_Schlick ( vec3 f0, float f90, float dotLH ) { float fresnel = exp2 ( ( - 5.55473 * dotLH - 6.98316 ) * dotLH ) ;\nreturn ( f90 - f0 ) * fresnel + f0 ; }\nfloat G_GGX_SmithCorrelated ( float alpha, float dotNL, float dotNV ) { float a2 = pow2(alpha) ;\nfloat gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNV) ) ;\nfloat gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2(dotNL) ) ;\nreturn 0.5 / max ( gv + gl , EPSILON ) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",344],[0,"\nfloat G_GGX_SmithCorrelated_Anisotropic ( float at, float ab, float ToV, float BoV, float ToL, float BoL, float NoV, float NoL ) { float lambdaV = NoL * length ( vec3 ( at * ToV , ab * BoV , NoV ) ) ;\nfloat lambdaL = NoV * length ( vec3 ( at * ToL , ab * BoL , NoL ) ) ;\nreturn 0.5 / max ( lambdaV + lambdaL , EPSILON ) ; }\n\n"],[6],[0,"\nfloat D_GGX ( float alpha, float dotNH ) { float a2 = pow2(alpha) ;\nfloat denom = pow2(dotNH) * ( a2 - 1.0 ) + 1.0 ;\nreturn RECIPROCAL_PI * a2 / pow2(denom) ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",348],[0,"\nfloat D_GGX_Anisotropic ( float at, float ab, float ToH, float BoH, float NoH ) { float a2 = at * ab ;\nhighp vec3 d = vec3 ( ab * ToH , at * BoH , a2 * NoH ) ;\nhighp float d2 = dot ( d , d ) ;\nfloat b2 = a2 / d2 ;\nreturn a2 * b2 * b2 * RECIPROCAL_PI ; }\n\n"],[6],[0,"\nfloat DG_GGX ( float alpha, float dotNV, float dotNL, float dotNH ) { float D = D_GGX(alpha, dotNH) ;\nfloat G = G_GGX_SmithCorrelated(alpha, dotNL, dotNV) ;\nreturn G * D ; }\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",352],[0,"\nfloat DG_GGX_anisotropic ( vec3 h, vec3 l, SurfaceData surfaceData, float alpha, float dotNV, float dotNL, float dotNH ) { vec3 t = surfaceData.anisotropicT ;\nvec3 b = surfaceData.anisotropicB ;\nvec3 v = surfaceData.viewDir ;\nfloat dotTV = dot ( t , v ) ;\nfloat dotBV = dot ( b , v ) ;\nfloat dotTL = dot ( t , l ) ;\nfloat dotBL = dot ( b , l ) ;\nfloat dotTH = dot ( t , h ) ;\nfloat dotBH = dot ( b , h ) ;\nfloat at = max ( alpha * ( 1.0 + surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat ab = max ( alpha * ( 1.0 - surfaceData.anisotropy ) , MIN_ROUGHNESS ) ;\nfloat D = D_GGX_Anisotropic(at, ab, dotTH, dotBH, dotNH) ;\nfloat G = G_GGX_SmithCorrelated_Anisotropic(at, ab, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL) ;\nreturn G * D ; }\n\n"],[6],[0,"\nvec3 BRDF_Specular_GGX ( vec3 incidentDirection, SurfaceData surfaceData, BSDFData bsdfData, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2(roughness) ;\nvec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( normal , incidentDirection )) ;\nfloat dotNV = saturate(dot ( normal , surfaceData.viewDir )) ;\nfloat dotNH = saturate(dot ( normal , halfDir )) ;\nfloat dotLH = saturate(dot ( incidentDirection , halfDir )) ;\nvec3 F = F_Schlick(specularColor, bsdfData.specularF90, dotLH) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",356],[0," F = mix ( F , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",360],[0," float GD = DG_GGX_anisotropic(halfDir, incidentDirection, surfaceData, alpha, dotNV, dotNL, dotNH) ; \n"],[5,362],[0," float GD = DG_GGX(alpha, dotNV, dotNL, dotNH) ; \n"],[6],[0,"\nreturn F * GD ; }\nvec3 BRDF_Diffuse_Lambert ( vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor ; }\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",366],[0,"\nvec3 iorToFresnel0 ( vec3 transmittedIOR, float incidentIOR ) { return pow ( ( transmittedIOR - incidentIOR ) / ( transmittedIOR + incidentIOR ) , vec3 ( 2.0 ) ) ; }\nfloat iorToFresnel0 ( float transmittedIOR, float incidentIOR ) { return pow ( ( transmittedIOR - incidentIOR ) / ( transmittedIOR + incidentIOR ) , 2.0 ) ; }\nvec3 fresnelToIOR ( vec3 f0 ) { vec3 sqrtF0 = sqrt ( f0 ) ;\nreturn ( vec3 ( 1.0 ) + sqrtF0 ) / ( vec3 ( 1.0 ) - sqrtF0 ) ; }\nvec3 evalSensitivity ( float opd, vec3 shift ) { float phase = 2.0 * PI * opd * 1.0e-9 ;\nconst vec3 val = vec3 ( 5.4856e-13 , 4.4201e-13 , 5.2481e-13 ) ;\nconst vec3 pos = vec3 ( 1.6810e+06 , 1.7953e+06 , 2.2084e+06 ) ;\nconst vec3 var = vec3 ( 4.3278e+09 , 9.3046e+09 , 6.6121e+09 ) ;\nvec3 xyz = val * sqrt ( 2.0 * PI * var ) * cos ( pos * phase + shift ) * exp ( - var * pow2(phase) ) ;\nxyz.x += 9.7470e-14 * sqrt ( 2.0 * PI * 4.5282e+09 ) * cos ( 2.2399e+06 * phase + shift[0] ) * exp ( - 4.5282e+09 * pow2(phase) ) ;\nxyz /= 1.0685e-7 ;\nconst mat3 XYZ_TO_RGB = mat3 ( 3.2404542 , - 0.9692660 , 0.0556434 , - 1.5371385 , 1.8760108 , - 0.2040259 , - 0.4985314 , 0.0415560 , 1.0572252 ) ;\nvec3 rgb = XYZ_TO_RGB * xyz ;\nreturn rgb ; }\nvec3 evalIridescenceSpecular ( float outsideIOR, float dotNV, float thinIOR, vec3 baseF0, float baseF90, float iridescenceThickness ) { vec3 iridescence = vec3 ( 1.0 ) ;\nfloat iridescenceIOR = mix ( outsideIOR , thinIOR , smoothstep ( 0.0 , 0.03 , iridescenceThickness ) ) ;\nfloat sinTheta2Sq = pow ( outsideIOR / iridescenceIOR , 2.0 ) * ( 1.0 - pow ( dotNV , 2.0 ) ) ;\nfloat cosTheta2Sq = 1.0 - sinTheta2Sq ;\nif ( cosTheta2Sq < 0.0 ) { return iridescence ; }\nfloat cosTheta2 = sqrt ( cosTheta2Sq ) ;\nfloat f0 = iorToFresnel0(iridescenceIOR, outsideIOR) ;\nfloat reflectance = F_Schlick(f0, baseF90, dotNV) ;\nfloat t121 = 1.0 - reflectance ;\nfloat phi12 = 0.0 ;\nfloat phi21 = PI - phi12 ;\nvec3 baseIOR = fresnelToIOR(clamp ( baseF0 , 0.0 , 0.9999 )) ;\nvec3 r1 = iorToFresnel0(baseIOR, iridescenceIOR) ;\nvec3 r23 = F_Schlick(r1, baseF90, cosTheta2) ;\nvec3 phi23 = vec3 ( 0.0 ) ;\nif ( baseIOR[0] < iridescenceIOR ) { phi23[0] = PI ; }\nif ( baseIOR[1] < iridescenceIOR ) { phi23[1] = PI ; }\nif ( baseIOR[2] < iridescenceIOR ) { phi23[2] = PI ; }\nfloat opd = 2.0 * iridescenceIOR * iridescenceThickness * cosTheta2 ;\nvec3 phi = vec3 ( phi21 ) + phi23 ;\nvec3 r123 = clamp ( reflectance * r23 , 1e-5 , 0.9999 ) ;\nvec3 sr123 = sqrt ( r123 ) ;\nvec3 rs = pow2(t121) * r23 / ( vec3 ( 1.0 ) - r123 ) ;\nvec3 c0 = reflectance + rs ;\niridescence = c0 ;\nvec3 cm = rs - t121 ;\nfor ( int m = 1 ; m <= 2 ; ++ m ) { cm *= sr123 ;\nvec3 sm = 2.0 * evalSensitivity(float ( m ) * opd, float ( m ) * phi) ;\niridescence += cm * sm ; }\nreturn iridescence = max ( iridescence , vec3 ( 0.0 ) ) ; }\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",376],[0,"\nfloat D_Charlie ( float roughness, float dotNH ) { float invAlpha = 1.0 / roughness ;\nfloat cos2h = dotNH * dotNH ;\nfloat sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;\nreturn ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ; }\nfloat V_Neubelt ( float NoV, float NoL ) { return saturate(1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) )) ; }\nvec3 sheenBRDF ( vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness ) { vec3 halfDir = normalize ( incidentDirection + surfaceData.viewDir ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nfloat dotNH = saturate(dot ( surfaceData.normal , halfDir )) ;\nfloat D = D_Charlie(sheenRoughness, dotNH) ;\nfloat V = V_Neubelt(surfaceData.dotNV, dotNL) ;\nvec3 F = sheenColor ;\nreturn D * V * F ; }\nfloat prefilteredSheenDFG ( float dotNV, float sheenRoughness ) { \n"],[1,"HAS_TEX_LOD",372],[0," return texture2DLodEXT ( scene_PrefilteredDFG , vec2 ( dotNV , sheenRoughness ) , 0.0 ).b ; \n"],[5,374],[0," return texture2D ( scene_PrefilteredDFG , vec2 ( dotNV , sheenRoughness ) , 0.0 ).b ; \n"],[6],[0," }\n\n"],[6],[0,"\nvec2 envDFGApprox ( float roughness, float dotNV ) { const vec4 c0 = vec4 ( - 1 , - 0.0275 , - 0.572 , 0.022 ) ;\nconst vec4 c1 = vec4 ( 1 , 0.0425 , 1.04 , - 0.04 ) ;\nvec4 r = roughness * c0 + c1 ;\nfloat a004 = min ( r.x * r.x , exp2 ( - 9.28 * dotNV ) ) * r.x + r.y ;\nreturn vec2 ( - 1.04 , 1.04 ) * a004 + r.zw ; }\nvec3 envBRDFApprox ( vec3 f0, float f90, float roughness, float dotNV ) { vec2 AB = envDFGApprox(roughness, dotNV) ;\nreturn f0 * AB.x + f90 * AB.y ; }\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",391],[0,"\nuniform sampler2D camera_OpaqueTexture;\nvec3 evaluateTransmission ( SurfaceData surfaceData, BSDFData bsdfData ) { RefractionModelResult ray ;\n\n"],[3,"REFRACTION_MODE","==",0,382],[0," refractionModelSphere(- surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, surfaceData.thickness, ray) ; \n"],[5,385],[3,"REFRACTION_MODE","==",1,385],[0," refractionModelPlanar(- surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, surfaceData.thickness, ray) ; \n"],[6],[0,"\nvec3 refractedRayExit = ray.positionExit ;\nvec4 samplingPositionNDC = camera_ProjMat * camera_ViewMat * vec4 ( refractedRayExit , 1.0 ) ;\nvec2 refractionCoords = ( samplingPositionNDC.xy / samplingPositionNDC.w ) * 0.5 + 0.5 ;\nvec3 refractionTransmitted = texture2DSRGB(camera_OpaqueTexture, refractionCoords).rgb ;\nrefractionTransmitted *= bsdfData.diffuseColor ;\nrefractionTransmitted *= ( 1.0 - max ( max ( bsdfData.envSpecularDFG.r , bsdfData.envSpecularDFG.g ) , bsdfData.envSpecularDFG.b ) ) ;\n\n"],[1,"MATERIAL_HAS_THICKNESS",389],[0," vec3 transmittance = min ( vec3 ( 1.0 ) , exp ( - surfaceData.absorptionCoefficient * ray.transmissionLength ) ) ;\nrefractionTransmitted *= transmittance ; \n"],[6],[0,"\nreturn refractionTransmitted ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",401],[0,"\nuniform sampler2D camera_AOTexture;\nfloat evaluateAmbientOcclusion ( vec2 uv ) { \n"],[1,"MATERIAL_IS_TRANSPARENT",397],[0," return 1.0 ; \n"],[5,399],[0," return texture2D ( camera_AOTexture , uv ).r ; \n"],[6],[0," }\n\n"],[6],[0,"\nvoid initBSDFData ( SurfaceData surfaceData, out BSDFData bsdfData ) { vec3 albedoColor = surfaceData.albedoColor ;\nfloat metallic = surfaceData.metallic ;\nfloat roughness = surfaceData.roughness ;\nvec3 dielectricBaseF0 = vec3 ( pow2(( surfaceData.IOR - 1.0 ) / ( surfaceData.IOR + 1.0 )) ) ;\nvec3 dielectricF0 = min ( dielectricBaseF0 * surfaceData.specularColor , vec3 ( 1.0 ) ) * surfaceData.specularIntensity ;\nfloat dielectricF90 = surfaceData.specularIntensity ;\nbsdfData.specularF0 = mix ( dielectricF0 , albedoColor , metallic ) ;\nbsdfData.specularF90 = mix ( dielectricF90 , 1.0 , metallic ) ;\nbsdfData.diffuseColor = albedoColor * ( 1.0 - metallic ) * ( 1.0 - max ( max ( dielectricF0.r , dielectricF0.g ) , dielectricF0.b ) ) ;\nbsdfData.roughness = max ( MIN_PERCEPTUAL_ROUGHNESS , min ( roughness + getAARoughnessFactor(surfaceData.normal) , 1.0 ) ) ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",405],[0," float topIOR = 1.0 ;\nbsdfData.iridescenceSpecularColor = evalIridescenceSpecular(topIOR, surfaceData.dotNV, surfaceData.iridescenceIOR, bsdfData.specularF0, bsdfData.specularF90, surfaceData.iridescenceThickness) ; \n"],[6],[0,"\nbsdfData.resolvedSpecularF0 = bsdfData.specularF0 ;\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",409],[0," bsdfData.resolvedSpecularF0 = mix ( bsdfData.resolvedSpecularF0 , bsdfData.iridescenceSpecularColor , surfaceData.iridescenceFactor ) ; \n"],[6],[0,"\nvec2 dfg = envDFGApprox(bsdfData.roughness, surfaceData.dotNV) ;\nbsdfData.envSpecularDFG = bsdfData.resolvedSpecularF0 * dfg.x + bsdfData.specularF90 * dfg.y ;\nbsdfData.energyCompensation = 1.0 + bsdfData.resolvedSpecularF0 * ( 1.0 / max ( dfg.x + dfg.y , EPSILON ) - 1.0 ) ;\nbsdfData.diffuseAO = surfaceData.ambientOcclusion ;\n\n"],[1,"SCENE_ENABLE_AMBIENT_OCCLUSION",413],[0," float ambientAO = evaluateAmbientOcclusion(( surfaceData.positionCS.xy / surfaceData.positionCS.w ) * 0.5 + 0.5) ;\nbsdfData.diffuseAO = min ( bsdfData.diffuseAO , ambientAO ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",417],[0," bsdfData.clearCoatRoughness = max ( MIN_PERCEPTUAL_ROUGHNESS , min ( surfaceData.clearCoatRoughness + getAARoughnessFactor(surfaceData.clearCoatNormal) , 1.0 ) ) ;\nbsdfData.clearCoatSpecularColor = vec3 ( 0.04 ) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",421],[0," bsdfData.sheenRoughness = max ( MIN_PERCEPTUAL_ROUGHNESS , min ( surfaceData.sheenRoughness + getAARoughnessFactor(surfaceData.normal) , 1.0 ) ) ;\nbsdfData.approxIBLSheenDG = prefilteredSheenDFG(surfaceData.dotNV, bsdfData.sheenRoughness) ;\nbsdfData.sheenScaling = 1.0 - bsdfData.approxIBLSheenDG * max ( max ( surfaceData.sheenColor.r , surfaceData.sheenColor.g ) , surfaceData.sheenColor.b ) ; \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INCLUDED",471],[0,"\n\n"],[7,"LIGHT_INCLUDED"],[0,"\nuniform ivec4 renderer_Layer;\n\n"],[2,"GRAPHICS_API_WEBGL2",431],[0,"\nbool isBitSet ( float value, float mask, float bitIndex ) { return mod ( floor ( value / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 && mod ( floor ( mask / pow ( 2.0 , bitIndex ) ) , 2.0 ) == 1.0 ; }\n\n"],[6],[0,"\nbool isRendererCulledByLight ( ivec2 rendererLayer, ivec2 lightCullingMask ) { \n"],[1,"GRAPHICS_API_WEBGL2",435],[0," return ! ( ( rendererLayer.x & lightCullingMask.x ) != 0 || ( rendererLayer.y & lightCullingMask.y ) != 0 ) ; \n"],[5,437],[0," for ( int i = 0 ; i < 16 ; i ++ ) { if ( isBitSet(float ( rendererLayer.x ), float ( lightCullingMask.x ), float ( i )) || isBitSet(float ( rendererLayer.y ), float ( lightCullingMask.y ), float ( i )) ) { return false ; } }\nreturn true ; \n"],[6],[0," }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",445],[0,"\nstruct DirectLight { vec3 color ; vec3 direction ; } ;\nuniform ivec2 scene_DirectLightCullingMask [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightColor [ SCENE_DIRECT_LIGHT_COUNT ];\nuniform vec3 scene_DirectLightDirection [ SCENE_DIRECT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",443],[0,"\nDirectLight getDirectLight ( int index ) { DirectLight light ;\nlight.color = scene_DirectLightColor[index] ;\nlight.direction = scene_DirectLightDirection[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",453],[0,"\nstruct PointLight { vec3 color ; vec3 position ; float distance ; } ;\nuniform ivec2 scene_PointLightCullingMask [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightColor [ SCENE_POINT_LIGHT_COUNT ];\nuniform vec3 scene_PointLightPosition [ SCENE_POINT_LIGHT_COUNT ];\nuniform float scene_PointLightDistance [ SCENE_POINT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",451],[0,"\nPointLight getPointLight ( int index ) { PointLight light ;\nlight.color = scene_PointLightColor[index] ;\nlight.position = scene_PointLightPosition[index] ;\nlight.distance = scene_PointLightDistance[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",461],[0,"\nstruct SpotLight { vec3 color ; vec3 position ; vec3 direction ; float distance ; float angleCos ; float penumbraCos ; } ;\nuniform ivec2 scene_SpotLightCullingMask [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightColor [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightPosition [ SCENE_SPOT_LIGHT_COUNT ];\nuniform vec3 scene_SpotLightDirection [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightDistance [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightAngleCos [ SCENE_SPOT_LIGHT_COUNT ];\nuniform float scene_SpotLightPenumbraCos [ SCENE_SPOT_LIGHT_COUNT ];\n\n"],[1,"GRAPHICS_API_WEBGL2",459],[0,"\nSpotLight getSpotLight ( int index ) { SpotLight light ;\nlight.color = scene_SpotLightColor[index] ;\nlight.position = scene_SpotLightPosition[index] ;\nlight.direction = scene_SpotLightDirection[index] ;\nlight.distance = scene_SpotLightDistance[index] ;\nlight.angleCos = scene_SpotLightAngleCos[index] ;\nlight.penumbraCos = scene_SpotLightPenumbraCos[index] ;\nreturn light ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\nstruct EnvMapLight { vec3 diffuse ; float mipMapLevel ; float diffuseIntensity ; float specularIntensity ; } ;\nuniform EnvMapLight scene_EnvMapLight;\n\n"],[1,"SCENE_USE_SH",465],[0,"\nuniform vec3 scene_EnvSH [ 9 ];\n\n"],[6],[0,"\n\n"],[1,"SCENE_USE_SPECULAR_ENV",469],[0,"\nuniform samplerCube scene_EnvSpecularSampler;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"REFLECTION_LOBE_INCLUDED",485],[0,"\n\n"],[7,"REFLECTION_LOBE_INCLUDED"],[0,"\nvoid diffuseLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 attenuationIrradiance, inout vec3 diffuseColor ) { diffuseColor += attenuationIrradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nvoid specularLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor ) { specularColor += attenuationIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.normal, bsdfData.specularF0, bsdfData.roughness) * bsdfData.energyCompensation ; }\nvoid sheenLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",479],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nspecularColor += attenuationIrradiance * sheenBRDF(incidentDirection, surfaceData, surfaceData.sheenColor, bsdfData.sheenRoughness) ; \n"],[6],[0," }\nfloat clearCoatLobe ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 color, inout vec3 specularColor ) { float attenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",483],[0," float clearCoatDotNL = saturate(dot ( surfaceData.clearCoatNormal , incidentDirection )) ;\nvec3 clearCoatIrradiance = clearCoatDotNL * color ;\nspecularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX(incidentDirection, surfaceData, bsdfData, surfaceData.clearCoatNormal, bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness) ;\nattenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn attenuation ; }\n\n"],[6],[0,"\nvoid surfaceShading ( SurfaceData surfaceData, BSDFData bsdfData, vec3 incidentDirection, vec3 lightColor, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nfloat dotNL = saturate(dot ( surfaceData.normal , incidentDirection )) ;\nvec3 irradiance = dotNL * lightColor * PI ;\nfloat attenuation = FUNCTION_CLEAR_COAT_LOBE(surfaceData, bsdfData, incidentDirection, lightColor, specularColor) ;\nvec3 attenuationIrradiance = attenuation * irradiance ;\nFUNCTION_DIFFUSE_LOBE(surfaceData, bsdfData, attenuationIrradiance, diffuseColor) ;\nFUNCTION_SPECULAR_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, specularColor) ;\nFUNCTION_SHEEN_LOBE(surfaceData, bsdfData, incidentDirection, attenuationIrradiance, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[1,"SCENE_DIRECT_LIGHT_COUNT",489],[0,"\nvoid addDirectionalDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, DirectLight directionalLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lightColor = directionalLight.color ;\nvec3 direction = - directionalLight.direction ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",493],[0,"\nvoid addPointDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, PointLight pointLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = pointLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nvec3 lightColor = pointLight.color ;\nlightColor *= clamp ( 1.0 - pow ( lightDistance / pointLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",497],[0,"\nvoid addSpotDirectLightRadiance ( SurfaceData surfaceData, BSDFData bsdfData, SpotLight spotLight, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 lVector = spotLight.position - surfaceData.position ;\nvec3 direction = normalize ( lVector ) ;\nfloat lightDistance = length ( lVector ) ;\nfloat angleCos = dot ( direction , - spotLight.direction ) ;\nfloat spotEffect = smoothstep ( spotLight.penumbraCos , spotLight.angleCos , angleCos ) ;\nfloat decayEffect = clamp ( 1.0 - pow ( lightDistance / spotLight.distance , 4.0 ) , 0.0 , 1.0 ) ;\nvec3 lightColor = spotLight.color ;\nlightColor *= spotEffect * decayEffect ;\nFUNCTION_SURFACE_SHADING(surfaceData, bsdfData, direction, lightColor, totalDiffuseColor, totalSpecularColor) ; }\n\n"],[6],[0,"\nvoid evaluateDirectRadiance ( SurfaceData surfaceData, BSDFData bsdfData, float shadowAttenuation, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { \n"],[1,"SCENE_DIRECT_LIGHT_COUNT",511],[0," for ( int i = 0 ; i < SCENE_DIRECT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_DirectLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",503],[0," DirectLight directionalLight = getDirectLight(i) ; \n"],[5,505],[0," DirectLight directionalLight ;\ndirectionalLight.color = scene_DirectLightColor[i] ;\ndirectionalLight.direction = scene_DirectLightDirection[i] ; \n"],[6],[0,"\n\n"],[1,"NEED_CALCULATE_SHADOWS",509],[0," if ( i == 0 ) { directionalLight.color *= shadowAttenuation ; } \n"],[6],[0,"\naddDirectionalDirectLightRadiance(surfaceData, bsdfData, directionalLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_POINT_LIGHT_COUNT",521],[0," for ( int i = 0 ; i < SCENE_POINT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_PointLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",517],[0," PointLight pointLight = getPointLight(i) ; \n"],[5,519],[0," PointLight pointLight ;\npointLight.color = scene_PointLightColor[i] ;\npointLight.position = scene_PointLightPosition[i] ;\npointLight.distance = scene_PointLightDistance[i] ; \n"],[6],[0,"\naddPointDirectLightRadiance(surfaceData, bsdfData, pointLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0,"\n\n"],[1,"SCENE_SPOT_LIGHT_COUNT",531],[0," for ( int i = 0 ; i < SCENE_SPOT_LIGHT_COUNT ; i ++ ) { if ( ! isRendererCulledByLight(renderer_Layer.xy, scene_SpotLightCullingMask[i]) ) { \n"],[1,"GRAPHICS_API_WEBGL2",527],[0," SpotLight spotLight = getSpotLight(i) ; \n"],[5,529],[0," SpotLight spotLight ;\nspotLight.color = scene_SpotLightColor[i] ;\nspotLight.position = scene_SpotLightPosition[i] ;\nspotLight.direction = scene_SpotLightDirection[i] ;\nspotLight.distance = scene_SpotLightDistance[i] ;\nspotLight.angleCos = scene_SpotLightAngleCos[i] ;\nspotLight.penumbraCos = scene_SpotLightPenumbraCos[i] ; \n"],[6],[0,"\naddSpotDirectLightRadiance(surfaceData, bsdfData, spotLight, totalDiffuseColor, totalSpecularColor) ; } } \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_PBR_INCLUDED",609],[0,"\n\n"],[7,"LIGHT_INDIRECT_PBR_INCLUDED"],[0,"\n\n"],[2,"FUNCTION_DIFFUSE_IBL",543],[0,"\n\n"],[8,"FUNCTION_DIFFUSE_IBL","evaluateDiffuseIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SPECULAR_IBL",549],[0,"\n\n"],[8,"FUNCTION_SPECULAR_IBL","evaluateSpecularIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_CLEAR_COAT_IBL",555],[0,"\n\n"],[8,"FUNCTION_CLEAR_COAT_IBL","evaluateClearCoatIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"FUNCTION_SHEEN_IBL",561],[0,"\n\n"],[8,"FUNCTION_SHEEN_IBL","evaluateSheenIBL"],[0,"\n\n"],[6],[0,"\n\n"],[2,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED",593],[0,"\n\n"],[7,"LIGHT_INDIRECT_FUNCTIONS_INCLUDED"],[0,"\nvec3 getReflectedVector ( SurfaceData surfaceData, vec3 n ) { \n"],[1,"MATERIAL_ENABLE_ANISOTROPY",569],[0," vec3 r = reflect ( - surfaceData.viewDir , surfaceData.anisotropicN ) ; \n"],[5,571],[0," vec3 r = reflect ( - surfaceData.viewDir , n ) ; \n"],[6],[0,"\nreturn r ; }\nfloat getSpecularMIPLevel ( float roughness, int maxMIPLevel ) { return roughness * float ( maxMIPLevel ) ; }\nvec3 getLightProbeRadiance ( SurfaceData surfaceData, vec3 normal, float roughness ) { \n"],[2,"SCENE_USE_SPECULAR_ENV",575],[0," return vec3 ( 0 ) ; \n"],[5,587],[0," vec3 reflectVec = getReflectedVector(surfaceData, normal) ;\nfloat specularMIPLevel = getSpecularMIPLevel(roughness, int ( scene_EnvMapLight.mipMapLevel )) ;\n\n"],[1,"HAS_TEX_LOD",579],[0," vec4 envMapColor = textureCubeLodEXT ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[5,581],[0," vec4 envMapColor = textureCube ( scene_EnvSpecularSampler , reflectVec , specularMIPLevel ) ; \n"],[6],[0,"\n\n"],[1,"ENGINE_NO_SRGB",585],[0," envMapColor = sRGBToLinear(envMapColor) ; \n"],[6],[0,"\nreturn envMapColor.rgb * scene_EnvMapLight.specularIntensity ; \n"],[6],[0," }\nfloat evaluateSpecularOcclusion ( float dotNV, float diffuseAO, float roughness ) { float specularAOFactor = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"or","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"SCENE_ENABLE_AMBIENT_OCCLUSION"}},"r":{"t":"def","m":"SCENE_USE_SPECULAR_ENV"}},591],[0," specularAOFactor = saturate(pow ( dotNV + diffuseAO , exp2 ( - 16.0 * roughness - 1.0 ) ) - 1.0 + diffuseAO) ; \n"],[6],[0,"\nreturn specularAOFactor ; }\n\n"],[6],[0,"\nvec3 getLightProbeIrradiance ( vec3 sh [ 9 ], vec3 normal ) { vec3 result = sh[0] + sh[1] * ( normal.y ) + sh[2] * ( normal.z ) + sh[3] * ( normal.x ) + sh[4] * ( normal.y * normal.x ) + sh[5] * ( normal.y * normal.z ) + sh[6] * ( 3.0 * normal.z * normal.z - 1.0 ) + sh[7] * ( normal.z * normal.x ) + sh[8] * ( normal.x * normal.x - normal.y * normal.y ) ;\nreturn max ( result , vec3 ( 0.0 ) ) ; }\nvoid evaluateDiffuseIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 diffuseColor ) { \n"],[1,"SCENE_USE_SH",597],[0," vec3 irradiance = getLightProbeIrradiance(scene_EnvSH, surfaceData.normal) ;\nirradiance *= scene_EnvMapLight.diffuseIntensity ; \n"],[5,599],[0," vec3 irradiance = scene_EnvMapLight.diffuse * scene_EnvMapLight.diffuseIntensity ;\nirradiance *= PI ; \n"],[6],[0,"\ndiffuseColor += bsdfData.diffuseAO * irradiance * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; }\nfloat evaluateClearCoatIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 specularColor ) { float radianceAttenuation = 1.0 ;\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",603],[0," vec3 clearCoatRadiance = getLightProbeRadiance(surfaceData, surfaceData.clearCoatNormal, bsdfData.clearCoatRoughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.clearCoatRoughness) ;\nspecularColor += specularAO * clearCoatRadiance * surfaceData.clearCoat * envBRDFApprox(bsdfData.clearCoatSpecularColor, 1.0, bsdfData.clearCoatRoughness, surfaceData.clearCoatDotNV) ;\nradianceAttenuation -= surfaceData.clearCoat * F_Schlick(0.04, 1.0, surfaceData.clearCoatDotNV) ; \n"],[6],[0,"\nreturn radianceAttenuation ; }\nvoid evaluateSpecularIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 outSpecularColor ) { vec3 radiance = getLightProbeRadiance(surfaceData, surfaceData.normal, bsdfData.roughness) ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.roughness) ;\noutSpecularColor += specularAO * radianceAttenuation * radiance * envBRDFApprox(bsdfData.resolvedSpecularF0, bsdfData.specularF90, bsdfData.roughness, surfaceData.dotNV) * bsdfData.energyCompensation ; }\nvoid evaluateSheenIBL ( SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 diffuseColor, inout vec3 specularColor ) { \n"],[1,"MATERIAL_ENABLE_SHEEN",607],[0," diffuseColor *= bsdfData.sheenScaling ;\nspecularColor *= bsdfData.sheenScaling ;\nfloat specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.sheenRoughness) ;\nvec3 reflectance = specularAO * radianceAttenuation * bsdfData.approxIBLSheenDG * surfaceData.sheenColor ;\nspecularColor += reflectance ; \n"],[6],[0," }\nvoid evaluateIBL ( SurfaceData surfaceData, BSDFData bsdfData, inout vec3 totalDiffuseColor, inout vec3 totalSpecularColor ) { vec3 diffuseColor = vec3 ( 0 ) ;\nvec3 specularColor = vec3 ( 0 ) ;\nFUNCTION_DIFFUSE_IBL(surfaceData, bsdfData, diffuseColor) ;\nfloat radianceAttenuation = FUNCTION_CLEAR_COAT_IBL(surfaceData, bsdfData, specularColor) ;\nFUNCTION_SPECULAR_IBL(surfaceData, bsdfData, radianceAttenuation, specularColor) ;\nFUNCTION_SHEEN_IBL(surfaceData, bsdfData, radianceAttenuation, diffuseColor, specularColor) ;\ntotalDiffuseColor += diffuseColor ;\ntotalSpecularColor += specularColor ; }\n\n"],[6],[0,"\n\n"],[2,"VERTEX_INCLUDE",615],[0,"\n\n"],[7,"VERTEX_INCLUDE"],[0,"\n\n"],[6],[0,"\n\n"],[2,"MATERIAL_INPUT_PBR_INCLUDED",866],[0,"\n\n"],[7,"MATERIAL_INPUT_PBR_INCLUDED"],[0,"\n\n"],[2,"NORMAL_INCLUDED",631],[0,"\n\n"],[7,"NORMAL_INCLUDED"],[0,"\nvec3 getNormalByNormalTexture ( mat3 tbn, sampler2D normalTexture, float normalIntensity, vec2 uv, bool isFrontFacing ) { vec3 normal = ( texture2D ( normalTexture , uv ) ).rgb ;\nnormal = normalize ( tbn * ( ( 2.0 * normal - 1.0 ) * vec3 ( normalIntensity , normalIntensity , 1.0 ) ) ) ;\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nreturn normal ; }\nmat3 getTBNByDerivatives ( vec2 uv, vec3 normal, vec3 position, bool isFrontFacing ) { \n"],[1,"HAS_DERIVATIVES",627],[0," uv = isFrontFacing ? uv : - uv ;\nvec3 dp1 = dFdx ( position ) ;\nvec3 dp2 = dFdy ( position ) ;\nvec2 duv1 = dFdx ( uv ) ;\nvec2 duv2 = dFdy ( uv ) ;\nvec3 dp2perp = cross ( dp2 , normal ) ;\nvec3 dp1perp = cross ( normal , dp1 ) ;\nvec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x ;\nvec3 bitangent = dp2perp * duv1.y + dp1perp * duv2.y ;\nfloat denom = max ( dot ( tangent , tangent ) , dot ( bitangent , bitangent ) ) ;\nfloat invmax = ( denom == 0.0 ) ? 0.0 : camera_ProjectionParams.x / sqrt ( denom ) ;\nreturn mat3 ( tangent * invmax , bitangent * invmax , normal ) ; \n"],[5,629],[0," return mat3 ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , normal ) ; \n"],[6],[0," }\n\n"],[6],[0,"\nuniform float material_AlphaCutoff;\nuniform vec4 material_BaseColor;\nuniform float material_Metal;\nuniform float material_Roughness;\nuniform float material_IOR;\nuniform vec3 material_EmissiveColor;\nuniform float material_NormalIntensity;\nuniform float material_OcclusionIntensity;\nuniform float material_OcclusionTextureCoord;\nuniform float material_SpecularIntensity;\nuniform vec3 material_SpecularColor;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",635],[0,"\nuniform sampler2D material_SpecularIntensityTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",639],[0,"\nuniform sampler2D material_SpecularColorTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",655],[0,"\nuniform float material_ClearCoat;\nuniform float material_ClearCoatRoughness;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",645],[0,"\nuniform sampler2D material_ClearCoatTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",649],[0,"\nuniform sampler2D material_ClearCoatRoughnessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",653],[0,"\nuniform sampler2D material_ClearCoatNormalTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",663],[0,"\nuniform vec3 material_AnisotropyInfo;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",661],[0,"\nuniform sampler2D material_AnisotropyTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",675],[0,"\nuniform vec4 material_IridescenceInfo;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",669],[0,"\nuniform sampler2D material_IridescenceThicknessTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",673],[0,"\nuniform sampler2D material_IridescenceTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",687],[0,"\nuniform float material_SheenRoughness;\nuniform vec3 material_SheenColor;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",681],[0,"\nuniform sampler2D material_SheenTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",685],[0,"\nuniform sampler2D material_SheenRoughnessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",703],[0,"\nuniform float material_Transmission;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",693],[0,"\nuniform sampler2D material_TransmissionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",701],[0,"\nuniform vec3 material_AttenuationColor;\nuniform float material_AttenuationDistance;\nuniform float material_Thickness;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",699],[0,"\nuniform sampler2D material_ThicknessTexture;\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",707],[0,"\nuniform sampler2D material_BaseTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",711],[0,"\nuniform sampler2D material_NormalTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",715],[0,"\nuniform sampler2D material_EmissiveTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",719],[0,"\nuniform sampler2D material_RoughnessMetallicTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",723],[0,"\nuniform sampler2D material_OcclusionTexture;\n\n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",727],[0,"\nvec3 getAnisotropicBentNormal ( SurfaceData surfaceData ) { vec3 anisotropyDirection = ( surfaceData.anisotropy >= 0.0 ) ? surfaceData.anisotropicB : surfaceData.anisotropicT ;\nvec3 anisotropicTangent = cross ( anisotropyDirection , surfaceData.viewDir ) ;\nvec3 anisotropicNormal = cross ( anisotropicTangent , anisotropyDirection ) ;\nvec3 bentNormal = normalize ( mix ( surfaceData.normal , anisotropicNormal , abs ( surfaceData.anisotropy ) * saturate(5.0 * surfaceData.roughness) ) ) ;\nreturn bentNormal ; }\n\n"],[6],[0,"\nSurfaceData getSurfaceData ( vec2 aoUV, bool isFrontFacing ) { SurfaceData surfaceData ;\nvec2 uv = uv ;\nvec4 baseColor = material_BaseColor ;\nfloat metallic = material_Metal ;\nfloat roughness = material_Roughness ;\nvec3 emissiveRadiance = material_EmissiveColor ;\n\n"],[1,"MATERIAL_HAS_BASETEXTURE",731],[0," baseColor *= texture2DSRGB(material_BaseTexture, uv) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",735],[0," baseColor *= vertexColor ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_IS_ALPHA_CUTOFF",739],[0," if ( baseColor.a < material_AlphaCutoff ) { discard ; } \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE",743],[0," vec4 metalRoughMapColor = texture2D ( material_RoughnessMetallicTexture , uv ) ;\nroughness *= metalRoughMapColor.g ;\nmetallic *= metalRoughMapColor.b ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_EMISSIVETEXTURE",747],[0," emissiveRadiance *= texture2DSRGB(material_EmissiveTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.albedoColor = baseColor.rgb ;\nsurfaceData.emissiveColor = emissiveRadiance ;\nsurfaceData.metallic = metallic ;\nsurfaceData.roughness = roughness ;\nsurfaceData.IOR = material_IOR ;\n\n"],[1,"MATERIAL_IS_TRANSPARENT",751],[0," surfaceData.opacity = baseColor.a ; \n"],[5,753],[0," surfaceData.opacity = 1.0 ; \n"],[6],[0,"\nsurfaceData.position = positionWS ;\nsurfaceData.positionCS = positionCS ;\n\n"],[1,"CAMERA_ORTHOGRAPHIC",757],[0," surfaceData.viewDir = - camera_Forward ; \n"],[5,759],[0," surfaceData.viewDir = normalize ( camera_Position - positionWS ) ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_NORMAL",763],[0," vec3 normal = normalize ( normalWS ) ; \n"],[5,768],[1,"HAS_DERIVATIVES",766],[0," vec3 pos_dx = dFdx ( positionWS ) ;\nvec3 pos_dy = dFdy ( positionWS ) ;\nvec3 normal = normalize ( cross ( pos_dx , pos_dy ) ) ;\nnormal *= camera_ProjectionParams.x ; \n"],[5,768],[0," vec3 normal = vec3 ( 0 , 0 , 1 ) ; \n"],[6],[0,"\nnormal *= float ( isFrontFacing ) * 2.0 - 1.0 ;\nsurfaceData.normal = normal ;\n\n"],[1,"NEED_TANGENT",782],[0," \n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},774],[0," surfaceData.tangent = tangentWS ;\nsurfaceData.bitangent = bitangentWS ;\nmat3 tbn = mat3 ( tangentWS , bitangentWS , normalWS ) ; \n"],[5,776],[0," mat3 tbn = getTBNByDerivatives(uv, normal, positionWS, isFrontFacing) ;\nsurfaceData.tangent = tbn[0] ;\nsurfaceData.bitangent = tbn[1] ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_NORMALTEXTURE",780],[0," surfaceData.normal = getNormalByNormalTexture(tbn, material_NormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[6],[0," \n"],[6],[0,"\nsurfaceData.dotNV = saturate(dot ( surfaceData.normal , surfaceData.viewDir )) ;\nsurfaceData.specularIntensity = material_SpecularIntensity ;\nsurfaceData.specularColor = material_SpecularColor ;\n\n"],[1,"MATERIAL_HAS_SPECULAR_TEXTURE",786],[0," surfaceData.specularIntensity *= texture2D ( material_SpecularIntensityTexture , uv ).a ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_SPECULAR_COLOR_TEXTURE",790],[0," surfaceData.specularColor *= texture2D ( material_SpecularColorTexture , uv ).rgb ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_CLEAR_COAT",808],[0," \n"],[1,"MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE",796],[0," surfaceData.clearCoatNormal = getNormalByNormalTexture(tbn, material_ClearCoatNormalTexture, material_NormalIntensity, uv, isFrontFacing) ; \n"],[5,798],[0," surfaceData.clearCoatNormal = normal ; \n"],[6],[0,"\nsurfaceData.clearCoatDotNV = saturate(dot ( surfaceData.clearCoatNormal , surfaceData.viewDir )) ;\nsurfaceData.clearCoat = material_ClearCoat ;\nsurfaceData.clearCoatRoughness = material_ClearCoatRoughness ;\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_TEXTURE",802],[0," surfaceData.clearCoat *= ( texture2D ( material_ClearCoatTexture , uv ) ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE",806],[0," surfaceData.clearCoatRoughness *= ( texture2D ( material_ClearCoatRoughnessTexture , uv ) ).g ; \n"],[6],[0,"\nsurfaceData.clearCoat = saturate(surfaceData.clearCoat) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_ANISOTROPY",816],[0," float anisotropy = material_AnisotropyInfo.z ;\nvec3 anisotropicDirection = vec3 ( material_AnisotropyInfo.xy , 0.0 ) ;\n\n"],[1,"MATERIAL_HAS_ANISOTROPY_TEXTURE",814],[0," vec3 anisotropyTextureInfo = ( texture2D ( material_AnisotropyTexture , uv ) ).rgb ;\nanisotropy *= anisotropyTextureInfo.b ;\nanisotropicDirection.xy *= anisotropyTextureInfo.rg * 2.0 - 1.0 ; \n"],[6],[0,"\nsurfaceData.anisotropy = anisotropy ;\nsurfaceData.anisotropicT = normalize ( mat3 ( surfaceData.tangent , surfaceData.bitangent , surfaceData.normal ) * anisotropicDirection ) ;\nsurfaceData.anisotropicB = normalize ( cross ( surfaceData.normal , surfaceData.anisotropicT ) ) ;\nsurfaceData.anisotropicN = getAnisotropicBentNormal(surfaceData) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_IRIDESCENCE",830],[0," surfaceData.iridescenceFactor = material_IridescenceInfo.x ;\nsurfaceData.iridescenceIOR = material_IridescenceInfo.y ;\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE",822],[0," float iridescenceThicknessWeight = texture2D ( material_IridescenceThicknessTexture , uv ).g ;\nsurfaceData.iridescenceThickness = mix ( material_IridescenceInfo.z , material_IridescenceInfo.w , iridescenceThicknessWeight ) ; \n"],[5,824],[0," surfaceData.iridescenceThickness = material_IridescenceInfo.w ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_IRIDESCENCE_TEXTURE",828],[0," surfaceData.iridescenceFactor *= texture2D ( material_IridescenceTexture , uv ).r ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_SHEEN",842],[0," vec3 sheenColor = material_SheenColor ;\n\n"],[1,"MATERIAL_HAS_SHEEN_TEXTURE",836],[0," sheenColor *= texture2DSRGB(material_SheenTexture, uv).rgb ; \n"],[6],[0,"\nsurfaceData.sheenColor = sheenColor ;\nsurfaceData.sheenRoughness = material_SheenRoughness ;\n\n"],[1,"MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE",840],[0," surfaceData.sheenRoughness *= texture2D ( material_SheenRoughnessTexture , uv ).a ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",858],[0," surfaceData.transmission = material_Transmission ;\n\n"],[1,"MATERIAL_HAS_TRANSMISSION_TEXTURE",848],[0," surfaceData.transmission *= texture2D ( material_TransmissionTexture , uv ).r ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_THICKNESS",856],[0," surfaceData.absorptionCoefficient = - log ( material_AttenuationColor + HALF_EPS ) / max ( HALF_EPS , material_AttenuationDistance ) ;\nsurfaceData.thickness = max ( material_Thickness , 0.0001 ) ;\n\n"],[1,"MATERIAL_HAS_THICKNESS_TEXTURE",854],[0," surfaceData.thickness *= texture2D ( material_ThicknessTexture , uv ).g ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"MATERIAL_HAS_OCCLUSION_TEXTURE",862],[0," surfaceData.ambientOcclusion = ( ( texture2D ( material_OcclusionTexture , aoUV ) ).r - 1.0 ) * material_OcclusionIntensity + 1.0 ; \n"],[5,864],[0," surfaceData.ambientOcclusion = 1.0 ; \n"],[6],[0,"\nreturn surfaceData ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[1,"LIGHTMAP_TEXTURE",872],[0,"\nuniform sampler2D u_lightMapTexture;\nuniform float u_lightMapIntensity;\n\n"],[6],[0,"\nvoid main() { BSDFData bsdfData ;\nvec2 aoUV = uv ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"MATERIAL_HAS_OCCLUSION_TEXTURE"},"r":{"t":"def","m":"RENDERER_HAS_UV1"}},876],[0," if ( material_OcclusionTextureCoord == 1.0 ) { aoUV = uv1 ; } \n"],[6],[0,"\nSurfaceData surfaceData = getSurfaceData(aoUV, gl_FrontFacing) ;\ninitBSDFData(surfaceData, bsdfData) ;\nvec3 totalDiffuseColor = vec3 ( 0 , 0 , 0 ) ;\nvec3 totalSpecularColor = vec3 ( 0 , 0 , 0 ) ;\nfloat shadowAttenuation = 1.0 ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"SCENE_DIRECT_LIGHT_COUNT"},"r":{"t":"def","m":"NEED_CALCULATE_SHADOWS"}},886],[0," \n"],[3,"SCENE_SHADOW_CASCADED_COUNT","==",1,882],[0," vec3 shadowCoord = shadowCoord ; \n"],[5,884],[0," vec3 shadowCoord = getShadowCoord(positionWS) ; \n"],[6],[0,"\nshadowAttenuation *= sampleShadowMap(positionWS, shadowCoord) ; \n"],[6],[0,"\nevaluateDirectRadiance(surfaceData, bsdfData, shadowAttenuation, totalDiffuseColor, totalSpecularColor) ;\nevaluateIBL(surfaceData, bsdfData, totalDiffuseColor, totalSpecularColor) ;\n\n"],[1,"LIGHTMAP_TEXTURE",894],[0," vec2 lightMapUV = uv ;\n\n"],[1,"RENDERER_HAS_UV1",892],[0," lightMapUV = uv1 ; \n"],[6],[0,"\ntotalDiffuseColor += texture2D ( u_lightMapTexture , lightMapUV ).rgb * u_lightMapIntensity * BRDF_Diffuse_Lambert(bsdfData.diffuseColor) ; \n"],[6],[0,"\n\n"],[1,"MATERIAL_ENABLE_TRANSMISSION",898],[0," vec3 refractionTransmitted = evaluateTransmission(surfaceData, bsdfData) ;\ntotalDiffuseColor = mix ( totalDiffuseColor , refractionTransmitted , surfaceData.transmission ) ; \n"],[6],[0,"\nvec4 color = vec4 ( ( totalDiffuseColor + totalSpecularColor ).rgb , surfaceData.opacity ) ;\ncolor.rgb += surfaceData.emissiveColor ;\n\n"],[3,"SCENE_FOG_MODE","!=",0,902],[0," color = fog(color, positionVS) ; \n"],[6],[0,"\ngl_FragColor = color ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect generated BakePBR.gsp for self-shadowing uv alias =="
python3 <<'PY'
import json
from pathlib import Path

path = Path("packages/custom-material/libs/bake-pbr/BakePBR.gsp")
data = json.loads(path.read_text())
frag = "".join(
    item[1]
    for item in data["subShaders"][0]["passes"][2]["fragmentShaderInstructions"]
    if isinstance(item, list) and len(item) > 1 and isinstance(item[1], str)
)

needle = "vec2 uv = uv"
idx = frag.find(needle)
print(f"{needle}: {'FOUND' if idx >= 0 else 'NOT FOUND'}")
if idx >= 0:
    start = max(0, idx - 200)
    end = min(len(frag), idx + 300)
    print("\nContext:\n")
    print(frag[start:end])
PY

echo
echo "== Inspect BakePBR source/template around getSurfaceData =="
src_files="$(fd -i 'BakePBR\.(shader|ts)$' packages 2>/dev/null || true)"
if [ -z "$src_files" ]; then
  echo "No BakePBR source/template found via fd."
else
  while IFS= read -r file; do
    [ -n "$file" ] || continue
    echo "--- $file ---"
    rg -n -C2 'getSurfaceData|vec2 uv = uv|material_BaseTexture|vertexColor' "$file" || true
    echo
  done <<< "$src_files"
fi

Repository: galacean/engine-toolkit

Length of output: 945


Fix the self-initializing uv local in generated getSurfaceData().

The fragment shader contains vec2 uv = uv;, which shadows the varying and initializes from an undefined local value. Every texture sample in this function will use garbage coordinates. The source shader signature differs (taking a varyings parameter), indicating the generator is mishandling the varying reference during compilation. Correct the generator/compiler and regenerate BakePBR.gsp.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/custom-material/libs/bake-pbr/BakePBR.gsp` at line 1, The fragment
generator produced a self-initializing local "vec2 uv = uv;" inside
getSurfaceData, shadowing the varying uv and leaving it undefined; fix the
generator so getSurfaceData uses the varying uv (or a properly passed-in
parameter) instead of declaring a local with the same name (inspect the code
path that emits getSurfaceData and the varying-to-local mapping), remove the
erroneous local declaration or rename it (e.g., use "vec2 uv_in" or reference
the existing varying "uv"), regenerate BakePBR.gsp so all texture lookups in
getSurfaceData use the correct UVs.

@@ -0,0 +1 @@
{"name":"outline-replace-shader","platformTarget":0,"subShaders":[{"name":"Default","tags":{},"passes":[{"name":"Forward","isUsePass":false,"tags":{},"renderStates":{"constantMap":{},"variableMap":{}},"vertexShaderInstructions":[[0,"\n"],[2,"COMMON_INCLUDED",30],[0,"\n\n"],[7,"COMMON_INCLUDED"],[0,"\n\n"],[8,"PI","3.14159265359"],[0,"\n\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n\n"],[8,"EPSILON","1e-6"],[0,"\n\n"],[8,"LOG2","1.442695"],[0,"\n\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",24],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,28],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",36],[0,"\n\n"],[7,"TRANSFORM_INCLUDED"],[0,"\nuniform mat4 renderer_MVPMat;\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",58],[0,"\n\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",56],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",46],[0,"\nuniform sampler2D renderer_JointSampler;\nuniform float renderer_JointCount;\nmat4 getJointMatrix ( sampler2D smp, float index ) { float base = index / renderer_JointCount ;\nfloat hf = 0.5 / renderer_JointCount ;\nfloat v = base + hf ;\nvec4 m0 = texture2D ( smp , vec2 ( 0.125 , v ) ) ;\nvec4 m1 = texture2D ( smp , vec2 ( 0.375 , v ) ) ;\nvec4 m2 = texture2D ( smp , vec2 ( 0.625 , v ) ) ;\nvec4 m3 = texture2D ( smp , vec2 ( 0.875 , v ) ) ;\nreturn mat4 ( m0 , m1 , m2 , m3 ) ; }\n\n"],[5,48],[0,"\nuniform mat4 renderer_JointMatrix [ RENDERER_JOINTS_NUM ];\n\n"],[6],[0,"\nmat4 getSkinMatrix ( ) { \n"],[1,"RENDERER_USE_JOINT_TEXTURE",52],[0," mat4 skinMatrix = WEIGHTS_0.x * getJointMatrix(renderer_JointSampler, JOINTS_0.x) + WEIGHTS_0.y * getJointMatrix(renderer_JointSampler, JOINTS_0.y) + WEIGHTS_0.z * getJointMatrix(renderer_JointSampler, JOINTS_0.z) + WEIGHTS_0.w * getJointMatrix(renderer_JointSampler, JOINTS_0.w) ; \n"],[5,54],[0," mat4 skinMatrix = WEIGHTS_0.x * renderer_JointMatrix[int ( JOINTS_0.x )] + WEIGHTS_0.y * renderer_JointMatrix[int ( JOINTS_0.y )] + WEIGHTS_0.z * renderer_JointMatrix[int ( JOINTS_0.z )] + WEIGHTS_0.w * renderer_JointMatrix[int ( JOINTS_0.w )] ; \n"],[6],[0,"\nreturn skinMatrix ; }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"BLENDSHAPE_INCLUDED",136],[0,"\n\n"],[7,"BLENDSHAPE_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",134],[0,"\n\n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",68],[0,"\nuniform mediump sampler2DArray renderer_BlendShapeTexture;\nuniform ivec3 renderer_BlendShapeTextureInfo;\nuniform float renderer_BlendShapeWeights [ RENDERER_BLENDSHAPE_COUNT ];\nvec3 getBlendShapeVertexElement ( int blendShapeIndex, int vertexElementIndex ) { int y = vertexElementIndex / renderer_BlendShapeTextureInfo.y ;\nint x = vertexElementIndex - y * renderer_BlendShapeTextureInfo.y ;\nivec3 uv = ivec3 ( x , y , blendShapeIndex ) ;\nreturn ( texelFetch ( renderer_BlendShapeTexture , uv , 0 ) ).xyz ; }\n\n"],[5,82],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},72],[0,"\nuniform float renderer_BlendShapeWeights [ 2 ];\n\n"],[5,80],[0,"\n\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},76],[0,"\nuniform float renderer_BlendShapeWeights [ 4 ];\n\n"],[5,78],[0,"\nuniform float renderer_BlendShapeWeights [ 8 ];\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid calculateBlendShape ( inout vec4 position\n"],[1,"RENDERER_HAS_NORMAL",90],[0," , inout vec3 normal \n"],[1,"RENDERER_HAS_TANGENT",88],[0," , inout vec4 tangent \n"],[6],[0," \n"],[6],[0," ) { \n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",102],[0," int vertexOffset = gl_VertexID * renderer_BlendShapeTextureInfo.x ;\nfor ( int i = 0 ; i < RENDERER_BLENDSHAPE_COUNT ; i ++ ) { int vertexElementOffset = vertexOffset ;\nfloat weight = renderer_BlendShapeWeights[i] ;\nif ( weight != 0.0 ) { position.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"}},96],[0," vertexElementOffset += 1 ;\nnormal += getBlendShapeVertexElement(i, vertexElementOffset) * weight ; \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_HAS_TANGENT"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},100],[0," vertexElementOffset += 1 ;\ntangent.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight ; \n"],[6],[0," } } \n"],[5,132],[0," position.xyz += POSITION_BS0 * renderer_BlendShapeWeights[0] ;\nposition.xyz += POSITION_BS1 * renderer_BlendShapeWeights[1] ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},114],[0," \n"],[1,"RENDERER_HAS_NORMAL",108],[0," normal += NORMAL_BS0 * renderer_BlendShapeWeights[0] ;\nnormal += NORMAL_BS1 * renderer_BlendShapeWeights[1] ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_TANGENT",112],[0," tangent.xyz += TANGENT_BS0 * renderer_BlendShapeWeights[0] ;\ntangent.xyz += TANGENT_BS1 * renderer_BlendShapeWeights[1] ; \n"],[6],[0," \n"],[5,130],[0," \n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},126],[0," position.xyz += POSITION_BS2 * renderer_BlendShapeWeights[2] ;\nposition.xyz += POSITION_BS3 * renderer_BlendShapeWeights[3] ;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_HAS_NORMAL"}},120],[0," normal += NORMAL_BS0 * renderer_BlendShapeWeights[0] ;\nnormal += NORMAL_BS1 * renderer_BlendShapeWeights[1] ;\nnormal += NORMAL_BS2 * renderer_BlendShapeWeights[2] ;\nnormal += NORMAL_BS3 * renderer_BlendShapeWeights[3] ; \n"],[6],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"},"r":{"t":"def","m":"RENDERER_HAS_TANGENT"}},124],[0," tangent.xyz += TANGENT_BS0 * renderer_BlendShapeWeights[0] ;\ntangent.xyz += TANGENT_BS1 * renderer_BlendShapeWeights[1] ;\ntangent.xyz += TANGENT_BS2 * renderer_BlendShapeWeights[2] ;\ntangent.xyz += TANGENT_BS3 * renderer_BlendShapeWeights[3] ; \n"],[6],[0," \n"],[5,128],[0," position.xyz += POSITION_BS2 * renderer_BlendShapeWeights[2] ;\nposition.xyz += POSITION_BS3 * renderer_BlendShapeWeights[3] ;\nposition.xyz += POSITION_BS4 * renderer_BlendShapeWeights[4] ;\nposition.xyz += POSITION_BS5 * renderer_BlendShapeWeights[5] ;\nposition.xyz += POSITION_BS6 * renderer_BlendShapeWeights[6] ;\nposition.xyz += POSITION_BS7 * renderer_BlendShapeWeights[7] ; \n"],[6],[0," \n"],[6],[0," \n"],[6],[0," }\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",194],[0,"\n\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\nattribute vec3 POSITION;\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",168],[0,"\n"],[2,"RENDERER_BLENDSHAPE_USE_TEXTURE",166],[0,"attribute vec3 POSITION_BS0;\nattribute vec3 POSITION_BS1;\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},148],[0,"attribute vec3 NORMAL_BS0;\nattribute vec3 NORMAL_BS1;\nattribute vec3 TANGENT_BS0;\nattribute vec3 TANGENT_BS1;\n\n"],[5,164],[0,"\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},160],[0,"attribute vec3 POSITION_BS2;\nattribute vec3 POSITION_BS3;\n\n"],[1,"RENDERER_BLENDSHAPE_HAS_NORMAL",154],[0,"attribute vec3 NORMAL_BS0;\nattribute vec3 NORMAL_BS1;\nattribute vec3 NORMAL_BS2;\nattribute vec3 NORMAL_BS3;\n\n"],[6],[0,"\n"],[1,"RENDERER_BLENDSHAPE_HAS_TANGENT",158],[0,"attribute vec3 TANGENT_BS0;\nattribute vec3 TANGENT_BS1;\nattribute vec3 TANGENT_BS2;\nattribute vec3 TANGENT_BS3;\n\n"],[6],[0,"\n"],[5,162],[0,"attribute vec3 POSITION_BS2;\nattribute vec3 POSITION_BS3;\nattribute vec3 POSITION_BS4;\nattribute vec3 POSITION_BS5;\nattribute vec3 POSITION_BS6;\nattribute vec3 POSITION_BS7;\n\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV",172],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_UV1",176],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_SKIN",180],[0,"attribute vec4 JOINTS_0;\nattribute vec4 WEIGHTS_0;\n\n"],[6],[0,"\n"],[1,"RENDERER_ENABLE_VERTEXCOLOR",184],[0,"\n"],[6],[0,"\n"],[1,"RENDERER_HAS_NORMAL",188],[0,"attribute vec3 NORMAL;\n\n"],[6],[0,"\n"],[1,"RENDERER_HAS_TANGENT",192],[0,"attribute vec4 TANGENT;\n\n"],[6],[0,"\n\n"],[6],[0,"\nvoid main() { Varyings v ;\nvec4 position = vec4 ( POSITION , 1.0 ) ;\n\n"],[1,"RENDERER_HAS_NORMAL",202],[0," vec3 normal = vec3 ( NORMAL ) ;\n\n"],[1,"RENDERER_HAS_TANGENT",200],[0," vec4 tangent = vec4 ( TANGENT ) ; \n"],[6],[0," \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",214],[0," calculateBlendShape(position\n"],[1,"RENDERER_HAS_NORMAL",212],[0," , normal \n"],[1,"RENDERER_HAS_TANGENT",210],[0," , tangent \n"],[6],[0," \n"],[6],[0,") ; \n"],[6],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",218],[0," mat4 skinMatrix = getSkinMatrix() ;\nposition = skinMatrix * position ; \n"],[6],[0,"\ngl_Position = renderer_MVPMat * position ;\nreturn v ; }"]],"fragmentShaderInstructions":[[0,"\n"],[2,"COMMON_INCLUDED",30],[0,"\n\n"],[7,"COMMON_INCLUDED"],[0,"\n\n"],[8,"PI","3.14159265359"],[0,"\n\n"],[8,"RECIPROCAL_PI","0.31830988618"],[0,"\n\n"],[8,"EPSILON","1e-6"],[0,"\n\n"],[8,"LOG2","1.442695"],[0,"\n\n"],[8,"HALF_MIN","6.103515625e-5"],[0,"\n\n"],[8,"HALF_EPS","4.8828125e-4"],[0,"\n\n"],[9,"saturate",["a"],"clamp( a, 0.0, 1.0 )"],[0,"\n\n"],[1,"GRAPHICS_API_WEBGL2",24],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverse(mat)"],[0,"\n\n"],[5,28],[0,"\n\n"],[9,"INVERSE_MAT",["mat"],"inverseMat(mat)"],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"TRANSFORM_INCLUDED",36],[0,"\n\n"],[7,"TRANSFORM_INCLUDED"],[0,"\n\n"],[6],[0,"\n\n"],[2,"SKIN_INCLUDED",52],[0,"\n\n"],[7,"SKIN_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_SKIN",50],[0,"\n\n"],[1,"RENDERER_USE_JOINT_TEXTURE",46],[0,"\n\n"],[5,48],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"BLENDSHAPE_INCLUDED",80],[0,"\n\n"],[7,"BLENDSHAPE_INCLUDED"],[0,"\n\n"],[1,"RENDERER_HAS_BLENDSHAPE",78],[0,"\n\n"],[1,"RENDERER_BLENDSHAPE_USE_TEXTURE",62],[0,"\n\n"],[5,76],[0,"\n\n"],[4,{"t":"and","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},66],[0,"\n\n"],[5,74],[0,"\n\n"],[4,{"t":"or","l":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_NORMAL"},"r":{"t":"def","m":"RENDERER_BLENDSHAPE_HAS_TANGENT"}},70],[0,"\n\n"],[5,72],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[6],[0,"\n\n"],[2,"ATTRIBUTES_INCLUDED",86],[0,"\n\n"],[7,"ATTRIBUTES_INCLUDED"],[0,"\n\n"],[6],[0,"\nuniform vec4 camera_OutlineReplaceColor;\nvoid main() { gl_FragColor = camera_OutlineReplaceColor ; }"]]}]}]} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify generated shaders do not return a value from void main().
# Expected result: no matches.
rg -nUP 'void\s+main\s*\(\s*\)\s*\{[\s\S]*?\breturn\s+[A-Za-z_]\w*\s*;' --iglob '*.gsp'

Repository: galacean/engine-toolkit

Length of output: 50379


🏁 Script executed:

#!/bin/bash
# Extract and verify the void main() pattern in OutlineReplace.gsp specifically
# Search for the exact main function in vertex shader

rg -A 5 'void\s+main\s*\(\s*\)' packages/outline/libs/OutlineReplace.gsp | head -30

Repository: galacean/engine-toolkit

Length of output: 10860


🌐 Web query:

GLSL void main return invalid syntax

💡 Result:

In GLSL shaders, the entry point function must be declared exactly as void main. It takes no parameters and returns no value. A return statement with a value (e.g., return someValue;) inside main is invalid syntax because main is void. return; without a value is allowed in main for early exit, equivalent to reaching the end of the function. It does not require writing to all outputs beforehand; unwritten outputs behave as if the end of main was reached. This applies to both desktop GLSL and GLSL ES. Using return expr; (non-void expression) in void main triggers a compile-time syntax or semantic error, such as "void function cannot return a value". Correct syntax: void main { // code return; // OK: early exit } Invalid: void main { return 42; // ERROR: invalid syntax } Official specs confirm main must be void with no parameters or return value.

Citations:


Remove invalid return statement from void main() in the vertex shader.

The vertex shader contains void main() { ... return v; }. According to GLSL specification, void main() cannot return a value—only return; for early exit is valid. This will cause shader compilation to fail at runtime. Fix the source shader template (then regenerate the .gsp file) to remove the return value.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/outline/libs/OutlineReplace.gsp` at line 1, The vertex shader's void
main() incorrectly uses "return v;" which returns a value from a void function
(see the main() function and the Varyings v declaration); remove the returned
expression so the function either ends without a return or uses a bare "return;"
for early exit. Update the shader template that generates the vertex main (look
for the sequence "void main() { Varyings v ;" and the trailing "return v;") to
drop the value from the return, then regenerate the .gsp output.

The repo had `husky: ^8.0.3` in devDeps but kept the v4-style
`husky.hooks` block in package.json plus stale v4-era scripts in
`.git/hooks/`. v8 doesn't read the v4 config, and the leftover
`pnpx --no-install husky-run` invocation in the v4 hooks crashes
under modern pnpm (which routes `pnpx` to `pnpm dlx` and rejects
`--no-install` as a package name). Net effect: per-developer hook
behavior was an open box — some envs ran broken hooks, others ran
none.

Migrate to the v8 standard:

- Drop the `husky.hooks` config from package.json.
- Add `prepare: husky install` so `pnpm install` initializes hooks
  on every fresh clone, pointing `core.hooksPath` at `.husky/`.
- Commit `.husky/pre-commit` (lint-staged) and `.husky/commit-msg`
  (commitlint) so all devs share the same hook content via git.
- Auto-generated `.husky/_/` is gitignored by husky install.

After this, `.git/hooks/` becomes irrelevant (git reads
`core.hooksPath`), so each dev's stale v4 leftovers no longer fire.
Each package's `src/index.ts` now does `export * from "../libs"`,
mirroring engine's pattern. Two effects:

1. `libs/index.ts` joins the TS project graph through the include
   chain, so the IDE resolves `*.gsp` imports via `src/global.d.ts`
   (extended with `declare module "*.gsp"`). Drops the previous
   `libs/global.d.ts` sidecar + auto-emitted triple-slash hint.

2. tsc auto-adjusts rootDir to the package root because `src/`
   imports cross into `../libs/`, shifting emitted declarations under
   `types/src/...`. Update each `package.json` `"types"` path
   accordingly — matches engine's existing layout.

Verified: `pnpm clean && pnpm b:all` succeeds end-to-end; all 8
packages emit types at the new paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant