Skip to content

ShaderLab: #define macro not expanded in swizzle position #2952

@GuoLei1990

Description

@GuoLei1990

Description

ShaderLab's compiler does not expand #define macros when used in swizzle position (after .). This is valid in standard GLSL but fails in ShaderLab.

Reproduction

#define OCCLUSION_CHANNEL r
#define ROUGHNESS_CHANNEL g
#define METALLIC_CHANNEL b

vec4 res = texture2D(pbrMap, v.v_uv);
pbr.x *= res.OCCLUSION_CHANNEL;   // ❌ CompilationError: Unexpected token OCCLUSION_CHANNEL
pbr.y *= res.ROUGHNESS_CHANNEL;
pbr.z *= res.METALLIC_CHANNEL;

Expected behavior

The preprocessor should expand OCCLUSION_CHANNEL to r before the compiler parses the swizzle, resulting in res.r — which is valid GLSL.

Actual behavior

CompilationError: Unexpected token OCCLUSION_CHANNEL

The compiler encounters OCCLUSION_CHANNEL as an unknown identifier in swizzle position because macro expansion did not occur before swizzle parsing.

Workaround

Replace macro-based swizzle with literal channel names:

pbr.x *= res.r;   // occlusion
pbr.y *= res.g;   // roughness
pbr.z *= res.b;   // metallic

Context

Discovered during Cocos Creator → Galacean ShaderLab migration. Cocos shaders commonly use #define to abstract channel selection (e.g., #pragma define-meta ALPHA_TEST_CHANNEL options([a, r, g, b])), which works in standard GLSL but breaks in ShaderLab.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions