Cannot access ENUM typed properties in property textures from custom shader
- Dominant language
- JavaScript
- Stars
- 15.7k
- Forks
- 3.9k
- Avg merge
- 4d 6h
- Merged PRs (30d)
- 34
Description
The attached archive contains a `tileset.json` that refers to an embedded glTF asset with something that is _supposed_ to be a valid property texture with `ENUM` typed properties.
(Note: Creating this glTF asset involved some manual tweaks. It _might_ be something wrong with the structure, but I _think_ that it should be valid for now)
It also contains a sandcastle that can be used to show the asset, and to select a custom shader for each of the properties.
[PropertyTextureEnumCesiumIssue-2023-10-02.zip](https://github.com/CesiumGS/cesium/files/12782354/PropertyTextureEnumCesiumIssue-2023-10-02.zip)
The first property is defined as
```
"enumProperty" : {
"name" : "Example enum property",
"type" : "ENUM",
"enumType" : "exampleEnum",
"noData" : "NO_DATA_ENUM_VALUE",
"default" : "DEFAULT_ENUM_VALUE"
},
```
and stored in channel 0 of the texture.
In the custom shader, the `enumProperty` is accessed as
```
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
int value = int(fsInput.metadata.${propertyName});
if (value == 0) material.diffuse = vec3(1,0,0);
...
```
The `fsInput.metadata` does not seem to contain the expected `fsInput.metadata.enumProperty` at this point. So when selecting the `enumProperty` shader from the dropdown menu, the compilation bails out
I'll just dump the error output here, maybe somebody knows what to look for and can already tell whether this is just a simple mistake/misunderstanding, or an actual issue:
```
[Cesium WebGL] Fragment shader compile log: ERROR: 0:3: 'enumProperty' : no such field in structure
ERROR: 0:3: 'constructor' : a struct cannot be used as a constructor argument for this type
[Cesium WebGL] Fragment shader source:
#version 300 es
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
precision highp int;
#else
precision mediump float;
precision mediump int;
#define highp mediump
#endif
#define USE_IBL_LIGHTING
#define USE_SUN_LUMINANCE
#define HAS_NORMALS
#define HAS_TEXCOORD_0
#define USE_METALLIC_ROUGHNESS
#define HAS_BASE_COLOR_FACTOR
#define HAS_METALLIC_FACTOR
#define HAS_DOUBLE_SIDED_MATERIAL
#define HAS_CUSTOM_FRAGMENT_SHADER
#define CUSTOM_SHADER_MODIFY_MATERIAL
#define LIGHTING_PBR
#define LOG_DEPTH
#define OES_texture_float_linear
#define OES_texture_float
#line 0
layout(location = 0) out vec4 out_FragColor;
const float czm_epsilon7 = 0.0000001;
uniform float czm_oneOverLog2FarDepthFromNearPlusOne;
uniform float czm_farDepthFromNearPlusOne;
uniform float czm_gamma;
struct czm_pbrParameters
{
vec3 diffuseColor;
float roughness;
vec3 f0;
};
const float czm_pi = 3.141592653589793;
#ifdef LOG_DEPTH
in float v_depthFromNearPlusOne;
#ifdef POLYGON_OFFSET
uniform vec2 u_polygonOffset;
#endif
#endif
void czm_writeLogDepth(float depth)
{
#if (defined(LOG_DEPTH) && (__VERSION__ == 300 || defined(GL_EXT_frag_depth)))
if (depth <= 0.9999999 || depth > czm_farDepthFromNearPlusOne) {
discard;
}
#ifdef POLYGON_OFFSET
float factor = u_polygonOffset[0];
float units = u_polygonOffset[1];
#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))
if (factor != 0.0) {
float x = dFdx(depth);
float y = dFdy(depth);
float m = sqrt(x * x + y * y);
depth += m * factor;
}
#endif
#endif
gl_FragDepth = log2(depth) * czm_oneOverLog2FarDepthFromNearPlusOne;
#ifdef POLYGON_OFFSET
gl_FragDepth += czm_epsilon7 * units;
#endif
#endif
}
void czm_writeLogDepth() {
#ifdef LOG_DEPTH
czm_writeLogDepth(v_depthFromNearPlusOne);
#endif
}
vec3 czm_linearToSrgb(vec3 linearIn)
{
return pow(linearIn, vec3(1.0/2.2));
}
vec4 czm_linearToSrgb(vec4 linearIn)
{
vec3 srgbOut = pow(linearIn.rgb, vec3(1.0/2.2));
return vec4(srgbOut, linearIn.a);
}
vec3 czm_gammaCorrect(vec3 color) {
#ifdef HDR
color = pow(color, vec3(czm_gamma));
#endif
return color;
}
vec4 czm_gammaCorrect(vec4 color) {
#ifdef HDR
color.rgb = pow(color.rgb, vec3(czm_gamma));
#endif
return color;
}
vec3 czm_acesTonemapping(vec3 color) {
float g = 0.985;
float a = 0.065;
float b = 0.0001;
float c = 0.433;
float d = 0.238;
color = (color * (color + a) - b) / (color * (g * color + c) + d);
color = clamp(color, 0.0, 1.0);
return color;
}
uniform vec3 czm_lightDirectionEC;
vec3 lambertianDiffuse(vec3 diffuseColor)
{
return diffuseColor / czm_pi;
}
vec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH)
{
return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
}
float smithVisibilityG1(float NdotV, float roughness)
{
float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
return NdotV / (NdotV * (1.0 - k) + k);
}
float smithVisibilityGGX(float roughness, float NdotL, float NdotV)
{
return (
smithVisibilityG1(NdotL, roughness) *
smithVisibilityG1(NdotV, roughness)
);
}
float GGX(float roughness, float NdotH)
{
float roughnessSquared = roughness * roughness;
float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;
return roughnessSquared / (czm_pi * f * f);
}
vec3 czm_pbrLighting(
vec3 positionEC,
vec3 normalEC,
vec3 lightDirectionEC,
vec3 lightColorHdr,
czm_pbrParameters pbrParameters
)
{
vec3 v = -normalize(positionEC);
vec3 l = normalize(lightDirectionEC);
vec3 h = normalize(v + l);
vec3 n = normalEC;
float NdotL = clamp(dot(n, l), 0.001, 1.0);
float NdotV = abs(dot(n, v)) + 0.001;
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);
vec3 f0 = pbrParameters.f0;
float reflectance = max(max(f0.r, f0.g), f0.b);
vec3 f90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));
vec3 F = fresnelSchlick2(f0, f90, VdotH);
float alpha = pbrParameters.roughness;
float G = smithVisibilityGGX(alpha, NdotL, NdotV);
float D = GGX(alpha, NdotH);
vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV);
vec3 diffuseColor = pbrParameters.diffuseColor;
vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(diffuseColor);
return (diffuseContribution + specularContribution) * NdotL * lightColorHdr;
}
uniform vec3 czm_lightColorHdr;
czm_pbrParameters czm_pbrMetallicRoughnessMaterial(
vec3 baseColor,
float metallic,
float roughness
)
{
czm_pbrParameters results;
roughness = clamp(roughness, 0.0, 1.0);
results.roughness = roughness * roughness;
metallic = clamp(metallic, 0.0, 1.0);
const vec3 REFLECTANCE_DIELECTRIC = vec3(0.04);
vec3 f0 = mix(REFLECTANCE_DIELECTRIC, baseColor, metallic);
results.f0 = f0;
results.diffuseColor = baseColor * (1.0 - f0) * (1.0 - metallic);
return results;
}
czm_pbrParameters czm_pbrSpecularGlossinessMaterial(
vec3 diffuse,
vec3 specular,
float glossiness
)
{
czm_pbrParameters results;
float roughness = 1.0 - glossiness;
results.roughness = roughness * roughness;
results.diffuseColor = diffuse * (1.0 - max(max(specular.r, specular.g), specular.b));
results.f0 = specular;
return results;
}
struct czm_modelMaterial {
vec3 diffuse;
float alpha;
vec3 specular;
float roughness;
vec3 normalEC;
float occlusion;
vec3 emissive;
};
bool czm_backFacing()
{
return gl_FrontFacing == false;
}
const float czm_epsilon3 = 0.001;
uniform float czm_specularEnvironmentMapsMaximumLOD;
uniform vec2 czm_specularEnvironmentMapSize;
uniform sampler2D czm_specularEnvironmentMaps;
vec3 czm_sampleOctahedralProjectionWithFiltering(sampler2D projectedMap, vec2 textureSize, vec3 direction, float lod)
{
direction /= dot(vec3(1.0), abs(direction));
vec2 rev = abs(direction.zx) - vec2(1.0);
vec2 neg = vec2(direction.x < 0.0 ? rev.x : -rev.x,
direction.z < 0.0 ? rev.y : -rev.y);
vec2 uv = direction.y < 0.0 ? neg : direction.xz;
vec2 coord = 0.5 * uv + vec2(0.5);
vec2 pixel = 1.0 / textureSize;
if (lod > 0.0)
{
float scale = 1.0 / pow(2.0, lod);
float offset = ((textureSize.y + 1.0) / textureSize.x);
coord.x *= offset;
coord *= scale;
coord.x += offset + pixel.x;
coord.y += (1.0 - (1.0 / pow(2.0, lod - 1.0))) + pixel.y * (lod - 1.0) * 2.0;
}
else
{
coord.x *= (textureSize.y / textureSize.x);
}
#ifndef OES_texture_float_linear
vec3 color1 = texture(projectedMap, coord + vec2(0.0, pixel.y)).rgb;
vec3 color2 = texture(projectedMap, coord + vec2(pixel.x, 0.0)).rgb;
vec3 color3 = texture(projectedMap, coord + pixel).rgb;
vec3 color4 = texture(projectedMap, coord).rgb;
vec2 texturePosition = coord * textureSize;
float fu = fract(texturePosition.x);
float fv = fract(texturePosition.y);
vec3 average1 = mix(color4, color2, fu);
vec3 average2 = mix(color1, color3, fu);
vec3 color = mix(average1, average2, fv);
#else
vec3 color = texture(projectedMap, coord).rgb;
#endif
return color;
}
vec3 czm_sampleOctahedralProjection(sampler2D projectedMap, vec2 textureSize, vec3 direction, float lod, float maxLod) {
float currentLod = floor(lod + 0.5);
float nextLod = min(currentLod + 1.0, maxLod);
vec3 colorCurrentLod = czm_sampleOctahedralProjectionWithFiltering(projectedMap, textureSize, direction, currentLod);
vec3 colorNextLod = czm_sampleOctahedralProjectionWithFiltering(projectedMap, textureSize, direction, nextLod);
return mix(colorNextLod, colorCurrentLod, nextLod - lod);
}
uniform vec3 czm_sphericalHarmonicCoefficients[9];
vec3 czm_sphericalHarmonics(vec3 normal, vec3 coefficients[9])
{
vec3 L00 = coefficients[0];
vec3 L1_1 = coefficients[1];
vec3 L10 = coefficients[2];
vec3 L11 = coefficients[3];
vec3 L2_2 = coefficients[4];
vec3 L2_1 = coefficients[5];
vec3 L20 = coefficients[6];
vec3 L21 = coefficients[7];
vec3 L22 = coefficients[8];
float x = normal.x;
float y = normal.y;
float z = normal.z;
return
L00
+ L1_1 * y
+ L10 * z
+ L11 * x
+ L2_2 * (y * x)
+ L2_1 * (y * z)
+ L20 * (3.0 * z * z - 1.0)
+ L21 * (z * x)
+ L22 * (x * x - y * y);
}
vec3 czm_srgbToLinear(vec3 srgbIn)
{
return pow(srgbIn, vec3(2.2));
}
vec4 czm_srgbToLinear(vec4 srgbIn)
{
vec3 linearOut = pow(srgbIn.rgb, vec3(2.2));
return vec4(linearOut, srgbIn.a);
}
uniform sampler2D czm_brdfLut;
uniform samplerCube czm_environmentMap;
vec4 czm_textureCube(samplerCube sampler, vec3 p) {
#if __VERSION__ == 300
return texture(sampler, p);
#else
return textureCube(sampler, p);
#endif
}
uniform mat3 czm_temeToPseudoFixed;
uniform vec3 czm_ellipsoidRadii;
uniform mat3 czm_inverseViewRotation;
uniform mat4 czm_inverseView;
#line 0
uniform vec2 model_iblFactor;
uniform mat3 model_iblReferenceFrameMatrix;
uniform float model_luminanceAtZenith;
uniform vec4 u_baseColorFactor;
uniform float u_metallicFactor;
uniform vec4 czm_pickColor;
in vec3 v_positionWC;
in vec3 v_positionEC;
in vec3 v_positionMC;
in vec3 v_normalEC;
in vec2 v_texCoord_0;
struct ProcessedAttributes
{
vec3 positionWC;
vec3 positionEC;
vec3 positionMC;
vec3 normalEC;
vec2 texCoord_0;
};
struct SelectedFeature
{
float _empty;
};
struct FeatureIds
{
float _empty;
};
struct Metadata
{
float _empty;
};
struct MetadataClass
{
float _empty;
};
struct MetadataStatistics
{
float _empty;
};
struct Attributes
{
float _empty;
};
struct FragmentInput
{
Attributes attributes;
FeatureIds featureIds;
Metadata metadata;
MetadataClass metadataClass;
MetadataStatistics metadataStatistics;
};
void setDynamicVaryings(inout ProcessedAttributes attributes)
{
attributes.texCoord_0 = v_texCoord_0;
}
void initializeFeatureIds(out FeatureIds featureIds, ProcessedAttributes attributes)
{
}
void initializeFeatureIdAliases(inout FeatureIds featureIds)
{
}
void initializeMetadata(out Metadata metadata, out MetadataClass metadataClass, out MetadataStatistics metadataStatistics, ProcessedAttributes attributes)
{
}
void initializeInputStruct(out FragmentInput fsInput, ProcessedAttributes attributes)
{
}
vec3 proceduralIBL(
vec3 positionEC,
vec3 normalEC,
vec3 lightDirectionEC,
vec3 lightColorHdr,
czm_pbrParameters pbrParameters
) {
vec3 v = -positionEC;
vec3 positionWC = vec3(czm_inverseView * vec4(positionEC, 1.0));
vec3 vWC = -normalize(positionWC);
vec3 l = normalize(lightDirectionEC);
vec3 n = normalEC;
vec3 r = normalize(czm_inverseViewRotation * normalize(reflect(v, n)));
float NdotL = clamp(dot(n, l), 0.001, 1.0);
float NdotV = abs(dot(n, v)) + 0.001;
float vertexRadius = length(positionWC);
float horizonDotNadir = 1.0 - min(1.0, czm_ellipsoidRadii.x / vertexRadius);
float reflectionDotNadir = dot(r, normalize(positionWC));
r.x = -r.x;
r = -normalize(czm_temeToPseudoFixed * r);
r.x = -r.x;
vec3 diffuseColor = pbrParameters.diffuseColor;
float roughness = pbrParameters.roughness;
vec3 specularColor = pbrParameters.f0;
float inverseRoughness = 1.04 - roughness;
inverseRoughness *= inverseRoughness;
vec3 sceneSkyBox = czm_textureCube(czm_environmentMap, r).rgb * inverseRoughness;
float atmosphereHeight = 0.05;
float blendRegionSize = 0.1 * ((1.0 - inverseRoughness) * 8.0 + 1.1 - horizonDotNadir);
float blendRegionOffset = roughness * -1.0;
float farAboveHorizon = clamp(horizonDotNadir - blendRegionSize * 0.5 + blendRegionOffset, 1.0e-10 - blendRegionSize, 0.99999);
float aroundHorizon = clamp(horizonDotNadir + blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999);
float farBelowHorizon = clamp(horizonDotNadir + blendRegionSize * 1.5, 1.0e-10 - blendRegionSize, 0.99999);
float smoothstepHeight = smoothstep(0.0, atmosphereHeight, horizonDotNadir);
vec3 belowHorizonColor = mix(vec3(0.1, 0.15, 0.25), vec3(0.4, 0.7, 0.9), smoothstepHeight);
vec3 nadirColor = belowHorizonColor * 0.5;
vec3 aboveHorizonColor = mix(vec3(0.9, 1.0, 1.2), belowHorizonColor, roughness * 0.5);
vec3 blueSkyColor = mix(vec3(0.18, 0.26, 0.48), aboveHorizonColor, reflectionDotNadir * inverseRoughness * 0.5 + 0.75);
vec3 zenithColor = mix(blueSkyColor, sceneSkyBox, smoothstepHeight);
vec3 blueSkyDiffuseColor = vec3(0.7, 0.85, 0.9);
float diffuseIrradianceFromEarth = (1.0 - horizonDotNadir) * (reflectionDotNadir * 0.25 + 0.75) * smoothstepHeight;
float diffuseIrradianceFromSky = (1.0 - smoothstepHeight) * (1.0 - (reflectionDotNadir * 0.25 + 0.25));
vec3 diffuseIrradiance = blueSkyDiffuseColor * clamp(diffuseIrradianceFromEarth + diffuseIrradianceFromSky, 0.0, 1.0);
float notDistantRough = (1.0 - horizonDotNadir * roughness * 0.8);
vec3 specularIrradiance = mix(zenithColor, aboveHorizonColor, smoothstep(farAboveHorizon, aroundHorizon, reflectionDotNadir) * notDistantRough);
specularIrradiance = mix(specularIrradiance, belowHorizonColor, smoothstep(aroundHorizon, farBelowHorizon, reflectionDotNadir) * inverseRoughness);
specularIrradiance = mix(specularIrradiance, nadirColor, smoothstep(farBelowHorizon, 1.0, reflectionDotNadir) * inverseRoughness);
#ifdef USE_SUN_LUMINANCE
float LdotZenith = clamp(dot(normalize(czm_inverseViewRotation * l), vWC), 0.001, 1.0);
float S = acos(LdotZenith);
float NdotZenith = clamp(dot(normalize(czm_inverseViewRotation * n), vWC), 0.001, 1.0);
float gamma = acos(NdotL);
float numerator = ((0.91 + 10.0 * exp(-3.0 * gamma) + 0.45 * pow(NdotL, 2.0)) * (1.0 - exp(-0.32 / NdotZenith)));
float denominator = (0.91 + 10.0 * exp(-3.0 * S) + 0.45 * pow(LdotZenith,2.0)) * (1.0 - exp(-0.32));
float luminance = model_luminanceAtZenith * (numerator / denominator);
#endif
vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;
vec3 iblColor = (diffuseIrradiance * diffuseColor * model_iblFactor.x) + (specularIrradiance * czm_srgbToLinear(specularColor * brdfLut.x + brdfLut.y) * model_iblFactor.y);
float maximumComponent = max(max(lightColorHdr.x, lightColorHdr.y), lightColorHdr.z);
vec3 lightColor = lightColorHdr / max(maximumComponent, 1.0);
iblColor *= lightColor;
#ifdef USE_SUN_LUMINANCE
iblColor *= luminance;
#endif
return iblColor;
}
#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)
vec3 textureIBL(
vec3 positionEC,
vec3 normalEC,
vec3 lightDirectionEC,
czm_pbrParameters pbrParameters
) {
vec3 diffuseColor = pbrParameters.diffuseColor;
float roughness = pbrParameters.roughness;
vec3 specularColor = pbrParameters.f0;
vec3 v = -positionEC;
vec3 n = normalEC;
vec3 l = normalize(lightDirectionEC);
vec3 h = normalize(v + l);
float NdotV = abs(dot(n, v)) + 0.001;
float VdotH = clamp(dot(v, h), 0.0, 1.0);
const mat3 yUpToZUp = mat3(
-1.0, 0.0, 0.0,
0.0, 0.0, -1.0,
0.0, 1.0, 0.0
);
vec3 cubeDir = normalize(yUpToZUp * model_iblReferenceFrameMatrix * normalize(reflect(-v, n)));
#ifdef DIFFUSE_IBL
#ifdef CUSTOM_SPHERICAL_HARMONICS
vec3 diffuseIrradiance = czm_sphericalHarmonics(cubeDir, model_sphericalHarmonicCoefficients);
#else
vec3 diffuseIrradiance = czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients);
#endif
#else
vec3 diffuseIrradiance = vec3(0.0);
#endif
#ifdef SPECULAR_IBL
vec3 r0 = specularColor.rgb;
float reflectance = max(max(r0.r, r0.g), r0.b);
vec3 r90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));
vec3 F = fresnelSchlick2(r0, r90, VdotH);
vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;
#ifdef CUSTOM_SPECULAR_IBL
vec3 specularIBL = czm_sampleOctahedralProjection(model_specularEnvironmentMaps, model_specularEnvironmentMapsSize, cubeDir, roughness * model_specularEnvironmentMapsMaximumLOD, model_specularEnvironmentMapsMaximumLOD);
#else
vec3 specularIBL = czm_sampleOctahedralProjection(czm_specularEnvironmentMaps, czm_specularEnvironmentMapSize, cubeDir, roughness * czm_specularEnvironmentMapsMaximumLOD, czm_specularEnvironmentMapsMaximumLOD);
#endif
specularIBL *= F * brdfLut.x + brdfLut.y;
#else
vec3 specularIBL = vec3(0.0);
#endif
return diffuseColor * diffuseIrradiance + specularColor * specularIBL;
}
#endif
vec3 imageBasedLightingStage(
vec3 positionEC,
vec3 normalEC,
vec3 lightDirectionEC,
vec3 lightColorHdr,
czm_pbrParameters pbrParameters
) {
#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)
return textureIBL(
positionEC,
normalEC,
lightDirectionEC,
pbrParameters
);
#else
return proceduralIBL(
positionEC,
normalEC,
lightDirectionEC,
lightColorHdr,
pbrParameters
);
#endif
}
void geometryStage(out ProcessedAttributes attributes)
{
attributes.positionMC = v_positionMC;
attributes.positionEC = v_positionEC;
#ifdef COMPUTE_POSITION_WC_CUSTOM_SHADER
attributes.positionWC = v_positionWC;
#endif
#ifdef HAS_NORMALS
attributes.normalEC = normalize(v_normalEC);
#endif
#ifdef HAS_TANGENTS
attributes.tangentEC = normalize(v_tangentEC);
#endif
#ifdef HAS_BITANGENTS
attributes.bitangentEC = normalize(v_bitangentEC);
#endif
setDynamicVaryings(attributes);
}
bool isDefaultStyleColor(vec3 color)
{
return all(greaterThan(color, vec3(1.0 - czm_epsilon3)));
}
vec3 blend(vec3 sourceColor, vec3 styleColor, float styleColorBlend)
{
vec3 blendColor = mix(sourceColor, styleColor, styleColorBlend);
vec3 color = isDefaultStyleColor(styleColor.rgb) ? sourceColor : blendColor;
return color;
}
vec2 computeTextureTransform(vec2 texCoord, mat3 textureTransform)
{
return vec2(textureTransform * vec3(texCoord, 1.0));
}
#ifdef HAS_NORMALS
vec3 computeNormal(ProcessedAttributes attributes)
{
vec3 ng = attributes.normalEC;
vec3 normal = ng;
#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)
vec2 normalTexCoords = TEXCOORD_NORMAL;
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM
normalTexCoords = computeTextureTransform(normalTexCoords, u_normalTextureTransform);
#endif
#ifdef HAS_BITANGENTS
vec3 t = attributes.tangentEC;
vec3 b = attributes.bitangentEC;
mat3 tbn = mat3(t, b, ng);
vec3 n = texture(u_normalTexture, normalTexCoords).rgb;
normal = normalize(tbn * (2.0 * n - 1.0));
#elif (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))
vec3 positionEC = attributes.positionEC;
vec3 pos_dx = dFdx(positionEC);
vec3 pos_dy = dFdy(positionEC);
vec3 tex_dx = dFdx(vec3(normalTexCoords,0.0));
vec3 tex_dy = dFdy(vec3(normalTexCoords,0.0));
vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
t = normalize(t - ng * dot(ng, t));
vec3 b = normalize(cross(ng, t));
mat3 tbn = mat3(t, b, ng);
vec3 n = texture(u_normalTexture, normalTexCoords).rgb;
normal = normalize(tbn * (2.0 * n - 1.0));
#endif
#endif
#ifdef HAS_DOUBLE_SIDED_MATERIAL
if (czm_backFacing()) {
normal = -normal;
}
#endif
return normal;
}
#endif
void materialStage(inout czm_modelMaterial material, ProcessedAttributes attributes, SelectedFeature feature)
{
#ifdef HAS_NORMALS
material.normalEC = computeNormal(attributes);
#endif
vec4 baseColorWithAlpha = vec4(1.0);
#ifdef HAS_BASE_COLOR_TEXTURE
vec2 baseColorTexCoords = TEXCOORD_BASE_COLOR;
#ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM
baseColorTexCoords = computeTextureTransform(baseColorTexCoords, u_baseColorTextureTransform);
#endif
baseColorWithAlpha = czm_srgbToLinear(texture(u_baseColorTexture, baseColorTexCoords));
#ifdef HAS_BASE_COLOR_FACTOR
baseColorWithAlpha *= u_baseColorFactor;
#endif
#elif defined(HAS_BASE_COLOR_FACTOR)
baseColorWithAlpha = u_baseColorFactor;
#endif
#ifdef HAS_POINT_CLOUD_COLOR_STYLE
baseColorWithAlpha = v_pointCloudColor;
#elif defined(HAS_COLOR_0)
vec4 color = attributes.color_0;
#ifdef HAS_SRGB_COLOR
color = czm_srgbToLinear(color);
#endif
baseColorWithAlpha *= color;
#endif
material.diffuse = baseColorWithAlpha.rgb;
material.alpha = baseColorWithAlpha.a;
#ifdef USE_CPU_STYLING
material.diffuse = blend(material.diffuse, feature.color.rgb, model_colorBlend);
#endif
#ifdef HAS_OCCLUSION_TEXTURE
vec2 occlusionTexCoords = TEXCOORD_OCCLUSION;
#ifdef HAS_OCCLUSION_TEXTURE_TRANSFORM
occlusionTexCoords = computeTextureTransform(occlusionTexCoords, u_occlusionTextureTransform);
#endif
material.occlusion = texture(u_occlusionTexture, occlusionTexCoords).r;
#endif
#ifdef HAS_EMISSIVE_TEXTURE
vec2 emissiveTexCoords = TEXCOORD_EMISSIVE;
#ifdef HAS_EMISSIVE_TEXTURE_TRANSFORM
emissiveTexCoords = computeTextureTransform(emissiveTexCoords, u_emissiveTextureTransform);
#endif
vec3 emissive = czm_srgbToLinear(texture(u_emissiveTexture, emissiveTexCoords).rgb);
#ifdef HAS_EMISSIVE_FACTOR
emissive *= u_emissiveFactor;
#endif
material.emissive = emissive;
#elif defined(HAS_EMISSIVE_FACTOR)
material.emissive = u_emissiveFactor;
#endif
#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)
#ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE
vec2 specularGlossinessTexCoords = TEXCOORD_SPECULAR_GLOSSINESS;
#ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE_TRANSFORM
specularGlossinessTexCoords = computeTextureTransform(specularGlossinessTexCoords, u_specularGlossinessTextureTransform);
#endif
vec4 specularGlossiness = czm_srgbToLinear(texture(u_specularGlossinessTexture, specularGlossinessTexCoords));
vec3 specular = specularGlossiness.rgb;
float glossiness = specularGlossiness.a;
#ifdef HAS_SPECULAR_FACTOR
specular *= u_specularFactor;
#endif
#ifdef HAS_GLOSSINESS_FACTOR
glossiness *= u_glossinessFactor;
#endif
#else
#ifdef HAS_SPECULAR_FACTOR
vec3 specular = clamp(u_specularFactor, vec3(0.0), vec3(1.0));
#else
vec3 specular = vec3(1.0);
#endif
#ifdef HAS_GLOSSINESS_FACTOR
float glossiness = clamp(u_glossinessFactor, 0.0, 1.0);
#else
float glossiness = 1.0;
#endif
#endif
#ifdef HAS_DIFFUSE_TEXTURE
vec2 diffuseTexCoords = TEXCOORD_DIFFUSE;
#ifdef HAS_DIFFUSE_TEXTURE_TRANSFORM
diffuseTexCoords = computeTextureTransform(diffuseTexCoords, u_diffuseTextureTransform);
#endif
vec4 diffuse = czm_srgbToLinear(texture(u_diffuseTexture, diffuseTexCoords));
#ifdef HAS_DIFFUSE_FACTOR
diffuse *= u_diffuseFactor;
#endif
#elif defined(HAS_DIFFUSE_FACTOR)
vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0));
#else
vec4 diffuse = vec4(1.0);
#endif
czm_pbrParameters parameters = czm_pbrSpecularGlossinessMaterial(
diffuse.rgb,
specular,
glossiness
);
material.diffuse = parameters.diffuseColor;
material.alpha = diffuse.a;
material.specular = parameters.f0;
material.roughness = parameters.roughness;
#elif defined(LIGHTING_PBR)
#ifdef HAS_METALLIC_ROUGHNESS_TEXTURE
vec2 metallicRoughnessTexCoords = TEXCOORD_METALLIC_ROUGHNESS;
#ifdef HAS_METALLIC_ROUGHNESS_TEXTURE_TRANSFORM
metallicRoughnessTexCoords = computeTextureTransform(metallicRoughnessTexCoords, u_metallicRoughnessTextureTransform);
#endif
vec3 metallicRoughness = texture(u_metallicRoughnessTexture, metallicRoughnessTexCoords).rgb;
float metalness = clamp(metallicRoughness.b, 0.0, 1.0);
float roughness = clamp(metallicRoughness.g, 0.04, 1.0);
#ifdef HAS_METALLIC_FACTOR
metalness *= u_metallicFactor;
#endif
#ifdef HAS_ROUGHNESS_FACTOR
roughness *= u_roughnessFactor;
#endif
#else
#ifdef HAS_METALLIC_FACTOR
float metalness = clamp(u_metallicFactor, 0.0, 1.0);
#else
float metalness = 1.0;
#endif
#ifdef HAS_ROUGHNESS_FACTOR
float roughness = clamp(u_roughnessFactor, 0.04, 1.0);
#else
float roughness = 1.0;
#endif
#endif
czm_pbrParameters parameters = czm_pbrMetallicRoughnessMaterial(
material.diffuse,
metalness,
roughness
);
material.diffuse = parameters.diffuseColor;
material.specular = parameters.f0;
material.roughness = parameters.roughness;
#endif
}
void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) {
initializeFeatureIds(featureIds, attributes);
initializeFeatureIdAliases(featureIds);
}
void metadataStage(
out Metadata metadata,
out MetadataClass metadataClass,
out MetadataStatistics metadataStatistics,
ProcessedAttributes attributes
)
{
initializeMetadata(metadata, metadataClass, metadataStatistics, attributes);
}
#line 0
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
int value = int(fsInput.metadata.enumProperty);
if (value == 0) material.diffuse = vec3(1,0,0);
else if (value == 1) material.diffuse = vec3(0,1,0);
else if (value == 2) material.diffuse = vec3(0,0,1);
else if (value == 3) material.diffuse = vec3(1,1,0);
else material.diffuse = vec3(1,0,1);
}
void customShaderStage(
inout czm_modelMaterial material,
ProcessedAttributes attributes,
FeatureIds featureIds,
Metadata metadata,
MetadataClass metadataClass,
MetadataStatistics metadataStatistics
) {
FragmentInput fsInput;
initializeInputStruct(fsInput, attributes);
fsInput.featureIds = featureIds;
fsInput.metadata = metadata;
fsInput.metadataClass = metadataClass;
fsInput.metadataStatistics = metadataStatistics;
fragmentMain(fsInput, material);
}
#ifdef LIGHTING_PBR
vec3 computePbrLighting(czm_modelMaterial inputMaterial, ProcessedAttributes attributes)
{
czm_pbrParameters pbrParameters;
pbrParameters.diffuseColor = inputMaterial.diffuse;
pbrParameters.f0 = inputMaterial.specular;
pbrParameters.roughness = inputMaterial.roughness;
#ifdef USE_CUSTOM_LIGHT_COLOR
vec3 lightColorHdr = model_lightColorHdr;
#else
vec3 lightColorHdr = czm_lightColorHdr;
#endif
vec3 color = inputMaterial.diffuse;
#ifdef HAS_NORMALS
color = czm_pbrLighting(
attributes.positionEC,
inputMaterial.normalEC,
czm_lightDirectionEC,
lightColorHdr,
pbrParameters
);
#ifdef USE_IBL_LIGHTING
color += imageBasedLightingStage(
attributes.positionEC,
inputMaterial.normalEC,
czm_lightDirectionEC,
lightColorHdr,
pbrParameters
);
#endif
#endif
color *= inputMaterial.occlusion;
color += inputMaterial.emissive;
#ifndef HDR
color = czm_acesTonemapping(color);
#endif
return color;
}
#endif
void lightingStage(inout czm_modelMaterial material, ProcessedAttributes attributes)
{
vec3 color = vec3(0.0);
#ifdef LIGHTING_PBR
color = computePbrLighting(material, attributes);
#else
color = material.diffuse;
#endif
#ifdef HAS_POINT_CLOUD_COLOR_STYLE
color = czm_gammaCorrect(color);
#elif !defined(HDR)
color = czm_linearToSrgb(color);
#endif
material.diffuse = color;
}
czm_modelMaterial defaultModelMaterial()
{
czm_modelMaterial material;
material.diffuse = vec3(0.0);
material.specular = vec3(1.0);
material.roughness = 1.0;
material.occlusion = 1.0;
material.normalEC = vec3(0.0, 0.0, 1.0);
material.emissive = vec3(0.0);
material.alpha = 1.0;
return material;
}
vec4 handleAlpha(vec3 color, float alpha)
{
#ifdef ALPHA_MODE_MASK
if (alpha < u_alphaCutoff) {
discard;
}
#endif
return vec4(color, alpha);
}
SelectedFeature selectedFeature;
void czm_log_depth_main()
{
#ifdef HAS_MODEL_SPLITTER
modelSplitterStage();
#endif
czm_modelMaterial material = defaultModelMaterial();
ProcessedAttributes attributes;
geometryStage(attributes);
FeatureIds featureIds;
featureIdStage(featureIds, attributes);
Metadata metadata;
MetadataClass metadataClass;
MetadataStatistics metadataStatistics;
metadataStage(metadata, metadataClass, metadataStatistics, attributes);
#ifdef HAS_SELECTED_FEATURE_ID
selectedFeatureIdStage(selectedFeature, featureIds);
#endif
#ifndef CUSTOM_SHADER_REPLACE_MATERIAL
materialStage(material, attributes, selectedFeature);
#endif
#ifdef HAS_CUSTOM_FRAGMENT_SHADER
customShaderStage(material, attributes, featureIds, metadata, metadataClass, metadataStatistics);
#endif
lightingStage(material, attributes);
#ifdef HAS_SELECTED_FEATURE_ID
cpuStylingStage(material, selectedFeature);
#endif
#ifdef HAS_MODEL_COLOR
modelColorStage(material);
#endif
#ifdef HAS_PRIMITIVE_OUTLINE
primitiveOutlineStage(material);
#endif
vec4 color = handleAlpha(material.diffuse, material.alpha);
#ifdef HAS_CLIPPING_PLANES
modelClippingPlanesStage(color);
#endif
#if defined(HAS_SILHOUETTE) && defined(HAS_NORMALS)
silhouetteStage(color);
#endif
out_FragColor = color;
}
#line 0
void main()
{
czm_log_depth_main();
czm_writeLogDepth();
}
An error occurred while rendering. Rendering has stopped.
RuntimeError: Fragment shader failed to compile. Compile log: ERROR: 0:3: 'enumProperty' : no such field in structure
ERROR: 0:3: 'constructor' : a struct cannot be used as a constructor argument for this type
Error
at new RuntimeError (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:13369:13)
at createAndLinkProgram (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:72993:11)
at reinitialize (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:73146:21)
at initialize2 (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:73141:5)
at ShaderProgram._bind (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:73200:5)
at beginDraw (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:182850:19)
at Context.draw (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:182944:5)
at DrawCommand.execute (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:69989:13)
at executeCommand (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:226429:15)
at executeCommands2 (https://sandcastle.cesium.com/CesiumUnminified/Cesium.js:226660:11)
```
Contributor guide
Research direction
Start with the attached archive's tileset.json and the included Sandcastle reproduction, first verifying that the embedded glTF property texture and ENUM definitions are valid. Then trace how the custom shader exposes property-texture metadata to fsInput.metadata. Done means enumProperty is available in the shader and the reproduction compiles and displays the expected result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100