Add existing to tracked
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
// robust iterative solution without trig functions
|
||||
// https://github.com/0xfaded/ellipse_demo/issues/1
|
||||
// https://stackoverflow.com/questions/22959698/distance-from-given-point-to-given-ellipse
|
||||
//
|
||||
// This version uses only a single iteration for best performance. For fog
|
||||
// rendering, the difference is negligible.
|
||||
vec2 nearestPointOnEllipseFast(vec2 pos, vec2 radii) {
|
||||
vec2 p = abs(pos);
|
||||
vec2 inverseRadii = 1.0 / radii;
|
||||
vec2 evoluteScale = (radii.x * radii.x - radii.y * radii.y) * vec2(1.0, -1.0) * inverseRadii;
|
||||
|
||||
// We describe the ellipse parametrically: v = radii * vec2(cos(t), sin(t))
|
||||
// but store the cos and sin of t in a vec2 for efficiency.
|
||||
// Initial guess: t = cos(pi/4)
|
||||
vec2 tTrigs = vec2(0.70710678118);
|
||||
vec2 v = radii * tTrigs;
|
||||
|
||||
// Find the evolute of the ellipse (center of curvature) at v.
|
||||
vec2 evolute = evoluteScale * tTrigs * tTrigs * tTrigs;
|
||||
// Find the (approximate) intersection of p - evolute with the ellipsoid.
|
||||
vec2 q = normalize(p - evolute) * length(v - evolute);
|
||||
// Update the estimate of t.
|
||||
tTrigs = (q + evolute) * inverseRadii;
|
||||
tTrigs = normalize(clamp(tTrigs, 0.0, 1.0));
|
||||
v = radii * tTrigs;
|
||||
|
||||
return v * sign(pos);
|
||||
}
|
||||
|
||||
vec3 computeEllipsoidPositionWC(vec3 positionMC) {
|
||||
// Get the world-space position and project onto a meridian plane of
|
||||
// the ellipsoid
|
||||
vec3 positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;
|
||||
|
||||
vec2 positionEllipse = vec2(length(positionWC.xy), positionWC.z);
|
||||
vec2 nearestPoint = nearestPointOnEllipseFast(positionEllipse, czm_ellipsoidRadii.xz);
|
||||
|
||||
// Reconstruct a 3D point in world space
|
||||
return vec3(nearestPoint.x * normalize(positionWC.xy), nearestPoint.y);
|
||||
}
|
||||
|
||||
void applyFog(inout vec4 color, vec4 groundAtmosphereColor, vec3 lightDirection, float distanceToCamera) {
|
||||
|
||||
vec3 fogColor = groundAtmosphereColor.rgb;
|
||||
|
||||
// If there is dynamic lighting, apply that to the fog.
|
||||
const float NONE = 0.0;
|
||||
if (czm_atmosphereDynamicLighting != NONE) {
|
||||
float darken = clamp(dot(normalize(czm_viewerPositionWC), lightDirection), czm_fogMinimumBrightness, 1.0);
|
||||
fogColor *= darken;
|
||||
}
|
||||
|
||||
// Tonemap if HDR rendering is disabled
|
||||
#ifndef HDR
|
||||
fogColor.rgb = czm_pbrNeutralTonemapping(fogColor.rgb);
|
||||
fogColor.rgb = czm_inverseGamma(fogColor.rgb);
|
||||
#endif
|
||||
|
||||
vec3 withFog = czm_fog(distanceToCamera, color.rgb, fogColor, czm_fogVisualDensityScalar);
|
||||
color = vec4(withFog, color.a);
|
||||
}
|
||||
|
||||
void atmosphereStage(inout vec4 color, in ProcessedAttributes attributes) {
|
||||
vec3 rayleighColor;
|
||||
vec3 mieColor;
|
||||
float opacity;
|
||||
|
||||
vec3 positionWC;
|
||||
vec3 lightDirection;
|
||||
|
||||
// When the camera is in space, compute the position per-fragment for
|
||||
// more accurate ground atmosphere. All other cases will use
|
||||
//
|
||||
// The if condition will be added in https://github.com/CesiumGS/cesium/issues/11717
|
||||
if (false) {
|
||||
positionWC = computeEllipsoidPositionWC(attributes.positionMC);
|
||||
lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC, czm_atmosphereDynamicLighting);
|
||||
|
||||
// The fog color is derived from the ground atmosphere color
|
||||
czm_computeGroundAtmosphereScattering(
|
||||
positionWC,
|
||||
lightDirection,
|
||||
rayleighColor,
|
||||
mieColor,
|
||||
opacity
|
||||
);
|
||||
} else {
|
||||
positionWC = attributes.positionWC;
|
||||
lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC, czm_atmosphereDynamicLighting);
|
||||
rayleighColor = v_atmosphereRayleighColor;
|
||||
mieColor = v_atmosphereMieColor;
|
||||
opacity = v_atmosphereOpacity;
|
||||
}
|
||||
|
||||
//color correct rayleigh and mie colors
|
||||
const bool ignoreBlackPixels = true;
|
||||
rayleighColor = czm_applyHSBShift(rayleighColor, czm_atmosphereHsbShift, ignoreBlackPixels);
|
||||
mieColor = czm_applyHSBShift(mieColor, czm_atmosphereHsbShift, ignoreBlackPixels);
|
||||
|
||||
vec4 groundAtmosphereColor = czm_computeAtmosphereColor(positionWC, lightDirection, rayleighColor, mieColor, opacity);
|
||||
|
||||
if (u_isInFog) {
|
||||
float distanceToCamera = length(attributes.positionEC);
|
||||
applyFog(color, groundAtmosphereColor, lightDirection, distanceToCamera);
|
||||
} else {
|
||||
// Ground atmosphere
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "// robust iterative solution without trig functions\n\
|
||||
// https://github.com/0xfaded/ellipse_demo/issues/1\n\
|
||||
// https://stackoverflow.com/questions/22959698/distance-from-given-point-to-given-ellipse\n\
|
||||
//\n\
|
||||
// This version uses only a single iteration for best performance. For fog\n\
|
||||
// rendering, the difference is negligible.\n\
|
||||
vec2 nearestPointOnEllipseFast(vec2 pos, vec2 radii) {\n\
|
||||
vec2 p = abs(pos);\n\
|
||||
vec2 inverseRadii = 1.0 / radii;\n\
|
||||
vec2 evoluteScale = (radii.x * radii.x - radii.y * radii.y) * vec2(1.0, -1.0) * inverseRadii;\n\
|
||||
\n\
|
||||
// We describe the ellipse parametrically: v = radii * vec2(cos(t), sin(t))\n\
|
||||
// but store the cos and sin of t in a vec2 for efficiency.\n\
|
||||
// Initial guess: t = cos(pi/4)\n\
|
||||
vec2 tTrigs = vec2(0.70710678118);\n\
|
||||
vec2 v = radii * tTrigs;\n\
|
||||
\n\
|
||||
// Find the evolute of the ellipse (center of curvature) at v.\n\
|
||||
vec2 evolute = evoluteScale * tTrigs * tTrigs * tTrigs;\n\
|
||||
// Find the (approximate) intersection of p - evolute with the ellipsoid.\n\
|
||||
vec2 q = normalize(p - evolute) * length(v - evolute);\n\
|
||||
// Update the estimate of t.\n\
|
||||
tTrigs = (q + evolute) * inverseRadii;\n\
|
||||
tTrigs = normalize(clamp(tTrigs, 0.0, 1.0));\n\
|
||||
v = radii * tTrigs;\n\
|
||||
\n\
|
||||
return v * sign(pos);\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec3 computeEllipsoidPositionWC(vec3 positionMC) {\n\
|
||||
// Get the world-space position and project onto a meridian plane of\n\
|
||||
// the ellipsoid\n\
|
||||
vec3 positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;\n\
|
||||
\n\
|
||||
vec2 positionEllipse = vec2(length(positionWC.xy), positionWC.z);\n\
|
||||
vec2 nearestPoint = nearestPointOnEllipseFast(positionEllipse, czm_ellipsoidRadii.xz);\n\
|
||||
\n\
|
||||
// Reconstruct a 3D point in world space\n\
|
||||
return vec3(nearestPoint.x * normalize(positionWC.xy), nearestPoint.y);\n\
|
||||
}\n\
|
||||
\n\
|
||||
void applyFog(inout vec4 color, vec4 groundAtmosphereColor, vec3 lightDirection, float distanceToCamera) {\n\
|
||||
\n\
|
||||
vec3 fogColor = groundAtmosphereColor.rgb;\n\
|
||||
\n\
|
||||
// If there is dynamic lighting, apply that to the fog.\n\
|
||||
const float NONE = 0.0;\n\
|
||||
if (czm_atmosphereDynamicLighting != NONE) {\n\
|
||||
float darken = clamp(dot(normalize(czm_viewerPositionWC), lightDirection), czm_fogMinimumBrightness, 1.0);\n\
|
||||
fogColor *= darken;\n\
|
||||
}\n\
|
||||
\n\
|
||||
// Tonemap if HDR rendering is disabled\n\
|
||||
#ifndef HDR\n\
|
||||
fogColor.rgb = czm_pbrNeutralTonemapping(fogColor.rgb);\n\
|
||||
fogColor.rgb = czm_inverseGamma(fogColor.rgb);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec3 withFog = czm_fog(distanceToCamera, color.rgb, fogColor, czm_fogVisualDensityScalar);\n\
|
||||
color = vec4(withFog, color.a);\n\
|
||||
}\n\
|
||||
\n\
|
||||
void atmosphereStage(inout vec4 color, in ProcessedAttributes attributes) {\n\
|
||||
vec3 rayleighColor;\n\
|
||||
vec3 mieColor;\n\
|
||||
float opacity;\n\
|
||||
\n\
|
||||
vec3 positionWC;\n\
|
||||
vec3 lightDirection;\n\
|
||||
\n\
|
||||
// When the camera is in space, compute the position per-fragment for\n\
|
||||
// more accurate ground atmosphere. All other cases will use\n\
|
||||
//\n\
|
||||
// The if condition will be added in https://github.com/CesiumGS/cesium/issues/11717\n\
|
||||
if (false) {\n\
|
||||
positionWC = computeEllipsoidPositionWC(attributes.positionMC);\n\
|
||||
lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC, czm_atmosphereDynamicLighting);\n\
|
||||
\n\
|
||||
// The fog color is derived from the ground atmosphere color\n\
|
||||
czm_computeGroundAtmosphereScattering(\n\
|
||||
positionWC,\n\
|
||||
lightDirection,\n\
|
||||
rayleighColor,\n\
|
||||
mieColor,\n\
|
||||
opacity\n\
|
||||
);\n\
|
||||
} else {\n\
|
||||
positionWC = attributes.positionWC;\n\
|
||||
lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC, czm_atmosphereDynamicLighting);\n\
|
||||
rayleighColor = v_atmosphereRayleighColor;\n\
|
||||
mieColor = v_atmosphereMieColor;\n\
|
||||
opacity = v_atmosphereOpacity;\n\
|
||||
}\n\
|
||||
\n\
|
||||
//color correct rayleigh and mie colors\n\
|
||||
const bool ignoreBlackPixels = true;\n\
|
||||
rayleighColor = czm_applyHSBShift(rayleighColor, czm_atmosphereHsbShift, ignoreBlackPixels);\n\
|
||||
mieColor = czm_applyHSBShift(mieColor, czm_atmosphereHsbShift, ignoreBlackPixels);\n\
|
||||
\n\
|
||||
vec4 groundAtmosphereColor = czm_computeAtmosphereColor(positionWC, lightDirection, rayleighColor, mieColor, opacity);\n\
|
||||
\n\
|
||||
if (u_isInFog) {\n\
|
||||
float distanceToCamera = length(attributes.positionEC);\n\
|
||||
applyFog(color, groundAtmosphereColor, lightDirection, distanceToCamera);\n\
|
||||
} else {\n\
|
||||
// Ground atmosphere\n\
|
||||
}\n\
|
||||
}\n\
|
||||
";
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
void atmosphereStage(ProcessedAttributes attributes) {
|
||||
vec3 lightDirection = czm_getDynamicAtmosphereLightDirection(v_positionWC, czm_atmosphereDynamicLighting);
|
||||
|
||||
czm_computeGroundAtmosphereScattering(
|
||||
// This assumes the geometry stage came before this.
|
||||
v_positionWC,
|
||||
lightDirection,
|
||||
v_atmosphereRayleighColor,
|
||||
v_atmosphereMieColor,
|
||||
v_atmosphereOpacity
|
||||
);
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void atmosphereStage(ProcessedAttributes attributes) {\n\
|
||||
vec3 lightDirection = czm_getDynamicAtmosphereLightDirection(v_positionWC, czm_atmosphereDynamicLighting);\n\
|
||||
\n\
|
||||
czm_computeGroundAtmosphereScattering(\n\
|
||||
// This assumes the geometry stage came before this.\n\
|
||||
v_positionWC,\n\
|
||||
lightDirection,\n\
|
||||
v_atmosphereRayleighColor,\n\
|
||||
v_atmosphereMieColor,\n\
|
||||
v_atmosphereOpacity\n\
|
||||
);\n\
|
||||
}\n\
|
||||
";
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
void filterByPassType(vec4 featureColor)
|
||||
{
|
||||
bool styleTranslucent = (featureColor.a != 1.0);
|
||||
// Only render translucent features in the translucent pass (if the style or the original command has translucency).
|
||||
if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)
|
||||
{
|
||||
// If the model has a translucent silhouette, it needs to render during the silhouette color command,
|
||||
// (i.e. the command where model_silhouettePass = true), even if the model isn't translucent.
|
||||
#ifdef HAS_SILHOUETTE
|
||||
if(!model_silhouettePass) {
|
||||
discard;
|
||||
}
|
||||
#else
|
||||
discard;
|
||||
#endif
|
||||
}
|
||||
// If the current pass is not the translucent pass and the style is not translucent, don't render the feature.
|
||||
else if (czm_pass != czm_passTranslucent && styleTranslucent)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
void cpuStylingStage(inout czm_modelMaterial material, SelectedFeature feature)
|
||||
{
|
||||
vec4 featureColor = feature.color;
|
||||
if (featureColor.a == 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
// If a feature ID vertex attribute is used, the pass type filter is applied in the vertex shader.
|
||||
// So, we only apply in in the fragment shader if the feature ID texture is used.
|
||||
#if defined(HAS_SELECTED_FEATURE_ID_TEXTURE) && !defined(HAS_CLASSIFICATION)
|
||||
filterByPassType(featureColor);
|
||||
#endif
|
||||
|
||||
featureColor = czm_gammaCorrect(featureColor);
|
||||
|
||||
// Classification models compute the diffuse differently.
|
||||
#ifdef HAS_CLASSIFICATION
|
||||
material.diffuse = featureColor.rgb * featureColor.a;
|
||||
#else
|
||||
float highlight = ceil(model_colorBlend);
|
||||
material.diffuse *= mix(featureColor.rgb, vec3(1.0), highlight);
|
||||
#endif
|
||||
|
||||
material.alpha *= featureColor.a;
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void filterByPassType(vec4 featureColor)\n\
|
||||
{\n\
|
||||
bool styleTranslucent = (featureColor.a != 1.0);\n\
|
||||
// Only render translucent features in the translucent pass (if the style or the original command has translucency).\n\
|
||||
if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)\n\
|
||||
{ \n\
|
||||
// If the model has a translucent silhouette, it needs to render during the silhouette color command,\n\
|
||||
// (i.e. the command where model_silhouettePass = true), even if the model isn't translucent.\n\
|
||||
#ifdef HAS_SILHOUETTE\n\
|
||||
if(!model_silhouettePass) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#else\n\
|
||||
discard;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
// If the current pass is not the translucent pass and the style is not translucent, don't render the feature.\n\
|
||||
else if (czm_pass != czm_passTranslucent && styleTranslucent)\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
\n\
|
||||
void cpuStylingStage(inout czm_modelMaterial material, SelectedFeature feature)\n\
|
||||
{\n\
|
||||
vec4 featureColor = feature.color;\n\
|
||||
if (featureColor.a == 0.0)\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
\n\
|
||||
// If a feature ID vertex attribute is used, the pass type filter is applied in the vertex shader.\n\
|
||||
// So, we only apply in in the fragment shader if the feature ID texture is used.\n\
|
||||
#if defined(HAS_SELECTED_FEATURE_ID_TEXTURE) && !defined(HAS_CLASSIFICATION)\n\
|
||||
filterByPassType(featureColor);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
featureColor = czm_gammaCorrect(featureColor);\n\
|
||||
\n\
|
||||
// Classification models compute the diffuse differently.\n\
|
||||
#ifdef HAS_CLASSIFICATION\n\
|
||||
material.diffuse = featureColor.rgb * featureColor.a;\n\
|
||||
#else\n\
|
||||
float highlight = ceil(model_colorBlend);\n\
|
||||
material.diffuse *= mix(featureColor.rgb, vec3(1.0), highlight);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
material.alpha *= featureColor.a;\n\
|
||||
}\n\
|
||||
";
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
void filterByPassType(inout vec3 positionMC, vec4 featureColor)
|
||||
{
|
||||
bool styleTranslucent = (featureColor.a != 1.0);
|
||||
// Only render translucent features in the translucent pass (if the style or the original command has translucency).
|
||||
if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)
|
||||
{
|
||||
// If the model has a translucent silhouette, it needs to render during the silhouette color command,
|
||||
// (i.e. the command where model_silhouettePass = true), even if the model isn't translucent.
|
||||
#ifdef HAS_SILHOUETTE
|
||||
positionMC *= float(model_silhouettePass);
|
||||
#else
|
||||
positionMC *= 0.0;
|
||||
#endif
|
||||
}
|
||||
// If the current pass is not the translucent pass and the style is not translucent, don't render the feature.
|
||||
else if (czm_pass != czm_passTranslucent && styleTranslucent)
|
||||
{
|
||||
positionMC *= 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void cpuStylingStage(inout vec3 positionMC, inout SelectedFeature feature)
|
||||
{
|
||||
float show = ceil(feature.color.a);
|
||||
positionMC *= show;
|
||||
|
||||
#if defined(HAS_SELECTED_FEATURE_ID_ATTRIBUTE) && !defined(HAS_CLASSIFICATION)
|
||||
filterByPassType(positionMC, feature.color);
|
||||
#endif
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void filterByPassType(inout vec3 positionMC, vec4 featureColor)\n\
|
||||
{\n\
|
||||
bool styleTranslucent = (featureColor.a != 1.0);\n\
|
||||
// Only render translucent features in the translucent pass (if the style or the original command has translucency).\n\
|
||||
if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)\n\
|
||||
{\n\
|
||||
// If the model has a translucent silhouette, it needs to render during the silhouette color command,\n\
|
||||
// (i.e. the command where model_silhouettePass = true), even if the model isn't translucent.\n\
|
||||
#ifdef HAS_SILHOUETTE\n\
|
||||
positionMC *= float(model_silhouettePass);\n\
|
||||
#else\n\
|
||||
positionMC *= 0.0;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
// If the current pass is not the translucent pass and the style is not translucent, don't render the feature.\n\
|
||||
else if (czm_pass != czm_passTranslucent && styleTranslucent)\n\
|
||||
{\n\
|
||||
positionMC *= 0.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
\n\
|
||||
void cpuStylingStage(inout vec3 positionMC, inout SelectedFeature feature)\n\
|
||||
{\n\
|
||||
float show = ceil(feature.color.a);\n\
|
||||
positionMC *= show;\n\
|
||||
\n\
|
||||
#if defined(HAS_SELECTED_FEATURE_ID_ATTRIBUTE) && !defined(HAS_CLASSIFICATION)\n\
|
||||
filterByPassType(positionMC, feature.color);\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
#ifdef HAS_CONSTANT_LOD
|
||||
|
||||
vec4 constantLodTextureLookup(sampler2D textureSampler, vec3 constantLodParams) {
|
||||
bool atMaxClamp = v_constantLodUvCustom.z >= constantLodParams.y;
|
||||
bool atMinClamp = v_constantLodUvCustom.z <= constantLodParams.x;
|
||||
bool atClampBoundary = atMaxClamp || atMinClamp;
|
||||
|
||||
float effectiveDistance = atMaxClamp ? constantLodParams.y :
|
||||
(atMinClamp ? constantLodParams.x : v_constantLodUvCustom.z);
|
||||
|
||||
float logDepth = log2(effectiveDistance);
|
||||
logDepth = clamp(logDepth, -10.0, 20.0);
|
||||
|
||||
float f = fract(logDepth);
|
||||
float p = floor(logDepth);
|
||||
|
||||
if (atClampBoundary) {
|
||||
float clampedP = ceil(logDepth);
|
||||
vec2 tc = v_constantLodUvCustom.xy / pow(2.0, clampedP) * constantLodParams.z;
|
||||
return texture(textureSampler, tc);
|
||||
}
|
||||
|
||||
vec2 tc1 = v_constantLodUvCustom.xy / pow(2.0, p) * constantLodParams.z;
|
||||
vec2 tc2 = v_constantLodUvCustom.xy / pow(2.0, p + 1.0) * constantLodParams.z;
|
||||
return mix(texture(textureSampler, tc1), texture(textureSampler, tc2), f);
|
||||
}
|
||||
|
||||
vec4 constantLodTextureLookup(sampler2D textureSampler, vec3 constantLodParams, mat3 textureTransform) {
|
||||
bool atMaxClamp = v_constantLodUvCustom.z >= constantLodParams.y;
|
||||
bool atMinClamp = v_constantLodUvCustom.z <= constantLodParams.x;
|
||||
bool atClampBoundary = atMaxClamp || atMinClamp;
|
||||
|
||||
float effectiveDistance = atMaxClamp ? constantLodParams.y :
|
||||
(atMinClamp ? constantLodParams.x : v_constantLodUvCustom.z);
|
||||
|
||||
float logDepth = log2(effectiveDistance);
|
||||
logDepth = clamp(logDepth, -10.0, 20.0);
|
||||
|
||||
float f = fract(logDepth);
|
||||
float p = floor(logDepth);
|
||||
|
||||
if (atClampBoundary) {
|
||||
float clampedP = ceil(logDepth);
|
||||
vec2 tc = v_constantLodUvCustom.xy / pow(2.0, clampedP) * constantLodParams.z;
|
||||
// Apply texture transform to the final texture coordinates
|
||||
tc = czm_computeTextureTransform(tc, textureTransform);
|
||||
return texture(textureSampler, tc);
|
||||
}
|
||||
|
||||
vec2 tc1 = v_constantLodUvCustom.xy / pow(2.0, p) * constantLodParams.z;
|
||||
vec2 tc2 = v_constantLodUvCustom.xy / pow(2.0, p + 1.0) * constantLodParams.z;
|
||||
|
||||
// Apply texture transform to both LOD texture coordinates before mixing
|
||||
tc1 = czm_computeTextureTransform(tc1, textureTransform);
|
||||
tc2 = czm_computeTextureTransform(tc2, textureTransform);
|
||||
|
||||
return mix(texture(textureSampler, tc1), texture(textureSampler, tc2), f);
|
||||
}
|
||||
|
||||
#endif
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "#ifdef HAS_CONSTANT_LOD\n\
|
||||
\n\
|
||||
vec4 constantLodTextureLookup(sampler2D textureSampler, vec3 constantLodParams) {\n\
|
||||
bool atMaxClamp = v_constantLodUvCustom.z >= constantLodParams.y;\n\
|
||||
bool atMinClamp = v_constantLodUvCustom.z <= constantLodParams.x;\n\
|
||||
bool atClampBoundary = atMaxClamp || atMinClamp;\n\
|
||||
\n\
|
||||
float effectiveDistance = atMaxClamp ? constantLodParams.y : \n\
|
||||
(atMinClamp ? constantLodParams.x : v_constantLodUvCustom.z);\n\
|
||||
\n\
|
||||
float logDepth = log2(effectiveDistance);\n\
|
||||
logDepth = clamp(logDepth, -10.0, 20.0);\n\
|
||||
\n\
|
||||
float f = fract(logDepth);\n\
|
||||
float p = floor(logDepth);\n\
|
||||
\n\
|
||||
if (atClampBoundary) {\n\
|
||||
float clampedP = ceil(logDepth);\n\
|
||||
vec2 tc = v_constantLodUvCustom.xy / pow(2.0, clampedP) * constantLodParams.z;\n\
|
||||
return texture(textureSampler, tc);\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec2 tc1 = v_constantLodUvCustom.xy / pow(2.0, p) * constantLodParams.z;\n\
|
||||
vec2 tc2 = v_constantLodUvCustom.xy / pow(2.0, p + 1.0) * constantLodParams.z;\n\
|
||||
return mix(texture(textureSampler, tc1), texture(textureSampler, tc2), f);\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec4 constantLodTextureLookup(sampler2D textureSampler, vec3 constantLodParams, mat3 textureTransform) {\n\
|
||||
bool atMaxClamp = v_constantLodUvCustom.z >= constantLodParams.y;\n\
|
||||
bool atMinClamp = v_constantLodUvCustom.z <= constantLodParams.x;\n\
|
||||
bool atClampBoundary = atMaxClamp || atMinClamp;\n\
|
||||
\n\
|
||||
float effectiveDistance = atMaxClamp ? constantLodParams.y : \n\
|
||||
(atMinClamp ? constantLodParams.x : v_constantLodUvCustom.z);\n\
|
||||
\n\
|
||||
float logDepth = log2(effectiveDistance);\n\
|
||||
logDepth = clamp(logDepth, -10.0, 20.0);\n\
|
||||
\n\
|
||||
float f = fract(logDepth);\n\
|
||||
float p = floor(logDepth);\n\
|
||||
\n\
|
||||
if (atClampBoundary) {\n\
|
||||
float clampedP = ceil(logDepth);\n\
|
||||
vec2 tc = v_constantLodUvCustom.xy / pow(2.0, clampedP) * constantLodParams.z;\n\
|
||||
// Apply texture transform to the final texture coordinates\n\
|
||||
tc = czm_computeTextureTransform(tc, textureTransform);\n\
|
||||
return texture(textureSampler, tc);\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec2 tc1 = v_constantLodUvCustom.xy / pow(2.0, p) * constantLodParams.z;\n\
|
||||
vec2 tc2 = v_constantLodUvCustom.xy / pow(2.0, p + 1.0) * constantLodParams.z;\n\
|
||||
\n\
|
||||
// Apply texture transform to both LOD texture coordinates before mixing\n\
|
||||
tc1 = czm_computeTextureTransform(tc1, textureTransform);\n\
|
||||
tc2 = czm_computeTextureTransform(tc2, textureTransform);\n\
|
||||
\n\
|
||||
return mix(texture(textureSampler, tc1), texture(textureSampler, tc2), f);\n\
|
||||
}\n\
|
||||
\n\
|
||||
#endif\n\
|
||||
";
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#ifdef HAS_CONSTANT_LOD
|
||||
// Extract model scale to compensate for minimumPixelSize scaling
|
||||
float modelScaleX = length(czm_model[0].xyz);
|
||||
float modelScaleY = length(czm_model[1].xyz);
|
||||
float modelScaleZ = length(czm_model[2].xyz);
|
||||
float modelScale = (modelScaleX + modelScaleY + modelScaleZ) / 3.0;
|
||||
|
||||
// Transform model position through ENU but as direction only (w=0) to avoid position-dependent rotation
|
||||
vec3 enuDir = (u_constantLodWorldToEnu * czm_model * vec4(v_positionMC, 0.0)).xyz;
|
||||
v_constantLodUvCustom.xy = (enuDir.yx + u_constantLodOffset) / modelScale;
|
||||
v_constantLodUvCustom.z = u_constantLodDistance / modelScale;
|
||||
#endif
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "#ifdef HAS_CONSTANT_LOD\n\
|
||||
// Extract model scale to compensate for minimumPixelSize scaling\n\
|
||||
float modelScaleX = length(czm_model[0].xyz);\n\
|
||||
float modelScaleY = length(czm_model[1].xyz);\n\
|
||||
float modelScaleZ = length(czm_model[2].xyz);\n\
|
||||
float modelScale = (modelScaleX + modelScaleY + modelScaleZ) / 3.0;\n\
|
||||
\n\
|
||||
// Transform model position through ENU but as direction only (w=0) to avoid position-dependent rotation\n\
|
||||
vec3 enuDir = (u_constantLodWorldToEnu * czm_model * vec4(v_positionMC, 0.0)).xyz;\n\
|
||||
v_constantLodUvCustom.xy = (enuDir.yx + u_constantLodOffset) / modelScale;\n\
|
||||
v_constantLodUvCustom.z = u_constantLodDistance / modelScale;\n\
|
||||
#endif";
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
void customShaderStage(
|
||||
inout czm_modelMaterial material,
|
||||
ProcessedAttributes attributes,
|
||||
FeatureIds featureIds,
|
||||
Metadata metadata,
|
||||
MetadataClass metadataClass,
|
||||
MetadataStatistics metadataStatistics
|
||||
) {
|
||||
// FragmentInput and initializeInputStruct() are dynamically generated in JS,
|
||||
// see CustomShaderPipelineStage.js
|
||||
FragmentInput fsInput;
|
||||
initializeInputStruct(fsInput, attributes);
|
||||
fsInput.featureIds = featureIds;
|
||||
fsInput.metadata = metadata;
|
||||
fsInput.metadataClass = metadataClass;
|
||||
fsInput.metadataStatistics = metadataStatistics;
|
||||
fragmentMain(fsInput, material);
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void customShaderStage(\n\
|
||||
inout czm_modelMaterial material,\n\
|
||||
ProcessedAttributes attributes,\n\
|
||||
FeatureIds featureIds,\n\
|
||||
Metadata metadata,\n\
|
||||
MetadataClass metadataClass,\n\
|
||||
MetadataStatistics metadataStatistics\n\
|
||||
) {\n\
|
||||
// FragmentInput and initializeInputStruct() are dynamically generated in JS, \n\
|
||||
// see CustomShaderPipelineStage.js\n\
|
||||
FragmentInput fsInput;\n\
|
||||
initializeInputStruct(fsInput, attributes);\n\
|
||||
fsInput.featureIds = featureIds;\n\
|
||||
fsInput.metadata = metadata;\n\
|
||||
fsInput.metadataClass = metadataClass;\n\
|
||||
fsInput.metadataStatistics = metadataStatistics;\n\
|
||||
fragmentMain(fsInput, material);\n\
|
||||
}\n\
|
||||
";
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
void customShaderStage(
|
||||
inout czm_modelVertexOutput vsOutput,
|
||||
inout ProcessedAttributes attributes,
|
||||
FeatureIds featureIds,
|
||||
Metadata metadata,
|
||||
MetadataClass metadataClass,
|
||||
MetadataStatistics metadataStatistics
|
||||
) {
|
||||
// VertexInput and initializeInputStruct() are dynamically generated in JS,
|
||||
// see CustomShaderPipelineStage.js
|
||||
VertexInput vsInput;
|
||||
initializeInputStruct(vsInput, attributes);
|
||||
vsInput.featureIds = featureIds;
|
||||
vsInput.metadata = metadata;
|
||||
vsInput.metadataClass = metadataClass;
|
||||
vsInput.metadataStatistics = metadataStatistics;
|
||||
vertexMain(vsInput, vsOutput);
|
||||
attributes.positionMC = vsOutput.positionMC;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void customShaderStage(\n\
|
||||
inout czm_modelVertexOutput vsOutput, \n\
|
||||
inout ProcessedAttributes attributes, \n\
|
||||
FeatureIds featureIds,\n\
|
||||
Metadata metadata,\n\
|
||||
MetadataClass metadataClass,\n\
|
||||
MetadataStatistics metadataStatistics\n\
|
||||
) {\n\
|
||||
// VertexInput and initializeInputStruct() are dynamically generated in JS, \n\
|
||||
// see CustomShaderPipelineStage.js\n\
|
||||
VertexInput vsInput;\n\
|
||||
initializeInputStruct(vsInput, attributes);\n\
|
||||
vsInput.featureIds = featureIds;\n\
|
||||
vsInput.metadata = metadata;\n\
|
||||
vsInput.metadataClass = metadataClass;\n\
|
||||
vsInput.metadataStatistics = metadataStatistics;\n\
|
||||
vertexMain(vsInput, vsOutput);\n\
|
||||
attributes.positionMC = vsOutput.positionMC;\n\
|
||||
}\n\
|
||||
";
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
void edgeDetectionStage(inout vec4 color, inout FeatureIds featureIds) {
|
||||
if (u_isEdgePass) {
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 screenCoord = gl_FragCoord.xy / czm_viewport.zw;
|
||||
|
||||
vec4 edgeColor = texture(czm_edgeColorTexture, screenCoord);
|
||||
vec4 edgeId = texture(czm_edgeIdTexture, screenCoord);
|
||||
|
||||
// Packed window-space depth from edge pass (0..1)
|
||||
float edgeDepthWin = czm_unpackDepth(texture(czm_edgeDepthTexture, screenCoord));
|
||||
|
||||
// Near / far for current frustum
|
||||
float n = czm_currentFrustum.x;
|
||||
float f = czm_currentFrustum.y;
|
||||
|
||||
// geometry depth in eye coordinate
|
||||
vec4 geomEC = czm_windowToEyeCoordinates(gl_FragCoord);
|
||||
float geomDepthLinear = -geomEC.z;
|
||||
|
||||
// Convert edge depth to linear depth
|
||||
float z_ndc_edge = edgeDepthWin * 2.0 - 1.0;
|
||||
float edgeDepthLinear = (2.0 * n * f) / (f + n - z_ndc_edge * (f - n));
|
||||
|
||||
float d = abs(edgeDepthLinear - geomDepthLinear);
|
||||
|
||||
// Adaptive epsilon using linear depth fwidth for robustness
|
||||
float pixelStepLinear = fwidth(geomDepthLinear);
|
||||
float rel = geomDepthLinear * 0.0005;
|
||||
float eps = max(n * 1e-4, max(pixelStepLinear * 1.5, rel));
|
||||
|
||||
// If Edge isn't behind any geometry and the pixel has edge data
|
||||
if (d < eps && edgeId.r > 0.0) {
|
||||
#ifdef HAS_EDGE_FEATURE_ID
|
||||
float edgeFeatureId = edgeId.g;
|
||||
float currentFeatureId = float(featureIds.featureId_0);
|
||||
#endif
|
||||
float globeDepth = czm_unpackDepth(texture(czm_globeDepthTexture, screenCoord));
|
||||
// Background / sky / globe: always show edge
|
||||
bool isBackground = geomDepthLinear > globeDepth;
|
||||
bool drawEdge = isBackground;
|
||||
|
||||
#ifdef HAS_EDGE_FEATURE_ID
|
||||
bool hasEdgeFeature = edgeFeatureId > 0.0;
|
||||
bool hasCurrentFeature = currentFeatureId > 0.0;
|
||||
bool featuresMatch = edgeFeatureId == currentFeatureId;
|
||||
|
||||
drawEdge = drawEdge || !hasEdgeFeature || !hasCurrentFeature || featuresMatch;
|
||||
#else
|
||||
drawEdge = true;
|
||||
#endif
|
||||
|
||||
if (drawEdge) {
|
||||
color = edgeColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void edgeDetectionStage(inout vec4 color, inout FeatureIds featureIds) {\n\
|
||||
if (u_isEdgePass) {\n\
|
||||
return;\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec2 screenCoord = gl_FragCoord.xy / czm_viewport.zw;\n\
|
||||
\n\
|
||||
vec4 edgeColor = texture(czm_edgeColorTexture, screenCoord);\n\
|
||||
vec4 edgeId = texture(czm_edgeIdTexture, screenCoord);\n\
|
||||
\n\
|
||||
// Packed window-space depth from edge pass (0..1)\n\
|
||||
float edgeDepthWin = czm_unpackDepth(texture(czm_edgeDepthTexture, screenCoord));\n\
|
||||
\n\
|
||||
// Near / far for current frustum\n\
|
||||
float n = czm_currentFrustum.x;\n\
|
||||
float f = czm_currentFrustum.y;\n\
|
||||
\n\
|
||||
// geometry depth in eye coordinate\n\
|
||||
vec4 geomEC = czm_windowToEyeCoordinates(gl_FragCoord);\n\
|
||||
float geomDepthLinear = -geomEC.z;\n\
|
||||
\n\
|
||||
// Convert edge depth to linear depth\n\
|
||||
float z_ndc_edge = edgeDepthWin * 2.0 - 1.0;\n\
|
||||
float edgeDepthLinear = (2.0 * n * f) / (f + n - z_ndc_edge * (f - n));\n\
|
||||
\n\
|
||||
float d = abs(edgeDepthLinear - geomDepthLinear);\n\
|
||||
\n\
|
||||
// Adaptive epsilon using linear depth fwidth for robustness\n\
|
||||
float pixelStepLinear = fwidth(geomDepthLinear);\n\
|
||||
float rel = geomDepthLinear * 0.0005;\n\
|
||||
float eps = max(n * 1e-4, max(pixelStepLinear * 1.5, rel));\n\
|
||||
\n\
|
||||
// If Edge isn't behind any geometry and the pixel has edge data\n\
|
||||
if (d < eps && edgeId.r > 0.0) {\n\
|
||||
#ifdef HAS_EDGE_FEATURE_ID\n\
|
||||
float edgeFeatureId = edgeId.g;\n\
|
||||
float currentFeatureId = float(featureIds.featureId_0);\n\
|
||||
#endif\n\
|
||||
float globeDepth = czm_unpackDepth(texture(czm_globeDepthTexture, screenCoord));\n\
|
||||
// Background / sky / globe: always show edge\n\
|
||||
bool isBackground = geomDepthLinear > globeDepth;\n\
|
||||
bool drawEdge = isBackground;\n\
|
||||
\n\
|
||||
#ifdef HAS_EDGE_FEATURE_ID\n\
|
||||
bool hasEdgeFeature = edgeFeatureId > 0.0;\n\
|
||||
bool hasCurrentFeature = currentFeatureId > 0.0;\n\
|
||||
bool featuresMatch = edgeFeatureId == currentFeatureId;\n\
|
||||
\n\
|
||||
drawEdge = drawEdge || !hasEdgeFeature || !hasCurrentFeature || featuresMatch;\n\
|
||||
#else\n\
|
||||
drawEdge = true;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
if (drawEdge) {\n\
|
||||
color = edgeColor;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
}\n\
|
||||
";
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// CESIUM_REDIRECTED_COLOR_OUTPUT flag is used to avoid color attachment conflicts
|
||||
// when shaders are processed by different rendering pipelines (e.g., OIT).
|
||||
// Only declare MRT outputs when not in a derived shader context.
|
||||
#if defined(HAS_EDGE_VISIBILITY_MRT) && !defined(CESIUM_REDIRECTED_COLOR_OUTPUT)
|
||||
layout(location = 1) out vec4 out_id; // edge id / metadata
|
||||
layout(location = 2) out vec4 out_edgeDepth; // packed depth
|
||||
#endif
|
||||
|
||||
void edgeVisibilityStage(inout vec4 color, inout FeatureIds featureIds)
|
||||
{
|
||||
#ifdef HAS_EDGE_VISIBILITY
|
||||
|
||||
if (!u_isEdgePass) {
|
||||
return;
|
||||
}
|
||||
|
||||
float edgeTypeInt = v_edgeType * 255.0;
|
||||
|
||||
if (edgeTypeInt < 0.5) {
|
||||
discard;
|
||||
}
|
||||
|
||||
if (edgeTypeInt > 0.5 && edgeTypeInt < 1.5) { // silhouette candidate
|
||||
// Silhouette check done in vertex shader
|
||||
// v_shouldDiscard will be > 0.5 if this edge should be discarded
|
||||
if (v_shouldDiscard > 0.5) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 finalColor = color;
|
||||
#ifdef HAS_EDGE_COLOR_ATTRIBUTE
|
||||
if (v_edgeColor.a >= 0.0) {
|
||||
finalColor = v_edgeColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_LINE_PATTERN
|
||||
// Pattern is 16-bit, each bit represents visibility at that position
|
||||
const float maskLength = 16.0;
|
||||
|
||||
// Get the relative position within the dash from 0 to 1
|
||||
float dashPosition = fract(v_lineCoord / maskLength);
|
||||
// Figure out the mask index
|
||||
float maskIndex = floor(dashPosition * maskLength);
|
||||
// Test the bit mask
|
||||
float maskTest = floor(u_linePattern / pow(2.0, maskIndex));
|
||||
|
||||
// If bit is 0 (gap), discard the fragment (use < 1.0 for better numerical stability)
|
||||
if (mod(maskTest, 2.0) < 1.0) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
color = finalColor;
|
||||
|
||||
#if defined(HAS_EDGE_VISIBILITY_MRT) && !defined(CESIUM_REDIRECTED_COLOR_OUTPUT)
|
||||
// Write edge metadata
|
||||
out_id = vec4(0.0);
|
||||
out_id.r = edgeTypeInt; // Edge type (0-3)
|
||||
#ifdef HAS_EDGE_FEATURE_ID
|
||||
out_id.g = float(featureIds.featureId_0); // Feature ID if available
|
||||
#else
|
||||
out_id.g = 0.0;
|
||||
#endif
|
||||
// Pack depth into separate MRT attachment
|
||||
out_edgeDepth = czm_packDepth(gl_FragCoord.z);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "// CESIUM_REDIRECTED_COLOR_OUTPUT flag is used to avoid color attachment conflicts\n\
|
||||
// when shaders are processed by different rendering pipelines (e.g., OIT).\n\
|
||||
// Only declare MRT outputs when not in a derived shader context.\n\
|
||||
#if defined(HAS_EDGE_VISIBILITY_MRT) && !defined(CESIUM_REDIRECTED_COLOR_OUTPUT)\n\
|
||||
layout(location = 1) out vec4 out_id; // edge id / metadata\n\
|
||||
layout(location = 2) out vec4 out_edgeDepth; // packed depth\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
void edgeVisibilityStage(inout vec4 color, inout FeatureIds featureIds)\n\
|
||||
{\n\
|
||||
#ifdef HAS_EDGE_VISIBILITY\n\
|
||||
\n\
|
||||
if (!u_isEdgePass) {\n\
|
||||
return;\n\
|
||||
}\n\
|
||||
\n\
|
||||
float edgeTypeInt = v_edgeType * 255.0;\n\
|
||||
\n\
|
||||
if (edgeTypeInt < 0.5) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
\n\
|
||||
if (edgeTypeInt > 0.5 && edgeTypeInt < 1.5) { // silhouette candidate\n\
|
||||
// Silhouette check done in vertex shader\n\
|
||||
// v_shouldDiscard will be > 0.5 if this edge should be discarded\n\
|
||||
if (v_shouldDiscard > 0.5) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec4 finalColor = color;\n\
|
||||
#ifdef HAS_EDGE_COLOR_ATTRIBUTE\n\
|
||||
if (v_edgeColor.a >= 0.0) {\n\
|
||||
finalColor = v_edgeColor;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_LINE_PATTERN\n\
|
||||
// Pattern is 16-bit, each bit represents visibility at that position\n\
|
||||
const float maskLength = 16.0;\n\
|
||||
\n\
|
||||
// Get the relative position within the dash from 0 to 1\n\
|
||||
float dashPosition = fract(v_lineCoord / maskLength);\n\
|
||||
// Figure out the mask index\n\
|
||||
float maskIndex = floor(dashPosition * maskLength);\n\
|
||||
// Test the bit mask\n\
|
||||
float maskTest = floor(u_linePattern / pow(2.0, maskIndex));\n\
|
||||
\n\
|
||||
// If bit is 0 (gap), discard the fragment (use < 1.0 for better numerical stability)\n\
|
||||
if (mod(maskTest, 2.0) < 1.0) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
color = finalColor;\n\
|
||||
\n\
|
||||
#if defined(HAS_EDGE_VISIBILITY_MRT) && !defined(CESIUM_REDIRECTED_COLOR_OUTPUT)\n\
|
||||
// Write edge metadata\n\
|
||||
out_id = vec4(0.0);\n\
|
||||
out_id.r = edgeTypeInt; // Edge type (0-3)\n\
|
||||
#ifdef HAS_EDGE_FEATURE_ID\n\
|
||||
out_id.g = float(featureIds.featureId_0); // Feature ID if available\n\
|
||||
#else\n\
|
||||
out_id.g = 0.0;\n\
|
||||
#endif\n\
|
||||
// Pack depth into separate MRT attachment\n\
|
||||
out_edgeDepth = czm_packDepth(gl_FragCoord.z);\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
}";
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
#ifdef HAS_EDGE_VISIBILITY
|
||||
void edgeVisibilityStageVS() {
|
||||
if (!u_isEdgePass) {
|
||||
return;
|
||||
}
|
||||
|
||||
v_edgeType = a_edgeType;
|
||||
v_faceNormalAView = czm_normal * a_faceNormalA;
|
||||
v_faceNormalBView = czm_normal * a_faceNormalB;
|
||||
v_edgeOffset = a_edgeOffset;
|
||||
|
||||
// Silhouette detection: check both endpoints of the edge
|
||||
v_shouldDiscard = 0.0;
|
||||
float edgeTypeInt = a_edgeType * 255.0;
|
||||
if (edgeTypeInt > 0.5 && edgeTypeInt < 1.5) {
|
||||
vec3 normalA = normalize(v_faceNormalAView);
|
||||
vec3 normalB = normalize(v_faceNormalBView);
|
||||
const float perpTol = 2.5e-4;
|
||||
|
||||
// Check at current vertex (first endpoint)
|
||||
vec4 currentPosEC = czm_modelView * vec4(v_positionMC, 1.0);
|
||||
vec3 toEye1 = normalize(-currentPosEC.xyz);
|
||||
float dotA1 = dot(normalA, toEye1);
|
||||
float dotB1 = dot(normalB, toEye1);
|
||||
|
||||
// Check at other vertex (second endpoint)
|
||||
vec4 otherPosEC = czm_modelView * vec4(a_edgeOtherPos, 1.0);
|
||||
vec3 toEye2 = normalize(-otherPosEC.xyz);
|
||||
float dotA2 = dot(normalA, toEye2);
|
||||
float dotB2 = dot(normalB, toEye2);
|
||||
|
||||
// Discard if EITHER endpoint is non-silhouette
|
||||
if (dotA1 * dotB1 > perpTol || dotA2 * dotB2 > perpTol) {
|
||||
v_shouldDiscard = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_EDGE_FEATURE_ID
|
||||
v_featureId_0 = a_edgeFeatureId;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EDGE_COLOR_ATTRIBUTE
|
||||
v_edgeColor = a_edgeColor;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_LINE_PATTERN
|
||||
#ifdef HAS_EDGE_CUMULATIVE_DISTANCE
|
||||
v_lineCoord = a_edgeCumulativeDistance * u_pixelsPerWorld;
|
||||
#else
|
||||
vec4 currentClip = czm_modelViewProjection * vec4(v_positionMC, 1.0);
|
||||
vec2 currentScreen = ((currentClip.xy / currentClip.w) * 0.5 + 0.5) * czm_viewport.zw;
|
||||
|
||||
vec4 otherClip = czm_modelViewProjection * vec4(a_edgeOtherPos, 1.0);
|
||||
vec2 otherScreen = ((otherClip.xy / otherClip.w) * 0.5 + 0.5) * czm_viewport.zw;
|
||||
vec2 windowDir = otherScreen - currentScreen;
|
||||
|
||||
const float textureCoordinateBase = 8192.0;
|
||||
if (abs(windowDir.x) > abs(windowDir.y)) {
|
||||
v_lineCoord = textureCoordinateBase + currentScreen.x;
|
||||
} else {
|
||||
v_lineCoord = textureCoordinateBase + currentScreen.y;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Expand vertex to form quad
|
||||
vec4 posClip = gl_Position;
|
||||
|
||||
if (length(a_edgeOtherPos) > 0.0 && abs(a_edgeOffset) > 0.0) {
|
||||
vec4 currentClip = posClip;
|
||||
vec4 otherClip = czm_modelViewProjection * vec4(a_edgeOtherPos, 1.0);
|
||||
|
||||
vec2 currentNDC = currentClip.xy / currentClip.w;
|
||||
vec2 otherNDC = otherClip.xy / otherClip.w;
|
||||
|
||||
vec2 edgeDirNDC = otherNDC - currentNDC;
|
||||
|
||||
// Ensure consistent edge direction
|
||||
if (edgeDirNDC.x < 0.0 || (abs(edgeDirNDC.x) < 0.001 && edgeDirNDC.y < 0.0)) {
|
||||
edgeDirNDC = -edgeDirNDC;
|
||||
}
|
||||
|
||||
edgeDirNDC = normalize(edgeDirNDC);
|
||||
vec2 perpNDC = vec2(-edgeDirNDC.y, edgeDirNDC.x);
|
||||
|
||||
// Convert line width from pixels to clip space
|
||||
float lineWidthPixels = u_lineWidth;
|
||||
vec2 viewportSize = czm_viewport.zw;
|
||||
vec2 clipPerPixel = (2.0 / viewportSize) * currentClip.w;
|
||||
vec2 offsetClip = perpNDC * lineWidthPixels * clipPerPixel * 0.5 * a_edgeOffset;
|
||||
|
||||
posClip.xy += offsetClip;
|
||||
}
|
||||
|
||||
gl_Position = posClip;
|
||||
}
|
||||
#endif
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "#ifdef HAS_EDGE_VISIBILITY\n\
|
||||
void edgeVisibilityStageVS() {\n\
|
||||
if (!u_isEdgePass) {\n\
|
||||
return;\n\
|
||||
}\n\
|
||||
\n\
|
||||
v_edgeType = a_edgeType;\n\
|
||||
v_faceNormalAView = czm_normal * a_faceNormalA;\n\
|
||||
v_faceNormalBView = czm_normal * a_faceNormalB;\n\
|
||||
v_edgeOffset = a_edgeOffset;\n\
|
||||
\n\
|
||||
// Silhouette detection: check both endpoints of the edge\n\
|
||||
v_shouldDiscard = 0.0;\n\
|
||||
float edgeTypeInt = a_edgeType * 255.0;\n\
|
||||
if (edgeTypeInt > 0.5 && edgeTypeInt < 1.5) {\n\
|
||||
vec3 normalA = normalize(v_faceNormalAView);\n\
|
||||
vec3 normalB = normalize(v_faceNormalBView);\n\
|
||||
const float perpTol = 2.5e-4;\n\
|
||||
\n\
|
||||
// Check at current vertex (first endpoint)\n\
|
||||
vec4 currentPosEC = czm_modelView * vec4(v_positionMC, 1.0);\n\
|
||||
vec3 toEye1 = normalize(-currentPosEC.xyz);\n\
|
||||
float dotA1 = dot(normalA, toEye1);\n\
|
||||
float dotB1 = dot(normalB, toEye1);\n\
|
||||
\n\
|
||||
// Check at other vertex (second endpoint)\n\
|
||||
vec4 otherPosEC = czm_modelView * vec4(a_edgeOtherPos, 1.0);\n\
|
||||
vec3 toEye2 = normalize(-otherPosEC.xyz);\n\
|
||||
float dotA2 = dot(normalA, toEye2);\n\
|
||||
float dotB2 = dot(normalB, toEye2);\n\
|
||||
\n\
|
||||
// Discard if EITHER endpoint is non-silhouette\n\
|
||||
if (dotA1 * dotB1 > perpTol || dotA2 * dotB2 > perpTol) {\n\
|
||||
v_shouldDiscard = 1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
\n\
|
||||
#ifdef HAS_EDGE_FEATURE_ID\n\
|
||||
v_featureId_0 = a_edgeFeatureId;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_EDGE_COLOR_ATTRIBUTE\n\
|
||||
v_edgeColor = a_edgeColor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_LINE_PATTERN\n\
|
||||
#ifdef HAS_EDGE_CUMULATIVE_DISTANCE\n\
|
||||
v_lineCoord = a_edgeCumulativeDistance * u_pixelsPerWorld;\n\
|
||||
#else\n\
|
||||
vec4 currentClip = czm_modelViewProjection * vec4(v_positionMC, 1.0);\n\
|
||||
vec2 currentScreen = ((currentClip.xy / currentClip.w) * 0.5 + 0.5) * czm_viewport.zw;\n\
|
||||
\n\
|
||||
vec4 otherClip = czm_modelViewProjection * vec4(a_edgeOtherPos, 1.0);\n\
|
||||
vec2 otherScreen = ((otherClip.xy / otherClip.w) * 0.5 + 0.5) * czm_viewport.zw;\n\
|
||||
vec2 windowDir = otherScreen - currentScreen;\n\
|
||||
\n\
|
||||
const float textureCoordinateBase = 8192.0;\n\
|
||||
if (abs(windowDir.x) > abs(windowDir.y)) {\n\
|
||||
v_lineCoord = textureCoordinateBase + currentScreen.x;\n\
|
||||
} else {\n\
|
||||
v_lineCoord = textureCoordinateBase + currentScreen.y;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Expand vertex to form quad\n\
|
||||
vec4 posClip = gl_Position;\n\
|
||||
\n\
|
||||
if (length(a_edgeOtherPos) > 0.0 && abs(a_edgeOffset) > 0.0) {\n\
|
||||
vec4 currentClip = posClip;\n\
|
||||
vec4 otherClip = czm_modelViewProjection * vec4(a_edgeOtherPos, 1.0);\n\
|
||||
\n\
|
||||
vec2 currentNDC = currentClip.xy / currentClip.w;\n\
|
||||
vec2 otherNDC = otherClip.xy / otherClip.w;\n\
|
||||
\n\
|
||||
vec2 edgeDirNDC = otherNDC - currentNDC;\n\
|
||||
\n\
|
||||
// Ensure consistent edge direction\n\
|
||||
if (edgeDirNDC.x < 0.0 || (abs(edgeDirNDC.x) < 0.001 && edgeDirNDC.y < 0.0)) {\n\
|
||||
edgeDirNDC = -edgeDirNDC;\n\
|
||||
}\n\
|
||||
\n\
|
||||
edgeDirNDC = normalize(edgeDirNDC);\n\
|
||||
vec2 perpNDC = vec2(-edgeDirNDC.y, edgeDirNDC.x);\n\
|
||||
\n\
|
||||
// Convert line width from pixels to clip space\n\
|
||||
float lineWidthPixels = u_lineWidth;\n\
|
||||
vec2 viewportSize = czm_viewport.zw;\n\
|
||||
vec2 clipPerPixel = (2.0 / viewportSize) * currentClip.w;\n\
|
||||
vec2 offsetClip = perpNDC * lineWidthPixels * clipPerPixel * 0.5 * a_edgeOffset;\n\
|
||||
\n\
|
||||
posClip.xy += offsetClip;\n\
|
||||
}\n\
|
||||
\n\
|
||||
gl_Position = posClip;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
";
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) {
|
||||
initializeFeatureIds(featureIds, attributes);
|
||||
initializeFeatureIdAliases(featureIds);
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) {\n\
|
||||
initializeFeatureIds(featureIds, attributes);\n\
|
||||
initializeFeatureIdAliases(featureIds);\n\
|
||||
}\n\
|
||||
";
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes)
|
||||
{
|
||||
initializeFeatureIds(featureIds, attributes);
|
||||
initializeFeatureIdAliases(featureIds);
|
||||
setFeatureIdVaryings();
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) \n\
|
||||
{\n\
|
||||
initializeFeatureIds(featureIds, attributes);\n\
|
||||
initializeFeatureIdAliases(featureIds);\n\
|
||||
setFeatureIdVaryings();\n\
|
||||
}\n\
|
||||
";
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
void geometryStage(out ProcessedAttributes attributes)
|
||||
{
|
||||
attributes.positionMC = v_positionMC;
|
||||
attributes.positionEC = v_positionEC;
|
||||
|
||||
#if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE)
|
||||
attributes.positionWC = v_positionWC;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_NORMALS
|
||||
// renormalize after interpolation
|
||||
attributes.normalEC = normalize(v_normalEC);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TANGENTS
|
||||
attributes.tangentEC = normalize(v_tangentEC);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BITANGENTS
|
||||
attributes.bitangentEC = normalize(v_bitangentEC);
|
||||
#endif
|
||||
|
||||
// Everything else is dynamically generated in GeometryPipelineStage
|
||||
setDynamicVaryings(attributes);
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void geometryStage(out ProcessedAttributes attributes)\n\
|
||||
{\n\
|
||||
attributes.positionMC = v_positionMC;\n\
|
||||
attributes.positionEC = v_positionEC;\n\
|
||||
\n\
|
||||
#if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE)\n\
|
||||
attributes.positionWC = v_positionWC;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
// renormalize after interpolation\n\
|
||||
attributes.normalEC = normalize(v_normalEC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_TANGENTS\n\
|
||||
attributes.tangentEC = normalize(v_tangentEC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_BITANGENTS\n\
|
||||
attributes.bitangentEC = normalize(v_bitangentEC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Everything else is dynamically generated in GeometryPipelineStage\n\
|
||||
setDynamicVaryings(attributes);\n\
|
||||
}\n\
|
||||
";
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
vec4 geometryStage(inout ProcessedAttributes attributes, mat4 modelView, mat3 normal)
|
||||
{
|
||||
vec4 computedPosition;
|
||||
|
||||
// Compute positions in different coordinate systems
|
||||
vec3 positionMC = attributes.positionMC;
|
||||
v_positionMC = positionMC;
|
||||
v_positionEC = (modelView * vec4(positionMC, 1.0)).xyz;
|
||||
|
||||
#if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)
|
||||
vec3 position2D = attributes.position2D;
|
||||
vec3 positionEC = (u_modelView2D * vec4(position2D, 1.0)).xyz;
|
||||
computedPosition = czm_projection * vec4(positionEC, 1.0);
|
||||
#else
|
||||
computedPosition = czm_projection * vec4(v_positionEC, 1.0);
|
||||
#endif
|
||||
|
||||
// Sometimes the custom shader and/or style needs this
|
||||
#if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE) || defined(ENABLE_CLIPPING_POLYGONS)
|
||||
// Note that this is a 32-bit position which may result in jitter on small
|
||||
// scales.
|
||||
v_positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_NORMALS
|
||||
v_normalEC = normalize(normal * attributes.normalMC);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TANGENTS
|
||||
v_tangentEC = normalize(normal * attributes.tangentMC);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BITANGENTS
|
||||
v_bitangentEC = normalize(normal * attributes.bitangentMC);
|
||||
#endif
|
||||
|
||||
// All other varyings need to be dynamically generated in
|
||||
// GeometryPipelineStage
|
||||
setDynamicVaryings(attributes);
|
||||
|
||||
return computedPosition;
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "vec4 geometryStage(inout ProcessedAttributes attributes, mat4 modelView, mat3 normal)\n\
|
||||
{\n\
|
||||
vec4 computedPosition;\n\
|
||||
\n\
|
||||
// Compute positions in different coordinate systems\n\
|
||||
vec3 positionMC = attributes.positionMC;\n\
|
||||
v_positionMC = positionMC;\n\
|
||||
v_positionEC = (modelView * vec4(positionMC, 1.0)).xyz;\n\
|
||||
\n\
|
||||
#if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)\n\
|
||||
vec3 position2D = attributes.position2D;\n\
|
||||
vec3 positionEC = (u_modelView2D * vec4(position2D, 1.0)).xyz;\n\
|
||||
computedPosition = czm_projection * vec4(positionEC, 1.0);\n\
|
||||
#else\n\
|
||||
computedPosition = czm_projection * vec4(v_positionEC, 1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Sometimes the custom shader and/or style needs this\n\
|
||||
#if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE) || defined(ENABLE_CLIPPING_POLYGONS)\n\
|
||||
// Note that this is a 32-bit position which may result in jitter on small\n\
|
||||
// scales.\n\
|
||||
v_positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
v_normalEC = normalize(normal * attributes.normalMC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_TANGENTS\n\
|
||||
v_tangentEC = normalize(normal * attributes.tangentMC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_BITANGENTS\n\
|
||||
v_bitangentEC = normalize(normal * attributes.bitangentMC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// All other varyings need to be dynamically generated in\n\
|
||||
// GeometryPipelineStage\n\
|
||||
setDynamicVaryings(attributes);\n\
|
||||
\n\
|
||||
return computedPosition;\n\
|
||||
}\n\
|
||||
";
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
#ifdef DIFFUSE_IBL
|
||||
vec3 sampleDiffuseEnvironment(vec3 cubeDir)
|
||||
{
|
||||
#ifdef CUSTOM_SPHERICAL_HARMONICS
|
||||
return czm_sphericalHarmonics(cubeDir, model_sphericalHarmonicCoefficients);
|
||||
#else
|
||||
return czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPECULAR_IBL
|
||||
vec3 sampleSpecularEnvironment(vec3 cubeDir, float roughness)
|
||||
{
|
||||
#ifdef CUSTOM_SPECULAR_IBL
|
||||
float lod = roughness * model_specularEnvironmentMapsMaximumLOD;
|
||||
return czm_textureCube(model_specularEnvironmentMaps, cubeDir, lod).rgb;
|
||||
#else
|
||||
float lod = roughness * czm_specularEnvironmentMapsMaximumLOD;
|
||||
return czm_textureCube(czm_specularEnvironmentMaps, cubeDir, lod).rgb;
|
||||
#endif
|
||||
}
|
||||
vec3 computeSpecularIBL(vec3 cubeDir, float NdotV, vec3 f0, float roughness)
|
||||
{
|
||||
// see https://bruop.github.io/ibl/ at Single Scattering Results
|
||||
// Roughness dependent fresnel, from Fdez-Aguera
|
||||
vec3 f90 = max(vec3(1.0 - roughness), f0);
|
||||
vec3 F = fresnelSchlick2(f0, f90, NdotV);
|
||||
|
||||
vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;
|
||||
vec3 specularSample = sampleSpecularEnvironment(cubeDir, roughness);
|
||||
|
||||
return specularSample * (F * brdfLut.x + brdfLut.y);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)
|
||||
/**
|
||||
* Compute the light contributions from environment maps and spherical harmonic coefficients.
|
||||
* See Fdez-Aguera, https://www.jcgt.org/published/0008/01/03/paper.pdf, for explanation
|
||||
* of the single- and multi-scattering terms.
|
||||
*
|
||||
* @param {vec3} viewDirectionEC Unit vector pointing from the fragment to the eye position.
|
||||
* @param {vec3} normalEC The surface normal in eye coordinates.
|
||||
* @param {czm_modelMaterial} The material properties.
|
||||
* @return {vec3} The computed HDR color.
|
||||
*/
|
||||
vec3 textureIBL(vec3 viewDirectionEC, vec3 normalEC, czm_modelMaterial material) {
|
||||
vec3 f0 = material.specular;
|
||||
float roughness = material.roughness;
|
||||
float specularWeight = 1.0;
|
||||
#ifdef USE_SPECULAR
|
||||
specularWeight = material.specularWeight;
|
||||
#endif
|
||||
float NdotV = clamp(dot(normalEC, viewDirectionEC), 0.0, 1.0);
|
||||
|
||||
// see https://bruop.github.io/ibl/ at Single Scattering Results
|
||||
// Roughness dependent fresnel, from Fdez-Aguera
|
||||
vec3 f90 = max(vec3(1.0 - roughness), f0);
|
||||
vec3 singleScatterFresnel = fresnelSchlick2(f0, f90, NdotV);
|
||||
|
||||
vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;
|
||||
vec3 FssEss = specularWeight * (singleScatterFresnel * brdfLut.x + brdfLut.y);
|
||||
|
||||
#ifdef DIFFUSE_IBL
|
||||
vec3 normalMC = normalize(model_iblReferenceFrameMatrix * normalEC);
|
||||
vec3 irradiance = sampleDiffuseEnvironment(normalMC);
|
||||
|
||||
vec3 averageFresnel = f0 + (1.0 - f0) / 21.0;
|
||||
float Ems = specularWeight * (1.0 - brdfLut.x - brdfLut.y);
|
||||
vec3 FmsEms = FssEss * averageFresnel * Ems / (1.0 - averageFresnel * Ems);
|
||||
vec3 dielectricScattering = (1.0 - FssEss - FmsEms) * material.diffuse;
|
||||
vec3 diffuseContribution = irradiance * (FmsEms + dielectricScattering) * model_iblFactor.x;
|
||||
#else
|
||||
vec3 diffuseContribution = vec3(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ANISOTROPY
|
||||
// Bend normal to account for anisotropic distortion of specular reflection
|
||||
vec3 anisotropyDirection = material.anisotropicB;
|
||||
vec3 anisotropicTangent = cross(anisotropyDirection, viewDirectionEC);
|
||||
vec3 anisotropicNormal = cross(anisotropicTangent, anisotropyDirection);
|
||||
float bendFactor = 1.0 - material.anisotropyStrength * (1.0 - roughness);
|
||||
float bendFactorPow4 = bendFactor * bendFactor * bendFactor * bendFactor;
|
||||
vec3 bentNormal = normalize(mix(anisotropicNormal, normalEC, bendFactorPow4));
|
||||
vec3 reflectEC = reflect(-viewDirectionEC, bentNormal);
|
||||
#else
|
||||
vec3 reflectEC = reflect(-viewDirectionEC, normalEC);
|
||||
#endif
|
||||
|
||||
#ifdef SPECULAR_IBL
|
||||
vec3 reflectMC = normalize(model_iblReferenceFrameMatrix * reflectEC);
|
||||
vec3 radiance = sampleSpecularEnvironment(reflectMC, roughness);
|
||||
vec3 specularContribution = radiance * FssEss * model_iblFactor.y;
|
||||
#else
|
||||
vec3 specularContribution = vec3(0.0);
|
||||
#endif
|
||||
|
||||
return diffuseContribution + specularContribution;
|
||||
}
|
||||
#endif
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "#ifdef DIFFUSE_IBL\n\
|
||||
vec3 sampleDiffuseEnvironment(vec3 cubeDir)\n\
|
||||
{\n\
|
||||
#ifdef CUSTOM_SPHERICAL_HARMONICS\n\
|
||||
return czm_sphericalHarmonics(cubeDir, model_sphericalHarmonicCoefficients); \n\
|
||||
#else\n\
|
||||
return czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients); \n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef SPECULAR_IBL\n\
|
||||
vec3 sampleSpecularEnvironment(vec3 cubeDir, float roughness)\n\
|
||||
{\n\
|
||||
#ifdef CUSTOM_SPECULAR_IBL\n\
|
||||
float lod = roughness * model_specularEnvironmentMapsMaximumLOD;\n\
|
||||
return czm_textureCube(model_specularEnvironmentMaps, cubeDir, lod).rgb;\n\
|
||||
#else\n\
|
||||
float lod = roughness * czm_specularEnvironmentMapsMaximumLOD;\n\
|
||||
return czm_textureCube(czm_specularEnvironmentMaps, cubeDir, lod).rgb;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
vec3 computeSpecularIBL(vec3 cubeDir, float NdotV, vec3 f0, float roughness)\n\
|
||||
{\n\
|
||||
// see https://bruop.github.io/ibl/ at Single Scattering Results\n\
|
||||
// Roughness dependent fresnel, from Fdez-Aguera\n\
|
||||
vec3 f90 = max(vec3(1.0 - roughness), f0);\n\
|
||||
vec3 F = fresnelSchlick2(f0, f90, NdotV);\n\
|
||||
\n\
|
||||
vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;\n\
|
||||
vec3 specularSample = sampleSpecularEnvironment(cubeDir, roughness);\n\
|
||||
\n\
|
||||
return specularSample * (F * brdfLut.x + brdfLut.y);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)\n\
|
||||
/**\n\
|
||||
* Compute the light contributions from environment maps and spherical harmonic coefficients.\n\
|
||||
* See Fdez-Aguera, https://www.jcgt.org/published/0008/01/03/paper.pdf, for explanation\n\
|
||||
* of the single- and multi-scattering terms.\n\
|
||||
*\n\
|
||||
* @param {vec3} viewDirectionEC Unit vector pointing from the fragment to the eye position.\n\
|
||||
* @param {vec3} normalEC The surface normal in eye coordinates.\n\
|
||||
* @param {czm_modelMaterial} The material properties.\n\
|
||||
* @return {vec3} The computed HDR color.\n\
|
||||
*/\n\
|
||||
vec3 textureIBL(vec3 viewDirectionEC, vec3 normalEC, czm_modelMaterial material) {\n\
|
||||
vec3 f0 = material.specular;\n\
|
||||
float roughness = material.roughness;\n\
|
||||
float specularWeight = 1.0;\n\
|
||||
#ifdef USE_SPECULAR\n\
|
||||
specularWeight = material.specularWeight;\n\
|
||||
#endif\n\
|
||||
float NdotV = clamp(dot(normalEC, viewDirectionEC), 0.0, 1.0);\n\
|
||||
\n\
|
||||
// see https://bruop.github.io/ibl/ at Single Scattering Results\n\
|
||||
// Roughness dependent fresnel, from Fdez-Aguera\n\
|
||||
vec3 f90 = max(vec3(1.0 - roughness), f0);\n\
|
||||
vec3 singleScatterFresnel = fresnelSchlick2(f0, f90, NdotV);\n\
|
||||
\n\
|
||||
vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;\n\
|
||||
vec3 FssEss = specularWeight * (singleScatterFresnel * brdfLut.x + brdfLut.y);\n\
|
||||
\n\
|
||||
#ifdef DIFFUSE_IBL\n\
|
||||
vec3 normalMC = normalize(model_iblReferenceFrameMatrix * normalEC);\n\
|
||||
vec3 irradiance = sampleDiffuseEnvironment(normalMC);\n\
|
||||
\n\
|
||||
vec3 averageFresnel = f0 + (1.0 - f0) / 21.0;\n\
|
||||
float Ems = specularWeight * (1.0 - brdfLut.x - brdfLut.y);\n\
|
||||
vec3 FmsEms = FssEss * averageFresnel * Ems / (1.0 - averageFresnel * Ems);\n\
|
||||
vec3 dielectricScattering = (1.0 - FssEss - FmsEms) * material.diffuse;\n\
|
||||
vec3 diffuseContribution = irradiance * (FmsEms + dielectricScattering) * model_iblFactor.x;\n\
|
||||
#else\n\
|
||||
vec3 diffuseContribution = vec3(0.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_ANISOTROPY\n\
|
||||
// Bend normal to account for anisotropic distortion of specular reflection\n\
|
||||
vec3 anisotropyDirection = material.anisotropicB;\n\
|
||||
vec3 anisotropicTangent = cross(anisotropyDirection, viewDirectionEC);\n\
|
||||
vec3 anisotropicNormal = cross(anisotropicTangent, anisotropyDirection);\n\
|
||||
float bendFactor = 1.0 - material.anisotropyStrength * (1.0 - roughness);\n\
|
||||
float bendFactorPow4 = bendFactor * bendFactor * bendFactor * bendFactor;\n\
|
||||
vec3 bentNormal = normalize(mix(anisotropicNormal, normalEC, bendFactorPow4));\n\
|
||||
vec3 reflectEC = reflect(-viewDirectionEC, bentNormal);\n\
|
||||
#else\n\
|
||||
vec3 reflectEC = reflect(-viewDirectionEC, normalEC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef SPECULAR_IBL\n\
|
||||
vec3 reflectMC = normalize(model_iblReferenceFrameMatrix * reflectEC);\n\
|
||||
vec3 radiance = sampleSpecularEnvironment(reflectMC, roughness);\n\
|
||||
vec3 specularContribution = radiance * FssEss * model_iblFactor.y;\n\
|
||||
#else\n\
|
||||
vec3 specularContribution = vec3(0.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return diffuseContribution + specularContribution;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
";
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
mat4 getInstancingTransform()
|
||||
{
|
||||
mat4 instancingTransform;
|
||||
|
||||
#ifdef HAS_INSTANCE_MATRICES
|
||||
instancingTransform = mat4(
|
||||
a_instancingTransformRow0.x, a_instancingTransformRow1.x, a_instancingTransformRow2.x, 0.0, // Column 1
|
||||
a_instancingTransformRow0.y, a_instancingTransformRow1.y, a_instancingTransformRow2.y, 0.0, // Column 2
|
||||
a_instancingTransformRow0.z, a_instancingTransformRow1.z, a_instancingTransformRow2.z, 0.0, // Column 3
|
||||
a_instancingTransformRow0.w, a_instancingTransformRow1.w, a_instancingTransformRow2.w, 1.0 // Column 4
|
||||
);
|
||||
#else
|
||||
vec3 translation = vec3(0.0, 0.0, 0.0);
|
||||
vec3 scale = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
#ifdef HAS_INSTANCE_TRANSLATION
|
||||
translation = a_instanceTranslation;
|
||||
#endif
|
||||
#ifdef HAS_INSTANCE_SCALE
|
||||
scale = a_instanceScale;
|
||||
#endif
|
||||
|
||||
instancingTransform = mat4(
|
||||
scale.x, 0.0, 0.0, 0.0,
|
||||
0.0, scale.y, 0.0, 0.0,
|
||||
0.0, 0.0, scale.z, 0.0,
|
||||
translation.x, translation.y, translation.z, 1.0
|
||||
);
|
||||
#endif
|
||||
|
||||
return instancingTransform;
|
||||
}
|
||||
|
||||
#ifdef USE_2D_INSTANCING
|
||||
mat4 getInstancingTransform2D()
|
||||
{
|
||||
mat4 instancingTransform2D;
|
||||
|
||||
#ifdef HAS_INSTANCE_MATRICES
|
||||
instancingTransform2D = mat4(
|
||||
a_instancingTransform2DRow0.x, a_instancingTransform2DRow1.x, a_instancingTransform2DRow2.x, 0.0, // Column 1
|
||||
a_instancingTransform2DRow0.y, a_instancingTransform2DRow1.y, a_instancingTransform2DRow2.y, 0.0, // Column 2
|
||||
a_instancingTransform2DRow0.z, a_instancingTransform2DRow1.z, a_instancingTransform2DRow2.z, 0.0, // Column 3
|
||||
a_instancingTransform2DRow0.w, a_instancingTransform2DRow1.w, a_instancingTransform2DRow2.w, 1.0 // Column 4
|
||||
);
|
||||
#else
|
||||
vec3 translation2D = vec3(0.0, 0.0, 0.0);
|
||||
vec3 scale = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
#ifdef HAS_INSTANCE_TRANSLATION
|
||||
translation2D = a_instanceTranslation2D;
|
||||
#endif
|
||||
#ifdef HAS_INSTANCE_SCALE
|
||||
scale = a_instanceScale;
|
||||
#endif
|
||||
|
||||
instancingTransform2D = mat4(
|
||||
scale.x, 0.0, 0.0, 0.0,
|
||||
0.0, scale.y, 0.0, 0.0,
|
||||
0.0, 0.0, scale.z, 0.0,
|
||||
translation2D.x, translation2D.y, translation2D.z, 1.0
|
||||
);
|
||||
#endif
|
||||
|
||||
return instancingTransform2D;
|
||||
}
|
||||
#endif
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "mat4 getInstancingTransform()\n\
|
||||
{\n\
|
||||
mat4 instancingTransform;\n\
|
||||
\n\
|
||||
#ifdef HAS_INSTANCE_MATRICES\n\
|
||||
instancingTransform = mat4(\n\
|
||||
a_instancingTransformRow0.x, a_instancingTransformRow1.x, a_instancingTransformRow2.x, 0.0, // Column 1\n\
|
||||
a_instancingTransformRow0.y, a_instancingTransformRow1.y, a_instancingTransformRow2.y, 0.0, // Column 2\n\
|
||||
a_instancingTransformRow0.z, a_instancingTransformRow1.z, a_instancingTransformRow2.z, 0.0, // Column 3\n\
|
||||
a_instancingTransformRow0.w, a_instancingTransformRow1.w, a_instancingTransformRow2.w, 1.0 // Column 4\n\
|
||||
);\n\
|
||||
#else\n\
|
||||
vec3 translation = vec3(0.0, 0.0, 0.0);\n\
|
||||
vec3 scale = vec3(1.0, 1.0, 1.0);\n\
|
||||
\n\
|
||||
#ifdef HAS_INSTANCE_TRANSLATION\n\
|
||||
translation = a_instanceTranslation;\n\
|
||||
#endif\n\
|
||||
#ifdef HAS_INSTANCE_SCALE\n\
|
||||
scale = a_instanceScale;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
instancingTransform = mat4(\n\
|
||||
scale.x, 0.0, 0.0, 0.0,\n\
|
||||
0.0, scale.y, 0.0, 0.0,\n\
|
||||
0.0, 0.0, scale.z, 0.0,\n\
|
||||
translation.x, translation.y, translation.z, 1.0\n\
|
||||
); \n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return instancingTransform;\n\
|
||||
}\n\
|
||||
\n\
|
||||
#ifdef USE_2D_INSTANCING\n\
|
||||
mat4 getInstancingTransform2D()\n\
|
||||
{\n\
|
||||
mat4 instancingTransform2D;\n\
|
||||
\n\
|
||||
#ifdef HAS_INSTANCE_MATRICES\n\
|
||||
instancingTransform2D = mat4(\n\
|
||||
a_instancingTransform2DRow0.x, a_instancingTransform2DRow1.x, a_instancingTransform2DRow2.x, 0.0, // Column 1\n\
|
||||
a_instancingTransform2DRow0.y, a_instancingTransform2DRow1.y, a_instancingTransform2DRow2.y, 0.0, // Column 2\n\
|
||||
a_instancingTransform2DRow0.z, a_instancingTransform2DRow1.z, a_instancingTransform2DRow2.z, 0.0, // Column 3\n\
|
||||
a_instancingTransform2DRow0.w, a_instancingTransform2DRow1.w, a_instancingTransform2DRow2.w, 1.0 // Column 4\n\
|
||||
);\n\
|
||||
#else\n\
|
||||
vec3 translation2D = vec3(0.0, 0.0, 0.0);\n\
|
||||
vec3 scale = vec3(1.0, 1.0, 1.0);\n\
|
||||
\n\
|
||||
#ifdef HAS_INSTANCE_TRANSLATION\n\
|
||||
translation2D = a_instanceTranslation2D;\n\
|
||||
#endif\n\
|
||||
#ifdef HAS_INSTANCE_SCALE\n\
|
||||
scale = a_instanceScale;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
instancingTransform2D = mat4(\n\
|
||||
scale.x, 0.0, 0.0, 0.0,\n\
|
||||
0.0, scale.y, 0.0, 0.0,\n\
|
||||
0.0, 0.0, scale.z, 0.0,\n\
|
||||
translation2D.x, translation2D.y, translation2D.z, 1.0\n\
|
||||
); \n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return instancingTransform2D;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
";
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
void instancingStage(inout ProcessedAttributes attributes)
|
||||
{
|
||||
vec3 positionMC = attributes.positionMC;
|
||||
|
||||
mat4 instancingTransform = getInstancingTransform();
|
||||
|
||||
attributes.positionMC = (instancingTransform * vec4(positionMC, 1.0)).xyz;
|
||||
|
||||
#ifdef HAS_NORMALS
|
||||
vec3 normalMC = attributes.normalMC;
|
||||
attributes.normalMC = (instancingTransform * vec4(normalMC, 0.0)).xyz;
|
||||
#endif
|
||||
|
||||
#ifdef USE_2D_INSTANCING
|
||||
mat4 instancingTransform2D = getInstancingTransform2D();
|
||||
attributes.position2D = (instancingTransform2D * vec4(positionMC, 1.0)).xyz;
|
||||
#endif
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void instancingStage(inout ProcessedAttributes attributes) \n\
|
||||
{\n\
|
||||
vec3 positionMC = attributes.positionMC;\n\
|
||||
\n\
|
||||
mat4 instancingTransform = getInstancingTransform();\n\
|
||||
\n\
|
||||
attributes.positionMC = (instancingTransform * vec4(positionMC, 1.0)).xyz;\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
vec3 normalMC = attributes.normalMC;\n\
|
||||
attributes.normalMC = (instancingTransform * vec4(normalMC, 0.0)).xyz;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_2D_INSTANCING\n\
|
||||
mat4 instancingTransform2D = getInstancingTransform2D();\n\
|
||||
attributes.position2D = (instancingTransform2D * vec4(positionMC, 1.0)).xyz;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
void legacyInstancingStage(
|
||||
inout ProcessedAttributes attributes,
|
||||
out mat4 instanceModelView,
|
||||
out mat3 instanceModelViewInverseTranspose)
|
||||
{
|
||||
vec3 positionMC = attributes.positionMC;
|
||||
|
||||
mat4 instancingTransform = getInstancingTransform();
|
||||
|
||||
mat4 instanceModel = instancingTransform * u_instance_nodeTransform;
|
||||
instanceModelView = u_instance_modifiedModelView;
|
||||
instanceModelViewInverseTranspose = mat3(u_instance_modifiedModelView * instanceModel);
|
||||
|
||||
attributes.positionMC = (instanceModel * vec4(positionMC, 1.0)).xyz;
|
||||
|
||||
#ifdef USE_2D_INSTANCING
|
||||
mat4 instancingTransform2D = getInstancingTransform2D();
|
||||
attributes.position2D = (instancingTransform2D * vec4(positionMC, 1.0)).xyz;
|
||||
#endif
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void legacyInstancingStage(\n\
|
||||
inout ProcessedAttributes attributes,\n\
|
||||
out mat4 instanceModelView,\n\
|
||||
out mat3 instanceModelViewInverseTranspose)\n\
|
||||
{\n\
|
||||
vec3 positionMC = attributes.positionMC;\n\
|
||||
\n\
|
||||
mat4 instancingTransform = getInstancingTransform();\n\
|
||||
\n\
|
||||
mat4 instanceModel = instancingTransform * u_instance_nodeTransform;\n\
|
||||
instanceModelView = u_instance_modifiedModelView;\n\
|
||||
instanceModelViewInverseTranspose = mat3(u_instance_modifiedModelView * instanceModel);\n\
|
||||
\n\
|
||||
attributes.positionMC = (instanceModel * vec4(positionMC, 1.0)).xyz;\n\
|
||||
\n\
|
||||
#ifdef USE_2D_INSTANCING\n\
|
||||
mat4 instancingTransform2D = getInstancingTransform2D();\n\
|
||||
attributes.position2D = (instancingTransform2D * vec4(positionMC, 1.0)).xyz;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
#ifdef USE_IBL_LIGHTING
|
||||
vec3 computeIBL(vec3 position, vec3 normal, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material)
|
||||
{
|
||||
#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)
|
||||
// Environment maps were provided, use them for IBL
|
||||
vec3 viewDirection = -normalize(position);
|
||||
vec3 iblColor = textureIBL(viewDirection, normal, material);
|
||||
return iblColor;
|
||||
#endif
|
||||
|
||||
return vec3(0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_CLEARCOAT
|
||||
vec3 addClearcoatReflection(vec3 baseLayerColor, vec3 position, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material)
|
||||
{
|
||||
vec3 viewDirection = -normalize(position);
|
||||
vec3 halfwayDirection = normalize(viewDirection + lightDirection);
|
||||
vec3 normal = material.clearcoatNormal;
|
||||
float NdotL = clamp(dot(normal, lightDirection), 0.001, 1.0);
|
||||
|
||||
// clearcoatF0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0)), but without KHR_materials_ior, ior is a constant 1.5.
|
||||
vec3 f0 = vec3(0.04);
|
||||
vec3 f90 = vec3(1.0);
|
||||
// Note: clearcoat Fresnel computed with dot(n, v) instead of dot(v, h).
|
||||
// This is to make it energy conserving with a simple layering function.
|
||||
float NdotV = clamp(dot(normal, viewDirection), 0.0, 1.0);
|
||||
vec3 F = fresnelSchlick2(f0, f90, NdotV);
|
||||
|
||||
// compute specular reflection from direct lighting
|
||||
float roughness = material.clearcoatRoughness;
|
||||
float alphaRoughness = roughness * roughness;
|
||||
float directStrength = computeDirectSpecularStrength(normal, lightDirection, viewDirection, halfwayDirection, alphaRoughness);
|
||||
vec3 directReflection = F * directStrength * NdotL;
|
||||
vec3 color = lightColorHdr * directReflection;
|
||||
|
||||
#ifdef SPECULAR_IBL
|
||||
// Find the direction in which to sample the environment map
|
||||
vec3 reflectMC = normalize(model_iblReferenceFrameMatrix * reflect(-viewDirection, normal));
|
||||
vec3 iblColor = computeSpecularIBL(reflectMC, NdotV, f0, roughness);
|
||||
color += iblColor * material.occlusion;
|
||||
#endif
|
||||
|
||||
float clearcoatFactor = material.clearcoatFactor;
|
||||
vec3 clearcoatColor = color * clearcoatFactor;
|
||||
|
||||
// Dim base layer based on transmission loss through clearcoat
|
||||
return baseLayerColor * (1.0 - clearcoatFactor * F) + clearcoatColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LIGHTING_PBR) && defined(HAS_NORMALS)
|
||||
vec3 computePbrLighting(in czm_modelMaterial material, in vec3 position)
|
||||
{
|
||||
#ifdef USE_CUSTOM_LIGHT_COLOR
|
||||
vec3 lightColorHdr = model_lightColorHdr;
|
||||
#else
|
||||
vec3 lightColorHdr = czm_lightColorHdr;
|
||||
#endif
|
||||
|
||||
vec3 viewDirection = -normalize(position);
|
||||
vec3 normal = material.normalEC;
|
||||
vec3 lightDirection = normalize(czm_lightDirectionEC);
|
||||
|
||||
vec3 directLighting = czm_pbrLighting(viewDirection, normal, lightDirection, material);
|
||||
vec3 directColor = lightColorHdr * directLighting;
|
||||
|
||||
// Accumulate colors from base layer
|
||||
vec3 color = directColor + material.emissive;
|
||||
#ifdef USE_IBL_LIGHTING
|
||||
color += computeIBL(position, normal, lightDirection, lightColorHdr, material);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CLEARCOAT
|
||||
color = addClearcoatReflection(color, position, lightDirection, lightColorHdr, material);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compute the material color under the current lighting conditions.
|
||||
* All other material properties are passed through so further stages
|
||||
* have access to them.
|
||||
*
|
||||
* @param {czm_modelMaterial} material The material properties from {@MaterialStageFS}
|
||||
* @param {ProcessedAttributes} attributes
|
||||
*/
|
||||
void lightingStage(inout czm_modelMaterial material, ProcessedAttributes attributes)
|
||||
{
|
||||
#ifdef LIGHTING_PBR
|
||||
#ifdef HAS_NORMALS
|
||||
vec3 color = computePbrLighting(material, attributes.positionEC);
|
||||
#else
|
||||
vec3 color = material.diffuse * material.occlusion + material.emissive;
|
||||
#endif
|
||||
// In HDR mode, the frame buffer is in linear color space. The
|
||||
// post-processing stages (see PostProcessStageCollection) will handle
|
||||
// tonemapping. However, if HDR is not enabled, we must tonemap else large
|
||||
// values may be clamped to 1.0
|
||||
#ifndef HDR
|
||||
color = czm_pbrNeutralTonemapping(color);
|
||||
#endif
|
||||
#else // unlit
|
||||
vec3 color = material.diffuse;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE
|
||||
// The colors resulting from point cloud styles are adjusted differently.
|
||||
color = czm_gammaCorrect(color);
|
||||
#elif !defined(HDR)
|
||||
// If HDR is not enabled, the frame buffer stores sRGB colors rather than
|
||||
// linear colors so the linear value must be converted.
|
||||
color = czm_linearToSrgb(color);
|
||||
#endif
|
||||
|
||||
material.diffuse = color;
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "#ifdef USE_IBL_LIGHTING\n\
|
||||
vec3 computeIBL(vec3 position, vec3 normal, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material)\n\
|
||||
{\n\
|
||||
#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)\n\
|
||||
// Environment maps were provided, use them for IBL\n\
|
||||
vec3 viewDirection = -normalize(position);\n\
|
||||
vec3 iblColor = textureIBL(viewDirection, normal, material);\n\
|
||||
return iblColor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return vec3(0.0);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_CLEARCOAT\n\
|
||||
vec3 addClearcoatReflection(vec3 baseLayerColor, vec3 position, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material)\n\
|
||||
{\n\
|
||||
vec3 viewDirection = -normalize(position);\n\
|
||||
vec3 halfwayDirection = normalize(viewDirection + lightDirection);\n\
|
||||
vec3 normal = material.clearcoatNormal;\n\
|
||||
float NdotL = clamp(dot(normal, lightDirection), 0.001, 1.0);\n\
|
||||
\n\
|
||||
// clearcoatF0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0)), but without KHR_materials_ior, ior is a constant 1.5.\n\
|
||||
vec3 f0 = vec3(0.04);\n\
|
||||
vec3 f90 = vec3(1.0);\n\
|
||||
// Note: clearcoat Fresnel computed with dot(n, v) instead of dot(v, h).\n\
|
||||
// This is to make it energy conserving with a simple layering function.\n\
|
||||
float NdotV = clamp(dot(normal, viewDirection), 0.0, 1.0);\n\
|
||||
vec3 F = fresnelSchlick2(f0, f90, NdotV);\n\
|
||||
\n\
|
||||
// compute specular reflection from direct lighting\n\
|
||||
float roughness = material.clearcoatRoughness;\n\
|
||||
float alphaRoughness = roughness * roughness;\n\
|
||||
float directStrength = computeDirectSpecularStrength(normal, lightDirection, viewDirection, halfwayDirection, alphaRoughness);\n\
|
||||
vec3 directReflection = F * directStrength * NdotL;\n\
|
||||
vec3 color = lightColorHdr * directReflection;\n\
|
||||
\n\
|
||||
#ifdef SPECULAR_IBL\n\
|
||||
// Find the direction in which to sample the environment map\n\
|
||||
vec3 reflectMC = normalize(model_iblReferenceFrameMatrix * reflect(-viewDirection, normal));\n\
|
||||
vec3 iblColor = computeSpecularIBL(reflectMC, NdotV, f0, roughness);\n\
|
||||
color += iblColor * material.occlusion;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
float clearcoatFactor = material.clearcoatFactor;\n\
|
||||
vec3 clearcoatColor = color * clearcoatFactor;\n\
|
||||
\n\
|
||||
// Dim base layer based on transmission loss through clearcoat\n\
|
||||
return baseLayerColor * (1.0 - clearcoatFactor * F) + clearcoatColor;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(LIGHTING_PBR) && defined(HAS_NORMALS)\n\
|
||||
vec3 computePbrLighting(in czm_modelMaterial material, in vec3 position)\n\
|
||||
{\n\
|
||||
#ifdef USE_CUSTOM_LIGHT_COLOR\n\
|
||||
vec3 lightColorHdr = model_lightColorHdr;\n\
|
||||
#else\n\
|
||||
vec3 lightColorHdr = czm_lightColorHdr;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec3 viewDirection = -normalize(position);\n\
|
||||
vec3 normal = material.normalEC;\n\
|
||||
vec3 lightDirection = normalize(czm_lightDirectionEC);\n\
|
||||
\n\
|
||||
vec3 directLighting = czm_pbrLighting(viewDirection, normal, lightDirection, material);\n\
|
||||
vec3 directColor = lightColorHdr * directLighting;\n\
|
||||
\n\
|
||||
// Accumulate colors from base layer\n\
|
||||
vec3 color = directColor + material.emissive;\n\
|
||||
#ifdef USE_IBL_LIGHTING\n\
|
||||
color += computeIBL(position, normal, lightDirection, lightColorHdr, material);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_CLEARCOAT\n\
|
||||
color = addClearcoatReflection(color, position, lightDirection, lightColorHdr, material);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return color;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
/**\n\
|
||||
* Compute the material color under the current lighting conditions.\n\
|
||||
* All other material properties are passed through so further stages\n\
|
||||
* have access to them.\n\
|
||||
*\n\
|
||||
* @param {czm_modelMaterial} material The material properties from {@MaterialStageFS}\n\
|
||||
* @param {ProcessedAttributes} attributes\n\
|
||||
*/\n\
|
||||
void lightingStage(inout czm_modelMaterial material, ProcessedAttributes attributes)\n\
|
||||
{\n\
|
||||
#ifdef LIGHTING_PBR\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
vec3 color = computePbrLighting(material, attributes.positionEC);\n\
|
||||
#else\n\
|
||||
vec3 color = material.diffuse * material.occlusion + material.emissive;\n\
|
||||
#endif\n\
|
||||
// In HDR mode, the frame buffer is in linear color space. The\n\
|
||||
// post-processing stages (see PostProcessStageCollection) will handle\n\
|
||||
// tonemapping. However, if HDR is not enabled, we must tonemap else large\n\
|
||||
// values may be clamped to 1.0\n\
|
||||
#ifndef HDR\n\
|
||||
color = czm_pbrNeutralTonemapping(color);\n\
|
||||
#endif\n\
|
||||
#else // unlit\n\
|
||||
vec3 color = material.diffuse;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE\n\
|
||||
// The colors resulting from point cloud styles are adjusted differently.\n\
|
||||
color = czm_gammaCorrect(color);\n\
|
||||
#elif !defined(HDR)\n\
|
||||
// If HDR is not enabled, the frame buffer stores sRGB colors rather than\n\
|
||||
// linear colors so the linear value must be converted.\n\
|
||||
color = czm_linearToSrgb(color);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
material.diffuse = color;\n\
|
||||
}\n\
|
||||
";
|
||||
+529
@@ -0,0 +1,529 @@
|
||||
// If the style color is white, it implies the feature has not been styled.
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef HAS_NORMAL_TEXTURE
|
||||
vec2 getNormalTexCoords()
|
||||
{
|
||||
vec2 texCoord = TEXCOORD_NORMAL;
|
||||
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM
|
||||
texCoord = czm_computeTextureTransform(texCoord, u_normalTextureTransform);
|
||||
#endif
|
||||
return texCoord;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAS_NORMAL_TEXTURE) || defined(HAS_CLEARCOAT_NORMAL_TEXTURE)
|
||||
vec3 computeTangent(in vec3 position, in vec2 normalTexCoords)
|
||||
{
|
||||
vec2 tex_dx = dFdx(normalTexCoords);
|
||||
vec2 tex_dy = dFdy(normalTexCoords);
|
||||
float determinant = tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y;
|
||||
vec3 tangent = tex_dy.t * dFdx(position) - tex_dx.t * dFdy(position);
|
||||
return tangent / determinant;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_ANISOTROPY
|
||||
struct NormalInfo {
|
||||
vec3 tangent;
|
||||
vec3 bitangent;
|
||||
vec3 normal;
|
||||
vec3 geometryNormal;
|
||||
};
|
||||
|
||||
NormalInfo getNormalInfo(ProcessedAttributes attributes)
|
||||
{
|
||||
vec3 geometryNormal = attributes.normalEC;
|
||||
#ifdef HAS_NORMAL_TEXTURE
|
||||
vec2 normalTexCoords = getNormalTexCoords();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BITANGENTS
|
||||
vec3 tangent = attributes.tangentEC;
|
||||
vec3 bitangent = attributes.bitangentEC;
|
||||
#else // Assume HAS_NORMAL_TEXTURE
|
||||
vec3 tangent = computeTangent(attributes.positionEC, normalTexCoords);
|
||||
tangent = normalize(tangent - geometryNormal * dot(geometryNormal, tangent));
|
||||
vec3 bitangent = normalize(cross(geometryNormal, tangent));
|
||||
#endif
|
||||
|
||||
#ifdef HAS_NORMAL_TEXTURE
|
||||
mat3 tbn = mat3(tangent, bitangent, geometryNormal);
|
||||
|
||||
vec3 normalSample;
|
||||
#if defined(HAS_NORMAL_CONSTANT_LOD) && defined(HAS_CONSTANT_LOD)
|
||||
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams, u_normalTextureTransform).rgb;
|
||||
#else
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams).rgb;
|
||||
#endif
|
||||
#else
|
||||
normalSample = texture(u_normalTexture, normalTexCoords).rgb;
|
||||
#endif
|
||||
|
||||
normalSample = 2.0 * normalSample - 1.0;
|
||||
#ifdef HAS_NORMAL_TEXTURE_SCALE
|
||||
normalSample.xy *= u_normalTextureScale;
|
||||
#endif
|
||||
vec3 normal = normalize(tbn * normalSample);
|
||||
#else
|
||||
vec3 normal = geometryNormal;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DOUBLE_SIDED_MATERIAL
|
||||
if (czm_backFacing()) {
|
||||
tangent *= -1.0;
|
||||
bitangent *= -1.0;
|
||||
normal *= -1.0;
|
||||
geometryNormal *= -1.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
NormalInfo normalInfo;
|
||||
normalInfo.tangent = tangent;
|
||||
normalInfo.bitangent = bitangent;
|
||||
normalInfo.normal = normal;
|
||||
normalInfo.geometryNormal = geometryNormal;
|
||||
|
||||
return normalInfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)
|
||||
vec3 getNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal)
|
||||
{
|
||||
vec2 normalTexCoords = getNormalTexCoords();
|
||||
|
||||
// If HAS_BITANGENTS is set, then HAS_TANGENTS is also set
|
||||
#ifdef HAS_BITANGENTS
|
||||
vec3 t = attributes.tangentEC;
|
||||
vec3 b = attributes.bitangentEC;
|
||||
#else
|
||||
vec3 t = computeTangent(attributes.positionEC, normalTexCoords);
|
||||
t = normalize(t - geometryNormal * dot(geometryNormal, t));
|
||||
vec3 b = normalize(cross(geometryNormal, t));
|
||||
#endif
|
||||
|
||||
mat3 tbn = mat3(t, b, geometryNormal);
|
||||
|
||||
vec3 normalSample;
|
||||
#if defined(HAS_NORMAL_CONSTANT_LOD) && defined(HAS_CONSTANT_LOD)
|
||||
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams, u_normalTextureTransform).rgb;
|
||||
#else
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams).rgb;
|
||||
#endif
|
||||
#else
|
||||
normalSample = texture(u_normalTexture, normalTexCoords).rgb;
|
||||
#endif
|
||||
|
||||
normalSample = 2.0 * normalSample - 1.0;
|
||||
#ifdef HAS_NORMAL_TEXTURE_SCALE
|
||||
normalSample.xy *= u_normalTextureScale;
|
||||
#endif
|
||||
return normalize(tbn * normalSample);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE
|
||||
vec3 getClearcoatNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal)
|
||||
{
|
||||
vec2 normalTexCoords = TEXCOORD_CLEARCOAT_NORMAL;
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_TRANSFORM
|
||||
normalTexCoords = vec2(u_clearcoatNormalTextureTransform * vec3(normalTexCoords, 1.0));
|
||||
#endif
|
||||
|
||||
// If HAS_BITANGENTS is set, then HAS_TANGENTS is also set
|
||||
#ifdef HAS_BITANGENTS
|
||||
vec3 t = attributes.tangentEC;
|
||||
vec3 b = attributes.bitangentEC;
|
||||
#else
|
||||
vec3 t = computeTangent(attributes.positionEC, normalTexCoords);
|
||||
t = normalize(t - geometryNormal * dot(geometryNormal, t));
|
||||
vec3 b = normalize(cross(geometryNormal, t));
|
||||
#endif
|
||||
|
||||
mat3 tbn = mat3(t, b, geometryNormal);
|
||||
vec3 normalSample = texture(u_clearcoatNormalTexture, normalTexCoords).rgb;
|
||||
normalSample = 2.0 * normalSample - 1.0;
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_SCALE
|
||||
normalSample.xy *= u_clearcoatNormalTextureScale;
|
||||
#endif
|
||||
return normalize(tbn * normalSample);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_NORMALS
|
||||
vec3 computeNormal(ProcessedAttributes attributes)
|
||||
{
|
||||
// Geometry normal. This is already normalized
|
||||
vec3 normal = attributes.normalEC;
|
||||
|
||||
#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)
|
||||
normal = getNormalFromTexture(attributes, normal);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DOUBLE_SIDED_MATERIAL
|
||||
if (czm_backFacing()) {
|
||||
normal = -normal;
|
||||
}
|
||||
#endif
|
||||
|
||||
return normal;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BASE_COLOR_TEXTURE
|
||||
vec4 getBaseColorFromTexture()
|
||||
{
|
||||
vec2 baseColorTexCoords = TEXCOORD_BASE_COLOR;
|
||||
#ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM
|
||||
baseColorTexCoords = czm_computeTextureTransform(baseColorTexCoords, u_baseColorTextureTransform);
|
||||
#endif
|
||||
|
||||
vec4 baseColorWithAlpha;
|
||||
#if defined(HAS_BASE_COLOR_CONSTANT_LOD) && defined(HAS_CONSTANT_LOD)
|
||||
#ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM
|
||||
baseColorWithAlpha = czm_srgbToLinear(constantLodTextureLookup(u_baseColorTexture, u_baseColorTextureConstantLodParams, u_baseColorTextureTransform));
|
||||
#else
|
||||
baseColorWithAlpha = czm_srgbToLinear(constantLodTextureLookup(u_baseColorTexture, u_baseColorTextureConstantLodParams));
|
||||
#endif
|
||||
#else
|
||||
baseColorWithAlpha = czm_srgbToLinear(texture(u_baseColorTexture, baseColorTexCoords));
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BASE_COLOR_FACTOR
|
||||
baseColorWithAlpha *= u_baseColorFactor;
|
||||
#endif
|
||||
|
||||
return baseColorWithAlpha;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EMISSIVE_TEXTURE
|
||||
vec3 getEmissiveFromTexture()
|
||||
{
|
||||
vec2 emissiveTexCoords = TEXCOORD_EMISSIVE;
|
||||
#ifdef HAS_EMISSIVE_TEXTURE_TRANSFORM
|
||||
emissiveTexCoords = czm_computeTextureTransform(emissiveTexCoords, u_emissiveTextureTransform);
|
||||
#endif
|
||||
|
||||
vec3 emissive = czm_srgbToLinear(texture(u_emissiveTexture, emissiveTexCoords).rgb);
|
||||
#ifdef HAS_EMISSIVE_FACTOR
|
||||
emissive *= u_emissiveFactor;
|
||||
#endif
|
||||
|
||||
return emissive;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)
|
||||
void setSpecularGlossiness(inout czm_modelMaterial material)
|
||||
{
|
||||
#ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE
|
||||
vec2 specularGlossinessTexCoords = TEXCOORD_SPECULAR_GLOSSINESS;
|
||||
#ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE_TRANSFORM
|
||||
specularGlossinessTexCoords = czm_computeTextureTransform(specularGlossinessTexCoords, u_specularGlossinessTextureTransform);
|
||||
#endif
|
||||
|
||||
vec4 specularGlossiness = czm_srgbToLinear(texture(u_specularGlossinessTexture, specularGlossinessTexCoords));
|
||||
vec3 specular = specularGlossiness.rgb;
|
||||
float glossiness = specularGlossiness.a;
|
||||
#ifdef HAS_LEGACY_SPECULAR_FACTOR
|
||||
specular *= u_legacySpecularFactor;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_GLOSSINESS_FACTOR
|
||||
glossiness *= u_glossinessFactor;
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAS_LEGACY_SPECULAR_FACTOR
|
||||
vec3 specular = clamp(u_legacySpecularFactor, 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 = czm_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
|
||||
|
||||
material.diffuse = diffuse.rgb * (1.0 - czm_maximumComponent(specular));
|
||||
// the specular glossiness extension's alpha overrides anything set
|
||||
// by the base material.
|
||||
material.alpha = diffuse.a;
|
||||
|
||||
material.specular = specular;
|
||||
|
||||
// glossiness is the opposite of roughness, but easier for artists to use.
|
||||
material.roughness = 1.0 - glossiness;
|
||||
}
|
||||
#elif defined(LIGHTING_PBR)
|
||||
float setMetallicRoughness(inout czm_modelMaterial material)
|
||||
{
|
||||
#ifdef HAS_METALLIC_ROUGHNESS_TEXTURE
|
||||
vec2 metallicRoughnessTexCoords = TEXCOORD_METALLIC_ROUGHNESS;
|
||||
#ifdef HAS_METALLIC_ROUGHNESS_TEXTURE_TRANSFORM
|
||||
metallicRoughnessTexCoords = czm_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.0, 1.0);
|
||||
#ifdef HAS_METALLIC_FACTOR
|
||||
metalness = clamp(metalness * u_metallicFactor, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_ROUGHNESS_FACTOR
|
||||
roughness = clamp(roughness * u_roughnessFactor, 0.0, 1.0);
|
||||
#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.0, 1.0);
|
||||
#else
|
||||
float roughness = 1.0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// dielectrics use f0 = 0.04, metals use albedo as f0
|
||||
const vec3 REFLECTANCE_DIELECTRIC = vec3(0.04);
|
||||
vec3 f0 = mix(REFLECTANCE_DIELECTRIC, material.baseColor.rgb, metalness);
|
||||
|
||||
material.specular = f0;
|
||||
|
||||
// diffuse only applies to dielectrics.
|
||||
material.diffuse = mix(material.baseColor.rgb, vec3(0.0), metalness);
|
||||
|
||||
// This is perceptual roughness. The square of this value is used for direct lighting
|
||||
material.roughness = roughness;
|
||||
|
||||
return metalness;
|
||||
}
|
||||
#ifdef USE_SPECULAR
|
||||
void setSpecular(inout czm_modelMaterial material, in float metalness)
|
||||
{
|
||||
#ifdef HAS_SPECULAR_TEXTURE
|
||||
vec2 specularTexCoords = TEXCOORD_SPECULAR;
|
||||
#ifdef HAS_SPECULAR_TEXTURE_TRANSFORM
|
||||
specularTexCoords = czm_computeTextureTransform(specularTexCoords, u_specularTextureTransform);
|
||||
#endif
|
||||
float specularWeight = texture(u_specularTexture, specularTexCoords).a;
|
||||
#ifdef HAS_SPECULAR_FACTOR
|
||||
specularWeight *= u_specularFactor;
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAS_SPECULAR_FACTOR
|
||||
float specularWeight = u_specularFactor;
|
||||
#else
|
||||
float specularWeight = 1.0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SPECULAR_COLOR_TEXTURE
|
||||
vec2 specularColorTexCoords = TEXCOORD_SPECULAR_COLOR;
|
||||
#ifdef HAS_SPECULAR_COLOR_TEXTURE_TRANSFORM
|
||||
specularColorTexCoords = czm_computeTextureTransform(specularColorTexCoords, u_specularColorTextureTransform);
|
||||
#endif
|
||||
vec3 specularColorSample = texture(u_specularColorTexture, specularColorTexCoords).rgb;
|
||||
vec3 specularColorFactor = czm_srgbToLinear(specularColorSample);
|
||||
#ifdef HAS_SPECULAR_COLOR_FACTOR
|
||||
specularColorFactor *= u_specularColorFactor;
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAS_SPECULAR_COLOR_FACTOR
|
||||
vec3 specularColorFactor = u_specularColorFactor;
|
||||
#else
|
||||
vec3 specularColorFactor = vec3(1.0);
|
||||
#endif
|
||||
#endif
|
||||
material.specularWeight = specularWeight;
|
||||
vec3 f0 = material.specular;
|
||||
vec3 dielectricSpecularF0 = min(f0 * specularColorFactor, vec3(1.0));
|
||||
material.specular = mix(dielectricSpecularF0, material.baseColor.rgb, metalness);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ANISOTROPY
|
||||
void setAnisotropy(inout czm_modelMaterial material, in NormalInfo normalInfo)
|
||||
{
|
||||
mat2 rotation = mat2(u_anisotropy.xy, -u_anisotropy.y, u_anisotropy.x);
|
||||
float anisotropyStrength = u_anisotropy.z;
|
||||
|
||||
vec2 direction = vec2(1.0, 0.0);
|
||||
#ifdef HAS_ANISOTROPY_TEXTURE
|
||||
vec2 anisotropyTexCoords = TEXCOORD_ANISOTROPY;
|
||||
#ifdef HAS_ANISOTROPY_TEXTURE_TRANSFORM
|
||||
anisotropyTexCoords = czm_computeTextureTransform(anisotropyTexCoords, u_anisotropyTextureTransform);
|
||||
#endif
|
||||
vec3 anisotropySample = texture(u_anisotropyTexture, anisotropyTexCoords).rgb;
|
||||
direction = anisotropySample.rg * 2.0 - vec2(1.0);
|
||||
anisotropyStrength *= anisotropySample.b;
|
||||
#endif
|
||||
|
||||
direction = rotation * direction;
|
||||
mat3 tbn = mat3(normalInfo.tangent, normalInfo.bitangent, normalInfo.normal);
|
||||
vec3 anisotropicT = tbn * normalize(vec3(direction, 0.0));
|
||||
vec3 anisotropicB = cross(normalInfo.geometryNormal, anisotropicT);
|
||||
|
||||
material.anisotropicT = anisotropicT;
|
||||
material.anisotropicB = anisotropicB;
|
||||
material.anisotropyStrength = anisotropyStrength;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CLEARCOAT
|
||||
void setClearcoat(inout czm_modelMaterial material, in ProcessedAttributes attributes)
|
||||
{
|
||||
#ifdef HAS_CLEARCOAT_TEXTURE
|
||||
vec2 clearcoatTexCoords = TEXCOORD_CLEARCOAT;
|
||||
#ifdef HAS_CLEARCOAT_TEXTURE_TRANSFORM
|
||||
clearcoatTexCoords = czm_computeTextureTransform(clearcoatTexCoords, u_clearcoatTextureTransform);
|
||||
#endif
|
||||
float clearcoatFactor = texture(u_clearcoatTexture, clearcoatTexCoords).r;
|
||||
#ifdef HAS_CLEARCOAT_FACTOR
|
||||
clearcoatFactor *= u_clearcoatFactor;
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAS_CLEARCOAT_FACTOR
|
||||
float clearcoatFactor = u_clearcoatFactor;
|
||||
#else
|
||||
// PERFORMANCE_IDEA: this case should turn the whole extension off
|
||||
float clearcoatFactor = 0.0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE
|
||||
vec2 clearcoatRoughnessTexCoords = TEXCOORD_CLEARCOAT_ROUGHNESS;
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE_TRANSFORM
|
||||
clearcoatRoughnessTexCoords = czm_computeTextureTransform(clearcoatRoughnessTexCoords, u_clearcoatRoughnessTextureTransform);
|
||||
#endif
|
||||
float clearcoatRoughness = texture(u_clearcoatRoughnessTexture, clearcoatRoughnessTexCoords).g;
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR
|
||||
clearcoatRoughness *= u_clearcoatRoughnessFactor;
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR
|
||||
float clearcoatRoughness = u_clearcoatRoughnessFactor;
|
||||
#else
|
||||
float clearcoatRoughness = 0.0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
material.clearcoatFactor = clearcoatFactor;
|
||||
// This is perceptual roughness. The square of this value is used for direct lighting
|
||||
material.clearcoatRoughness = clearcoatRoughness;
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE
|
||||
material.clearcoatNormal = getClearcoatNormalFromTexture(attributes, attributes.normalEC);
|
||||
#else
|
||||
material.clearcoatNormal = attributes.normalEC;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void materialStage(inout czm_modelMaterial material, ProcessedAttributes attributes, SelectedFeature feature)
|
||||
{
|
||||
#ifdef USE_ANISOTROPY
|
||||
NormalInfo normalInfo = getNormalInfo(attributes);
|
||||
material.normalEC = normalInfo.normal;
|
||||
#elif defined(HAS_NORMALS)
|
||||
material.normalEC = computeNormal(attributes);
|
||||
#endif
|
||||
|
||||
vec4 baseColorWithAlpha = vec4(1.0);
|
||||
// Regardless of whether we use PBR, set a base color.
|
||||
// HAS_BACKGROUND_FILL (from BENTLEY_materials_planar_fill) overrides with
|
||||
// the view's background color to create an invisible masking polygon.
|
||||
// The background color is in sRGB, so convert to linear to match the
|
||||
// material pipeline's expected color space.
|
||||
#ifdef HAS_BACKGROUND_FILL
|
||||
baseColorWithAlpha = czm_srgbToLinear(czm_backgroundColor);
|
||||
#elif defined(HAS_BASE_COLOR_TEXTURE)
|
||||
baseColorWithAlpha = getBaseColorFromTexture();
|
||||
#elif defined(HAS_BASE_COLOR_FACTOR)
|
||||
baseColorWithAlpha = u_baseColorFactor;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_IMAGERY
|
||||
baseColorWithAlpha = blendBaseColorWithImagery(baseColorWithAlpha);
|
||||
#endif // HAS_IMAGERY
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE
|
||||
baseColorWithAlpha = v_pointCloudColor;
|
||||
#elif defined(HAS_COLOR_0)
|
||||
vec4 color = attributes.color_0;
|
||||
// .pnts files store colors in the sRGB color space
|
||||
#ifdef HAS_SRGB_COLOR
|
||||
color = czm_srgbToLinear(color);
|
||||
#endif
|
||||
baseColorWithAlpha *= color;
|
||||
#endif
|
||||
|
||||
#ifdef USE_CPU_STYLING
|
||||
baseColorWithAlpha.rgb = blend(baseColorWithAlpha.rgb, feature.color.rgb, model_colorBlend);
|
||||
#endif
|
||||
material.baseColor = baseColorWithAlpha;
|
||||
material.diffuse = baseColorWithAlpha.rgb;
|
||||
material.alpha = baseColorWithAlpha.a;
|
||||
|
||||
#ifdef HAS_OCCLUSION_TEXTURE
|
||||
vec2 occlusionTexCoords = TEXCOORD_OCCLUSION;
|
||||
#ifdef HAS_OCCLUSION_TEXTURE_TRANSFORM
|
||||
occlusionTexCoords = czm_computeTextureTransform(occlusionTexCoords, u_occlusionTextureTransform);
|
||||
#endif
|
||||
material.occlusion = texture(u_occlusionTexture, occlusionTexCoords).r;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EMISSIVE_TEXTURE
|
||||
material.emissive = getEmissiveFromTexture();
|
||||
#elif defined(HAS_EMISSIVE_FACTOR)
|
||||
material.emissive = u_emissiveFactor;
|
||||
#endif
|
||||
|
||||
#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)
|
||||
setSpecularGlossiness(material);
|
||||
#elif defined(LIGHTING_PBR)
|
||||
float metalness = setMetallicRoughness(material);
|
||||
#ifdef USE_SPECULAR
|
||||
setSpecular(material, metalness);
|
||||
#endif
|
||||
#ifdef USE_ANISOTROPY
|
||||
setAnisotropy(material, normalInfo);
|
||||
#endif
|
||||
#ifdef USE_CLEARCOAT
|
||||
setClearcoat(material, attributes);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
+531
@@ -0,0 +1,531 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "// If the style color is white, it implies the feature has not been styled.\n\
|
||||
bool isDefaultStyleColor(vec3 color)\n\
|
||||
{\n\
|
||||
return all(greaterThan(color, vec3(1.0 - czm_epsilon3)));\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec3 blend(vec3 sourceColor, vec3 styleColor, float styleColorBlend)\n\
|
||||
{\n\
|
||||
vec3 blendColor = mix(sourceColor, styleColor, styleColorBlend);\n\
|
||||
vec3 color = isDefaultStyleColor(styleColor.rgb) ? sourceColor : blendColor;\n\
|
||||
return color;\n\
|
||||
}\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE\n\
|
||||
vec2 getNormalTexCoords()\n\
|
||||
{\n\
|
||||
vec2 texCoord = TEXCOORD_NORMAL;\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM\n\
|
||||
texCoord = czm_computeTextureTransform(texCoord, u_normalTextureTransform);\n\
|
||||
#endif\n\
|
||||
return texCoord;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(HAS_NORMAL_TEXTURE) || defined(HAS_CLEARCOAT_NORMAL_TEXTURE)\n\
|
||||
vec3 computeTangent(in vec3 position, in vec2 normalTexCoords)\n\
|
||||
{\n\
|
||||
vec2 tex_dx = dFdx(normalTexCoords);\n\
|
||||
vec2 tex_dy = dFdy(normalTexCoords);\n\
|
||||
float determinant = tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y;\n\
|
||||
vec3 tangent = tex_dy.t * dFdx(position) - tex_dx.t * dFdy(position);\n\
|
||||
return tangent / determinant;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_ANISOTROPY\n\
|
||||
struct NormalInfo {\n\
|
||||
vec3 tangent;\n\
|
||||
vec3 bitangent;\n\
|
||||
vec3 normal;\n\
|
||||
vec3 geometryNormal;\n\
|
||||
};\n\
|
||||
\n\
|
||||
NormalInfo getNormalInfo(ProcessedAttributes attributes)\n\
|
||||
{\n\
|
||||
vec3 geometryNormal = attributes.normalEC;\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE\n\
|
||||
vec2 normalTexCoords = getNormalTexCoords();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_BITANGENTS\n\
|
||||
vec3 tangent = attributes.tangentEC;\n\
|
||||
vec3 bitangent = attributes.bitangentEC;\n\
|
||||
#else // Assume HAS_NORMAL_TEXTURE\n\
|
||||
vec3 tangent = computeTangent(attributes.positionEC, normalTexCoords);\n\
|
||||
tangent = normalize(tangent - geometryNormal * dot(geometryNormal, tangent));\n\
|
||||
vec3 bitangent = normalize(cross(geometryNormal, tangent));\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE\n\
|
||||
mat3 tbn = mat3(tangent, bitangent, geometryNormal);\n\
|
||||
\n\
|
||||
vec3 normalSample;\n\
|
||||
#if defined(HAS_NORMAL_CONSTANT_LOD) && defined(HAS_CONSTANT_LOD)\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM\n\
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams, u_normalTextureTransform).rgb;\n\
|
||||
#else\n\
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams).rgb;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
normalSample = texture(u_normalTexture, normalTexCoords).rgb;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
normalSample = 2.0 * normalSample - 1.0;\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE_SCALE\n\
|
||||
normalSample.xy *= u_normalTextureScale;\n\
|
||||
#endif\n\
|
||||
vec3 normal = normalize(tbn * normalSample);\n\
|
||||
#else\n\
|
||||
vec3 normal = geometryNormal;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_DOUBLE_SIDED_MATERIAL\n\
|
||||
if (czm_backFacing()) {\n\
|
||||
tangent *= -1.0;\n\
|
||||
bitangent *= -1.0;\n\
|
||||
normal *= -1.0;\n\
|
||||
geometryNormal *= -1.0;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
NormalInfo normalInfo;\n\
|
||||
normalInfo.tangent = tangent;\n\
|
||||
normalInfo.bitangent = bitangent;\n\
|
||||
normalInfo.normal = normal;\n\
|
||||
normalInfo.geometryNormal = geometryNormal;\n\
|
||||
\n\
|
||||
return normalInfo;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)\n\
|
||||
vec3 getNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal)\n\
|
||||
{\n\
|
||||
vec2 normalTexCoords = getNormalTexCoords();\n\
|
||||
\n\
|
||||
// If HAS_BITANGENTS is set, then HAS_TANGENTS is also set\n\
|
||||
#ifdef HAS_BITANGENTS\n\
|
||||
vec3 t = attributes.tangentEC;\n\
|
||||
vec3 b = attributes.bitangentEC;\n\
|
||||
#else\n\
|
||||
vec3 t = computeTangent(attributes.positionEC, normalTexCoords);\n\
|
||||
t = normalize(t - geometryNormal * dot(geometryNormal, t));\n\
|
||||
vec3 b = normalize(cross(geometryNormal, t));\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
mat3 tbn = mat3(t, b, geometryNormal);\n\
|
||||
\n\
|
||||
vec3 normalSample;\n\
|
||||
#if defined(HAS_NORMAL_CONSTANT_LOD) && defined(HAS_CONSTANT_LOD)\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE_TRANSFORM\n\
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams, u_normalTextureTransform).rgb;\n\
|
||||
#else\n\
|
||||
normalSample = constantLodTextureLookup(u_normalTexture, u_normalTextureConstantLodParams).rgb;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
normalSample = texture(u_normalTexture, normalTexCoords).rgb;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
normalSample = 2.0 * normalSample - 1.0;\n\
|
||||
#ifdef HAS_NORMAL_TEXTURE_SCALE\n\
|
||||
normalSample.xy *= u_normalTextureScale;\n\
|
||||
#endif\n\
|
||||
return normalize(tbn * normalSample);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE\n\
|
||||
vec3 getClearcoatNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal)\n\
|
||||
{\n\
|
||||
vec2 normalTexCoords = TEXCOORD_CLEARCOAT_NORMAL;\n\
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_TRANSFORM\n\
|
||||
normalTexCoords = vec2(u_clearcoatNormalTextureTransform * vec3(normalTexCoords, 1.0));\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// If HAS_BITANGENTS is set, then HAS_TANGENTS is also set\n\
|
||||
#ifdef HAS_BITANGENTS\n\
|
||||
vec3 t = attributes.tangentEC;\n\
|
||||
vec3 b = attributes.bitangentEC;\n\
|
||||
#else\n\
|
||||
vec3 t = computeTangent(attributes.positionEC, normalTexCoords);\n\
|
||||
t = normalize(t - geometryNormal * dot(geometryNormal, t));\n\
|
||||
vec3 b = normalize(cross(geometryNormal, t));\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
mat3 tbn = mat3(t, b, geometryNormal);\n\
|
||||
vec3 normalSample = texture(u_clearcoatNormalTexture, normalTexCoords).rgb;\n\
|
||||
normalSample = 2.0 * normalSample - 1.0;\n\
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_SCALE\n\
|
||||
normalSample.xy *= u_clearcoatNormalTextureScale;\n\
|
||||
#endif\n\
|
||||
return normalize(tbn * normalSample);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
vec3 computeNormal(ProcessedAttributes attributes)\n\
|
||||
{\n\
|
||||
// Geometry normal. This is already normalized \n\
|
||||
vec3 normal = attributes.normalEC;\n\
|
||||
\n\
|
||||
#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)\n\
|
||||
normal = getNormalFromTexture(attributes, normal);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_DOUBLE_SIDED_MATERIAL\n\
|
||||
if (czm_backFacing()) {\n\
|
||||
normal = -normal;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return normal;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_BASE_COLOR_TEXTURE\n\
|
||||
vec4 getBaseColorFromTexture()\n\
|
||||
{\n\
|
||||
vec2 baseColorTexCoords = TEXCOORD_BASE_COLOR;\n\
|
||||
#ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM\n\
|
||||
baseColorTexCoords = czm_computeTextureTransform(baseColorTexCoords, u_baseColorTextureTransform);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 baseColorWithAlpha;\n\
|
||||
#if defined(HAS_BASE_COLOR_CONSTANT_LOD) && defined(HAS_CONSTANT_LOD)\n\
|
||||
#ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM\n\
|
||||
baseColorWithAlpha = czm_srgbToLinear(constantLodTextureLookup(u_baseColorTexture, u_baseColorTextureConstantLodParams, u_baseColorTextureTransform));\n\
|
||||
#else\n\
|
||||
baseColorWithAlpha = czm_srgbToLinear(constantLodTextureLookup(u_baseColorTexture, u_baseColorTextureConstantLodParams));\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
baseColorWithAlpha = czm_srgbToLinear(texture(u_baseColorTexture, baseColorTexCoords));\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_BASE_COLOR_FACTOR\n\
|
||||
baseColorWithAlpha *= u_baseColorFactor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return baseColorWithAlpha;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_EMISSIVE_TEXTURE\n\
|
||||
vec3 getEmissiveFromTexture()\n\
|
||||
{\n\
|
||||
vec2 emissiveTexCoords = TEXCOORD_EMISSIVE;\n\
|
||||
#ifdef HAS_EMISSIVE_TEXTURE_TRANSFORM\n\
|
||||
emissiveTexCoords = czm_computeTextureTransform(emissiveTexCoords, u_emissiveTextureTransform);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec3 emissive = czm_srgbToLinear(texture(u_emissiveTexture, emissiveTexCoords).rgb);\n\
|
||||
#ifdef HAS_EMISSIVE_FACTOR\n\
|
||||
emissive *= u_emissiveFactor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return emissive;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)\n\
|
||||
void setSpecularGlossiness(inout czm_modelMaterial material)\n\
|
||||
{\n\
|
||||
#ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE\n\
|
||||
vec2 specularGlossinessTexCoords = TEXCOORD_SPECULAR_GLOSSINESS;\n\
|
||||
#ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE_TRANSFORM\n\
|
||||
specularGlossinessTexCoords = czm_computeTextureTransform(specularGlossinessTexCoords, u_specularGlossinessTextureTransform);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 specularGlossiness = czm_srgbToLinear(texture(u_specularGlossinessTexture, specularGlossinessTexCoords));\n\
|
||||
vec3 specular = specularGlossiness.rgb;\n\
|
||||
float glossiness = specularGlossiness.a;\n\
|
||||
#ifdef HAS_LEGACY_SPECULAR_FACTOR\n\
|
||||
specular *= u_legacySpecularFactor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_GLOSSINESS_FACTOR\n\
|
||||
glossiness *= u_glossinessFactor;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
#ifdef HAS_LEGACY_SPECULAR_FACTOR\n\
|
||||
vec3 specular = clamp(u_legacySpecularFactor, vec3(0.0), vec3(1.0));\n\
|
||||
#else\n\
|
||||
vec3 specular = vec3(1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_GLOSSINESS_FACTOR\n\
|
||||
float glossiness = clamp(u_glossinessFactor, 0.0, 1.0);\n\
|
||||
#else\n\
|
||||
float glossiness = 1.0;\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_DIFFUSE_TEXTURE\n\
|
||||
vec2 diffuseTexCoords = TEXCOORD_DIFFUSE;\n\
|
||||
#ifdef HAS_DIFFUSE_TEXTURE_TRANSFORM\n\
|
||||
diffuseTexCoords = czm_computeTextureTransform(diffuseTexCoords, u_diffuseTextureTransform);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 diffuse = czm_srgbToLinear(texture(u_diffuseTexture, diffuseTexCoords));\n\
|
||||
#ifdef HAS_DIFFUSE_FACTOR\n\
|
||||
diffuse *= u_diffuseFactor;\n\
|
||||
#endif\n\
|
||||
#elif defined(HAS_DIFFUSE_FACTOR)\n\
|
||||
vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0));\n\
|
||||
#else\n\
|
||||
vec4 diffuse = vec4(1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
material.diffuse = diffuse.rgb * (1.0 - czm_maximumComponent(specular));\n\
|
||||
// the specular glossiness extension's alpha overrides anything set\n\
|
||||
// by the base material.\n\
|
||||
material.alpha = diffuse.a;\n\
|
||||
\n\
|
||||
material.specular = specular;\n\
|
||||
\n\
|
||||
// glossiness is the opposite of roughness, but easier for artists to use.\n\
|
||||
material.roughness = 1.0 - glossiness;\n\
|
||||
}\n\
|
||||
#elif defined(LIGHTING_PBR)\n\
|
||||
float setMetallicRoughness(inout czm_modelMaterial material)\n\
|
||||
{\n\
|
||||
#ifdef HAS_METALLIC_ROUGHNESS_TEXTURE\n\
|
||||
vec2 metallicRoughnessTexCoords = TEXCOORD_METALLIC_ROUGHNESS;\n\
|
||||
#ifdef HAS_METALLIC_ROUGHNESS_TEXTURE_TRANSFORM\n\
|
||||
metallicRoughnessTexCoords = czm_computeTextureTransform(metallicRoughnessTexCoords, u_metallicRoughnessTextureTransform);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec3 metallicRoughness = texture(u_metallicRoughnessTexture, metallicRoughnessTexCoords).rgb;\n\
|
||||
float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\n\
|
||||
float roughness = clamp(metallicRoughness.g, 0.0, 1.0);\n\
|
||||
#ifdef HAS_METALLIC_FACTOR\n\
|
||||
metalness = clamp(metalness * u_metallicFactor, 0.0, 1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_ROUGHNESS_FACTOR\n\
|
||||
roughness = clamp(roughness * u_roughnessFactor, 0.0, 1.0);\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
#ifdef HAS_METALLIC_FACTOR\n\
|
||||
float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n\
|
||||
#else\n\
|
||||
float metalness = 1.0;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_ROUGHNESS_FACTOR\n\
|
||||
float roughness = clamp(u_roughnessFactor, 0.0, 1.0);\n\
|
||||
#else\n\
|
||||
float roughness = 1.0;\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// dielectrics use f0 = 0.04, metals use albedo as f0\n\
|
||||
const vec3 REFLECTANCE_DIELECTRIC = vec3(0.04);\n\
|
||||
vec3 f0 = mix(REFLECTANCE_DIELECTRIC, material.baseColor.rgb, metalness);\n\
|
||||
\n\
|
||||
material.specular = f0;\n\
|
||||
\n\
|
||||
// diffuse only applies to dielectrics.\n\
|
||||
material.diffuse = mix(material.baseColor.rgb, vec3(0.0), metalness);\n\
|
||||
\n\
|
||||
// This is perceptual roughness. The square of this value is used for direct lighting\n\
|
||||
material.roughness = roughness;\n\
|
||||
\n\
|
||||
return metalness;\n\
|
||||
}\n\
|
||||
#ifdef USE_SPECULAR\n\
|
||||
void setSpecular(inout czm_modelMaterial material, in float metalness)\n\
|
||||
{\n\
|
||||
#ifdef HAS_SPECULAR_TEXTURE\n\
|
||||
vec2 specularTexCoords = TEXCOORD_SPECULAR;\n\
|
||||
#ifdef HAS_SPECULAR_TEXTURE_TRANSFORM\n\
|
||||
specularTexCoords = czm_computeTextureTransform(specularTexCoords, u_specularTextureTransform);\n\
|
||||
#endif\n\
|
||||
float specularWeight = texture(u_specularTexture, specularTexCoords).a;\n\
|
||||
#ifdef HAS_SPECULAR_FACTOR\n\
|
||||
specularWeight *= u_specularFactor;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
#ifdef HAS_SPECULAR_FACTOR\n\
|
||||
float specularWeight = u_specularFactor;\n\
|
||||
#else\n\
|
||||
float specularWeight = 1.0;\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_SPECULAR_COLOR_TEXTURE\n\
|
||||
vec2 specularColorTexCoords = TEXCOORD_SPECULAR_COLOR;\n\
|
||||
#ifdef HAS_SPECULAR_COLOR_TEXTURE_TRANSFORM\n\
|
||||
specularColorTexCoords = czm_computeTextureTransform(specularColorTexCoords, u_specularColorTextureTransform);\n\
|
||||
#endif\n\
|
||||
vec3 specularColorSample = texture(u_specularColorTexture, specularColorTexCoords).rgb;\n\
|
||||
vec3 specularColorFactor = czm_srgbToLinear(specularColorSample);\n\
|
||||
#ifdef HAS_SPECULAR_COLOR_FACTOR\n\
|
||||
specularColorFactor *= u_specularColorFactor;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
#ifdef HAS_SPECULAR_COLOR_FACTOR\n\
|
||||
vec3 specularColorFactor = u_specularColorFactor;\n\
|
||||
#else\n\
|
||||
vec3 specularColorFactor = vec3(1.0);\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
material.specularWeight = specularWeight;\n\
|
||||
vec3 f0 = material.specular;\n\
|
||||
vec3 dielectricSpecularF0 = min(f0 * specularColorFactor, vec3(1.0));\n\
|
||||
material.specular = mix(dielectricSpecularF0, material.baseColor.rgb, metalness);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
#ifdef USE_ANISOTROPY\n\
|
||||
void setAnisotropy(inout czm_modelMaterial material, in NormalInfo normalInfo)\n\
|
||||
{\n\
|
||||
mat2 rotation = mat2(u_anisotropy.xy, -u_anisotropy.y, u_anisotropy.x);\n\
|
||||
float anisotropyStrength = u_anisotropy.z;\n\
|
||||
\n\
|
||||
vec2 direction = vec2(1.0, 0.0);\n\
|
||||
#ifdef HAS_ANISOTROPY_TEXTURE\n\
|
||||
vec2 anisotropyTexCoords = TEXCOORD_ANISOTROPY;\n\
|
||||
#ifdef HAS_ANISOTROPY_TEXTURE_TRANSFORM\n\
|
||||
anisotropyTexCoords = czm_computeTextureTransform(anisotropyTexCoords, u_anisotropyTextureTransform);\n\
|
||||
#endif\n\
|
||||
vec3 anisotropySample = texture(u_anisotropyTexture, anisotropyTexCoords).rgb;\n\
|
||||
direction = anisotropySample.rg * 2.0 - vec2(1.0);\n\
|
||||
anisotropyStrength *= anisotropySample.b;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
direction = rotation * direction;\n\
|
||||
mat3 tbn = mat3(normalInfo.tangent, normalInfo.bitangent, normalInfo.normal);\n\
|
||||
vec3 anisotropicT = tbn * normalize(vec3(direction, 0.0));\n\
|
||||
vec3 anisotropicB = cross(normalInfo.geometryNormal, anisotropicT);\n\
|
||||
\n\
|
||||
material.anisotropicT = anisotropicT;\n\
|
||||
material.anisotropicB = anisotropicB;\n\
|
||||
material.anisotropyStrength = anisotropyStrength;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
#ifdef USE_CLEARCOAT\n\
|
||||
void setClearcoat(inout czm_modelMaterial material, in ProcessedAttributes attributes)\n\
|
||||
{\n\
|
||||
#ifdef HAS_CLEARCOAT_TEXTURE\n\
|
||||
vec2 clearcoatTexCoords = TEXCOORD_CLEARCOAT;\n\
|
||||
#ifdef HAS_CLEARCOAT_TEXTURE_TRANSFORM\n\
|
||||
clearcoatTexCoords = czm_computeTextureTransform(clearcoatTexCoords, u_clearcoatTextureTransform);\n\
|
||||
#endif\n\
|
||||
float clearcoatFactor = texture(u_clearcoatTexture, clearcoatTexCoords).r;\n\
|
||||
#ifdef HAS_CLEARCOAT_FACTOR\n\
|
||||
clearcoatFactor *= u_clearcoatFactor;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
#ifdef HAS_CLEARCOAT_FACTOR\n\
|
||||
float clearcoatFactor = u_clearcoatFactor;\n\
|
||||
#else\n\
|
||||
// PERFORMANCE_IDEA: this case should turn the whole extension off\n\
|
||||
float clearcoatFactor = 0.0;\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE\n\
|
||||
vec2 clearcoatRoughnessTexCoords = TEXCOORD_CLEARCOAT_ROUGHNESS;\n\
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE_TRANSFORM\n\
|
||||
clearcoatRoughnessTexCoords = czm_computeTextureTransform(clearcoatRoughnessTexCoords, u_clearcoatRoughnessTextureTransform);\n\
|
||||
#endif\n\
|
||||
float clearcoatRoughness = texture(u_clearcoatRoughnessTexture, clearcoatRoughnessTexCoords).g;\n\
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR\n\
|
||||
clearcoatRoughness *= u_clearcoatRoughnessFactor;\n\
|
||||
#endif\n\
|
||||
#else\n\
|
||||
#ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR\n\
|
||||
float clearcoatRoughness = u_clearcoatRoughnessFactor;\n\
|
||||
#else\n\
|
||||
float clearcoatRoughness = 0.0;\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
material.clearcoatFactor = clearcoatFactor;\n\
|
||||
// This is perceptual roughness. The square of this value is used for direct lighting\n\
|
||||
material.clearcoatRoughness = clearcoatRoughness;\n\
|
||||
#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE\n\
|
||||
material.clearcoatNormal = getClearcoatNormalFromTexture(attributes, attributes.normalEC);\n\
|
||||
#else\n\
|
||||
material.clearcoatNormal = attributes.normalEC;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
void materialStage(inout czm_modelMaterial material, ProcessedAttributes attributes, SelectedFeature feature)\n\
|
||||
{\n\
|
||||
#ifdef USE_ANISOTROPY\n\
|
||||
NormalInfo normalInfo = getNormalInfo(attributes);\n\
|
||||
material.normalEC = normalInfo.normal;\n\
|
||||
#elif defined(HAS_NORMALS)\n\
|
||||
material.normalEC = computeNormal(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 baseColorWithAlpha = vec4(1.0);\n\
|
||||
// Regardless of whether we use PBR, set a base color.\n\
|
||||
// HAS_BACKGROUND_FILL (from BENTLEY_materials_planar_fill) overrides with\n\
|
||||
// the view's background color to create an invisible masking polygon.\n\
|
||||
// The background color is in sRGB, so convert to linear to match the\n\
|
||||
// material pipeline's expected color space.\n\
|
||||
#ifdef HAS_BACKGROUND_FILL\n\
|
||||
baseColorWithAlpha = czm_srgbToLinear(czm_backgroundColor);\n\
|
||||
#elif defined(HAS_BASE_COLOR_TEXTURE)\n\
|
||||
baseColorWithAlpha = getBaseColorFromTexture();\n\
|
||||
#elif defined(HAS_BASE_COLOR_FACTOR)\n\
|
||||
baseColorWithAlpha = u_baseColorFactor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_IMAGERY\n\
|
||||
baseColorWithAlpha = blendBaseColorWithImagery(baseColorWithAlpha);\n\
|
||||
#endif // HAS_IMAGERY\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE\n\
|
||||
baseColorWithAlpha = v_pointCloudColor;\n\
|
||||
#elif defined(HAS_COLOR_0)\n\
|
||||
vec4 color = attributes.color_0;\n\
|
||||
// .pnts files store colors in the sRGB color space\n\
|
||||
#ifdef HAS_SRGB_COLOR\n\
|
||||
color = czm_srgbToLinear(color);\n\
|
||||
#endif\n\
|
||||
baseColorWithAlpha *= color;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_CPU_STYLING\n\
|
||||
baseColorWithAlpha.rgb = blend(baseColorWithAlpha.rgb, feature.color.rgb, model_colorBlend);\n\
|
||||
#endif\n\
|
||||
material.baseColor = baseColorWithAlpha;\n\
|
||||
material.diffuse = baseColorWithAlpha.rgb;\n\
|
||||
material.alpha = baseColorWithAlpha.a;\n\
|
||||
\n\
|
||||
#ifdef HAS_OCCLUSION_TEXTURE\n\
|
||||
vec2 occlusionTexCoords = TEXCOORD_OCCLUSION;\n\
|
||||
#ifdef HAS_OCCLUSION_TEXTURE_TRANSFORM\n\
|
||||
occlusionTexCoords = czm_computeTextureTransform(occlusionTexCoords, u_occlusionTextureTransform);\n\
|
||||
#endif\n\
|
||||
material.occlusion = texture(u_occlusionTexture, occlusionTexCoords).r;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_EMISSIVE_TEXTURE\n\
|
||||
material.emissive = getEmissiveFromTexture();\n\
|
||||
#elif defined(HAS_EMISSIVE_FACTOR)\n\
|
||||
material.emissive = u_emissiveFactor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)\n\
|
||||
setSpecularGlossiness(material);\n\
|
||||
#elif defined(LIGHTING_PBR)\n\
|
||||
float metalness = setMetallicRoughness(material);\n\
|
||||
#ifdef USE_SPECULAR\n\
|
||||
setSpecular(material, metalness);\n\
|
||||
#endif\n\
|
||||
#ifdef USE_ANISOTROPY\n\
|
||||
setAnisotropy(material, normalInfo);\n\
|
||||
#endif\n\
|
||||
#ifdef USE_CLEARCOAT\n\
|
||||
setClearcoat(material, attributes);\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
void metadataStage(
|
||||
FeatureIds featureIds,
|
||||
out Metadata metadata,
|
||||
out MetadataClass metadataClass,
|
||||
out MetadataStatistics metadataStatistics,
|
||||
ProcessedAttributes attributes
|
||||
)
|
||||
{
|
||||
initializeMetadata(featureIds, metadata, metadataClass, metadataStatistics, attributes);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void metadataStage(\n\
|
||||
FeatureIds featureIds,\n\
|
||||
out Metadata metadata,\n\
|
||||
out MetadataClass metadataClass,\n\
|
||||
out MetadataStatistics metadataStatistics,\n\
|
||||
ProcessedAttributes attributes\n\
|
||||
)\n\
|
||||
{\n\
|
||||
initializeMetadata(featureIds, metadata, metadataClass, metadataStatistics, attributes);\n\
|
||||
}\n\
|
||||
";
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
void metadataStage(
|
||||
FeatureIds featureIds,
|
||||
out Metadata metadata,
|
||||
out MetadataClass metadataClass,
|
||||
out MetadataStatistics metadataStatistics,
|
||||
ProcessedAttributes attributes
|
||||
)
|
||||
{
|
||||
initializeMetadata(featureIds, metadata, metadataClass, metadataStatistics, attributes);
|
||||
setMetadataVaryings();
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void metadataStage(\n\
|
||||
FeatureIds featureIds,\n\
|
||||
out Metadata metadata,\n\
|
||||
out MetadataClass metadataClass,\n\
|
||||
out MetadataStatistics metadataStatistics,\n\
|
||||
ProcessedAttributes attributes\n\
|
||||
)\n\
|
||||
{\n\
|
||||
initializeMetadata(featureIds, metadata, metadataClass, metadataStatistics, attributes);\n\
|
||||
setMetadataVaryings();\n\
|
||||
}\n\
|
||||
";
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
#ifdef USE_CLIPPING_PLANES_FLOAT_TEXTURE
|
||||
vec4 getClippingPlane(
|
||||
highp sampler2D packedClippingPlanes,
|
||||
int clippingPlaneNumber,
|
||||
mat4 transform
|
||||
) {
|
||||
int pixY = clippingPlaneNumber / CLIPPING_PLANES_TEXTURE_WIDTH;
|
||||
int pixX = clippingPlaneNumber - (pixY * CLIPPING_PLANES_TEXTURE_WIDTH);
|
||||
float pixelWidth = 1.0 / float(CLIPPING_PLANES_TEXTURE_WIDTH);
|
||||
float pixelHeight = 1.0 / float(CLIPPING_PLANES_TEXTURE_HEIGHT);
|
||||
float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel
|
||||
float v = (float(pixY) + 0.5) * pixelHeight;
|
||||
vec4 plane = texture(packedClippingPlanes, vec2(u, v));
|
||||
return czm_transformPlane(plane, transform);
|
||||
}
|
||||
#else
|
||||
// Handle uint8 clipping texture instead
|
||||
vec4 getClippingPlane(
|
||||
highp sampler2D packedClippingPlanes,
|
||||
int clippingPlaneNumber,
|
||||
mat4 transform
|
||||
) {
|
||||
int clippingPlaneStartIndex = clippingPlaneNumber * 2; // clipping planes are two pixels each
|
||||
int pixY = clippingPlaneStartIndex / CLIPPING_PLANES_TEXTURE_WIDTH;
|
||||
int pixX = clippingPlaneStartIndex - (pixY * CLIPPING_PLANES_TEXTURE_WIDTH);
|
||||
float pixelWidth = 1.0 / float(CLIPPING_PLANES_TEXTURE_WIDTH);
|
||||
float pixelHeight = 1.0 / float(CLIPPING_PLANES_TEXTURE_HEIGHT);
|
||||
float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel
|
||||
float v = (float(pixY) + 0.5) * pixelHeight;
|
||||
vec4 oct32 = texture(packedClippingPlanes, vec2(u, v)) * 255.0;
|
||||
vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);
|
||||
vec4 plane;
|
||||
plane.xyz = czm_octDecode(oct, 65535.0);
|
||||
plane.w = czm_unpackFloat(texture(packedClippingPlanes, vec2(u + pixelWidth, v)));
|
||||
return czm_transformPlane(plane, transform);
|
||||
}
|
||||
#endif
|
||||
|
||||
float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix) {
|
||||
vec4 position = czm_windowToEyeCoordinates(fragCoord);
|
||||
vec3 clipNormal = vec3(0.0);
|
||||
vec3 clipPosition = vec3(0.0);
|
||||
float pixelWidth = czm_metersPerPixel(position);
|
||||
|
||||
#ifdef UNION_CLIPPING_REGIONS
|
||||
float clipAmount; // For union planes, we want to get the min distance. So we set the initial value to the first plane distance in the loop below.
|
||||
#else
|
||||
float clipAmount = 0.0;
|
||||
bool clipped = true;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < CLIPPING_PLANES_LENGTH; ++i) {
|
||||
vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);
|
||||
clipNormal = clippingPlane.xyz;
|
||||
clipPosition = -clippingPlane.w * clipNormal;
|
||||
float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;
|
||||
|
||||
#ifdef UNION_CLIPPING_REGIONS
|
||||
clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));
|
||||
if (amount <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
#else
|
||||
clipAmount = max(amount, clipAmount);
|
||||
clipped = clipped && (amount <= 0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef UNION_CLIPPING_REGIONS
|
||||
if (clipped) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
return clipAmount;
|
||||
}
|
||||
|
||||
void modelClippingPlanesStage(inout vec4 color)
|
||||
{
|
||||
float clipDistance = clip(gl_FragCoord, model_clippingPlanes, model_clippingPlanesMatrix);
|
||||
vec4 clippingPlanesEdgeColor = vec4(1.0);
|
||||
clippingPlanesEdgeColor.rgb = model_clippingPlanesEdgeStyle.rgb;
|
||||
float clippingPlanesEdgeWidth = model_clippingPlanesEdgeStyle.a;
|
||||
|
||||
if (clipDistance > 0.0 && clipDistance < clippingPlanesEdgeWidth) {
|
||||
color = clippingPlanesEdgeColor;
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "#ifdef USE_CLIPPING_PLANES_FLOAT_TEXTURE\n\
|
||||
vec4 getClippingPlane(\n\
|
||||
highp sampler2D packedClippingPlanes,\n\
|
||||
int clippingPlaneNumber,\n\
|
||||
mat4 transform\n\
|
||||
) {\n\
|
||||
int pixY = clippingPlaneNumber / CLIPPING_PLANES_TEXTURE_WIDTH;\n\
|
||||
int pixX = clippingPlaneNumber - (pixY * CLIPPING_PLANES_TEXTURE_WIDTH);\n\
|
||||
float pixelWidth = 1.0 / float(CLIPPING_PLANES_TEXTURE_WIDTH);\n\
|
||||
float pixelHeight = 1.0 / float(CLIPPING_PLANES_TEXTURE_HEIGHT);\n\
|
||||
float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel\n\
|
||||
float v = (float(pixY) + 0.5) * pixelHeight;\n\
|
||||
vec4 plane = texture(packedClippingPlanes, vec2(u, v));\n\
|
||||
return czm_transformPlane(plane, transform);\n\
|
||||
}\n\
|
||||
#else\n\
|
||||
// Handle uint8 clipping texture instead\n\
|
||||
vec4 getClippingPlane(\n\
|
||||
highp sampler2D packedClippingPlanes,\n\
|
||||
int clippingPlaneNumber,\n\
|
||||
mat4 transform\n\
|
||||
) {\n\
|
||||
int clippingPlaneStartIndex = clippingPlaneNumber * 2; // clipping planes are two pixels each\n\
|
||||
int pixY = clippingPlaneStartIndex / CLIPPING_PLANES_TEXTURE_WIDTH;\n\
|
||||
int pixX = clippingPlaneStartIndex - (pixY * CLIPPING_PLANES_TEXTURE_WIDTH);\n\
|
||||
float pixelWidth = 1.0 / float(CLIPPING_PLANES_TEXTURE_WIDTH);\n\
|
||||
float pixelHeight = 1.0 / float(CLIPPING_PLANES_TEXTURE_HEIGHT);\n\
|
||||
float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel\n\
|
||||
float v = (float(pixY) + 0.5) * pixelHeight;\n\
|
||||
vec4 oct32 = texture(packedClippingPlanes, vec2(u, v)) * 255.0;\n\
|
||||
vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);\n\
|
||||
vec4 plane;\n\
|
||||
plane.xyz = czm_octDecode(oct, 65535.0);\n\
|
||||
plane.w = czm_unpackFloat(texture(packedClippingPlanes, vec2(u + pixelWidth, v)));\n\
|
||||
return czm_transformPlane(plane, transform);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix) {\n\
|
||||
vec4 position = czm_windowToEyeCoordinates(fragCoord);\n\
|
||||
vec3 clipNormal = vec3(0.0);\n\
|
||||
vec3 clipPosition = vec3(0.0);\n\
|
||||
float pixelWidth = czm_metersPerPixel(position);\n\
|
||||
\n\
|
||||
#ifdef UNION_CLIPPING_REGIONS\n\
|
||||
float clipAmount; // For union planes, we want to get the min distance. So we set the initial value to the first plane distance in the loop below.\n\
|
||||
#else\n\
|
||||
float clipAmount = 0.0;\n\
|
||||
bool clipped = true;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
for (int i = 0; i < CLIPPING_PLANES_LENGTH; ++i) {\n\
|
||||
vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n\
|
||||
clipNormal = clippingPlane.xyz;\n\
|
||||
clipPosition = -clippingPlane.w * clipNormal;\n\
|
||||
float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n\
|
||||
\n\
|
||||
#ifdef UNION_CLIPPING_REGIONS\n\
|
||||
clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));\n\
|
||||
if (amount <= 0.0) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#else\n\
|
||||
clipAmount = max(amount, clipAmount);\n\
|
||||
clipped = clipped && (amount <= 0.0);\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
\n\
|
||||
#ifndef UNION_CLIPPING_REGIONS\n\
|
||||
if (clipped) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return clipAmount;\n\
|
||||
}\n\
|
||||
\n\
|
||||
void modelClippingPlanesStage(inout vec4 color)\n\
|
||||
{\n\
|
||||
float clipDistance = clip(gl_FragCoord, model_clippingPlanes, model_clippingPlanesMatrix);\n\
|
||||
vec4 clippingPlanesEdgeColor = vec4(1.0);\n\
|
||||
clippingPlanesEdgeColor.rgb = model_clippingPlanesEdgeStyle.rgb;\n\
|
||||
float clippingPlanesEdgeWidth = model_clippingPlanesEdgeStyle.a;\n\
|
||||
\n\
|
||||
if (clipDistance > 0.0 && clipDistance < clippingPlanesEdgeWidth) {\n\
|
||||
color = clippingPlanesEdgeColor;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
";
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
void modelClippingPolygonsStage()
|
||||
{
|
||||
vec2 clippingPosition = v_clippingPosition;
|
||||
int regionIndex = v_regionIndex;
|
||||
czm_clipPolygons(model_clippingDistance, CLIPPING_POLYGON_REGIONS_LENGTH, clippingPosition, regionIndex);
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void modelClippingPolygonsStage()\n\
|
||||
{\n\
|
||||
vec2 clippingPosition = v_clippingPosition;\n\
|
||||
int regionIndex = v_regionIndex;\n\
|
||||
czm_clipPolygons(model_clippingDistance, CLIPPING_POLYGON_REGIONS_LENGTH, clippingPosition, regionIndex);\n\
|
||||
}\n\
|
||||
";
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
void modelClippingPolygonsStage(ProcessedAttributes attributes)
|
||||
{
|
||||
vec2 sphericalLatLong = czm_approximateSphericalCoordinates(v_positionWC);
|
||||
sphericalLatLong.y = czm_branchFreeTernary(sphericalLatLong.y < czm_pi, sphericalLatLong.y, sphericalLatLong.y - czm_twoPi);
|
||||
|
||||
vec2 minDistance = vec2(czm_infinity);
|
||||
v_regionIndex = -1;
|
||||
v_clippingPosition = vec2(czm_infinity);
|
||||
|
||||
for (int regionIndex = 0; regionIndex < CLIPPING_POLYGON_REGIONS_LENGTH; regionIndex++) {
|
||||
vec4 extents = czm_unpackClippingExtents(model_clippingExtents, regionIndex);
|
||||
vec2 rectUv = (sphericalLatLong.yx - extents.yx) * extents.wz;
|
||||
|
||||
vec2 clamped = clamp(rectUv, vec2(0.0), vec2(1.0));
|
||||
vec2 distance = abs(rectUv - clamped) * extents.wz;
|
||||
|
||||
if (minDistance.x > distance.x || minDistance.y > distance.y) {
|
||||
minDistance = distance;
|
||||
v_clippingPosition = rectUv;
|
||||
}
|
||||
|
||||
float threshold = 0.01;
|
||||
if (rectUv.x > threshold && rectUv.y > threshold && rectUv.x < 1.0 - threshold && rectUv.y < 1.0 - threshold) {
|
||||
v_regionIndex = regionIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void modelClippingPolygonsStage(ProcessedAttributes attributes)\n\
|
||||
{\n\
|
||||
vec2 sphericalLatLong = czm_approximateSphericalCoordinates(v_positionWC);\n\
|
||||
sphericalLatLong.y = czm_branchFreeTernary(sphericalLatLong.y < czm_pi, sphericalLatLong.y, sphericalLatLong.y - czm_twoPi);\n\
|
||||
\n\
|
||||
vec2 minDistance = vec2(czm_infinity);\n\
|
||||
v_regionIndex = -1;\n\
|
||||
v_clippingPosition = vec2(czm_infinity);\n\
|
||||
\n\
|
||||
for (int regionIndex = 0; regionIndex < CLIPPING_POLYGON_REGIONS_LENGTH; regionIndex++) {\n\
|
||||
vec4 extents = czm_unpackClippingExtents(model_clippingExtents, regionIndex);\n\
|
||||
vec2 rectUv = (sphericalLatLong.yx - extents.yx) * extents.wz;\n\
|
||||
\n\
|
||||
vec2 clamped = clamp(rectUv, vec2(0.0), vec2(1.0));\n\
|
||||
vec2 distance = abs(rectUv - clamped) * extents.wz;\n\
|
||||
\n\
|
||||
if (minDistance.x > distance.x || minDistance.y > distance.y) {\n\
|
||||
minDistance = distance;\n\
|
||||
v_clippingPosition = rectUv;\n\
|
||||
}\n\
|
||||
\n\
|
||||
float threshold = 0.01;\n\
|
||||
if (rectUv.x > threshold && rectUv.y > threshold && rectUv.x < 1.0 - threshold && rectUv.y < 1.0 - threshold) {\n\
|
||||
v_regionIndex = regionIndex;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
}\n\
|
||||
";
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
void modelColorStage(inout czm_modelMaterial material)
|
||||
{
|
||||
material.diffuse = mix(material.diffuse, model_color.rgb, model_colorBlend);
|
||||
float highlight = ceil(model_colorBlend);
|
||||
material.diffuse *= mix(model_color.rgb, vec3(1.0), highlight);
|
||||
material.alpha *= model_color.a;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void modelColorStage(inout czm_modelMaterial material)\n\
|
||||
{\n\
|
||||
material.diffuse = mix(material.diffuse, model_color.rgb, model_colorBlend);\n\
|
||||
float highlight = ceil(model_colorBlend);\n\
|
||||
material.diffuse *= mix(model_color.rgb, vec3(1.0), highlight);\n\
|
||||
material.alpha *= model_color.a;\n\
|
||||
}\n\
|
||||
";
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
|
||||
precision highp float;
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// BENTLEY_materials_planar_fill constants
|
||||
//
|
||||
// These factors scale gl_FragDepth AFTER czm_writeLogDepth has run, so
|
||||
// they are proportional offsets in log-depth space. The corresponding
|
||||
// eye-space offset therefore varies with the fragment's distance from
|
||||
// the camera (growing with distance). This is the intended behavior: it
|
||||
// matches the proportional depth comparison tolerance used by the edge
|
||||
// visibility system, so fills and edges stay consistently ordered at all
|
||||
// viewing distances.
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// Depth pull factor for all planar fills: scales log depth by 0.9995,
|
||||
// i.e. a 0.05% pull toward the camera in log-depth space.
|
||||
const float PLANAR_DEPTH_PULL = 0.9995;
|
||||
// Depth push factor for behind fills: scales log depth by 1.0002, i.e. a
|
||||
// 0.02% push away from the camera in log-depth space, so behind fills sit
|
||||
// behind same-object siblings.
|
||||
const float BEHIND_DEPTH_PUSH = 1.0002;
|
||||
// Tolerance for comparing feature IDs stored as floats (integer equality).
|
||||
const float FEATURE_ID_TOLERANCE = 0.5;
|
||||
// Offset added to feature IDs so 0 means "no planar fill" in the texture.
|
||||
const float FEATURE_ID_OFFSET = 1.0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void lineStyleStage()
|
||||
{
|
||||
#if defined(HAS_LINE_PATTERN) && !defined(HAS_EDGE_VISIBILITY)
|
||||
const float maskLength = 16.0;
|
||||
float dashPosition = fract(v_lineCoord / maskLength);
|
||||
float maskIndex = floor(dashPosition * maskLength);
|
||||
float maskTest = floor(u_linePattern / pow(2.0, maskIndex));
|
||||
if (mod(maskTest, 2.0) < 1.0) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SelectedFeature selectedFeature;
|
||||
|
||||
// Set by edge-pass fragments below; consumed by the snapId expression built
|
||||
// in PickingPipelineStage (see Scene#snap).
|
||||
bool isEdge = false;
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(PRIMITIVE_TYPE_POINTS) && defined(HAS_POINT_DIAMETER)
|
||||
// Render points as circles
|
||||
float distanceToCenter = length(gl_PointCoord - vec2(0.5));
|
||||
if (distanceToCenter > 0.5) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE
|
||||
if (v_pointCloudShow == 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_MODEL_SPLITTER
|
||||
modelSplitterStage();
|
||||
#endif
|
||||
|
||||
czm_modelMaterial material = defaultModelMaterial();
|
||||
|
||||
ProcessedAttributes attributes;
|
||||
geometryStage(attributes);
|
||||
|
||||
FeatureIds featureIds;
|
||||
featureIdStage(featureIds, attributes);
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// BENTLEY_materials_planar_fill: Feature-ID pre-pass output.
|
||||
//
|
||||
// When HAS_PLANAR_FILL_ID_PASS is defined this command is being rendered
|
||||
// into the planar fill ID framebuffer. Non-behind planar geometry writes
|
||||
// its feature ID + 1 into the R channel (0 = no feature) and returns.
|
||||
// No material / lighting / post-process stages are needed.
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
#ifdef HAS_PLANAR_FILL_ID_PASS
|
||||
if (u_isPlanarFillIdPass) {
|
||||
float fid = float(featureIds.PLANAR_FILL_FEATURE_ID) + FEATURE_ID_OFFSET;
|
||||
out_FragColor = vec4(fid, 0.0, 0.0, 1.0);
|
||||
// Still need to write log depth so the depth buffer is correct.
|
||||
#ifdef LOG_DEPTH
|
||||
czm_writeLogDepth();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Metadata metadata;
|
||||
MetadataClass metadataClass;
|
||||
MetadataStatistics metadataStatistics;
|
||||
metadataStage(featureIds, metadata, metadataClass, metadataStatistics, attributes);
|
||||
|
||||
//========================================================================
|
||||
// When not picking metadata START
|
||||
#ifndef METADATA_PICKING_ENABLED
|
||||
|
||||
#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);
|
||||
|
||||
// When not picking metadata END
|
||||
//========================================================================
|
||||
#else
|
||||
//========================================================================
|
||||
// When picking metadata START
|
||||
|
||||
vec4 metadataValues = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
metadataPickingStage(metadata, metadataClass, metadataValues);
|
||||
vec4 color = metadataValues;
|
||||
|
||||
#endif
|
||||
// When picking metadata END
|
||||
//========================================================================
|
||||
|
||||
lineStyleStage();
|
||||
|
||||
#ifdef HAS_CLIPPING_PLANES
|
||||
modelClippingPlanesStage(color);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLIPPING_POLYGONS
|
||||
modelClippingPolygonsStage();
|
||||
#endif
|
||||
|
||||
//========================================================================
|
||||
// When not picking metadata START
|
||||
#ifndef METADATA_PICKING_ENABLED
|
||||
|
||||
#if defined(HAS_SILHOUETTE) && defined(HAS_NORMALS)
|
||||
silhouetteStage(color);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_ATMOSPHERE
|
||||
atmosphereStage(color, attributes);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EDGE_VISIBILITY
|
||||
edgeVisibilityStage(color, featureIds);
|
||||
edgeDetectionStage(color, featureIds);
|
||||
// Edge-pass fragments rasterize the edge band itself. Flag them so the
|
||||
// snap payload (see Scene#snap) can distinguish edges from surfaces;
|
||||
// surface fragments leave isEdge false.
|
||||
if (u_isEdgePass) {
|
||||
isEdge = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
// When not picking metadata END
|
||||
//========================================================================
|
||||
|
||||
out_FragColor = color;
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// Explicit log-depth write.
|
||||
//
|
||||
// DerivedCommand.getLogDepthShaderProgram auto-wraps only when the raw
|
||||
// source does NOT already mention czm_writeLogDepth. We mention it
|
||||
// above in the HAS_PLANAR_FILL_ID_PASS block, so we must also handle
|
||||
// the normal code path ourselves. The LOG_DEPTH define is injected by
|
||||
// that same auto-wrapper, so this block is active exactly when needed.
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
#ifdef LOG_DEPTH
|
||||
czm_writeLogDepth();
|
||||
#endif
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// BENTLEY_materials_planar_fill: Proportional depth adjustment.
|
||||
//
|
||||
// Per the spec, planar primitives must render in front of non-planar
|
||||
// geometry. We use proportional depth scaling (similar to edge visibility)
|
||||
// which scales naturally with logarithmic depth at all viewing distances.
|
||||
//
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
#ifdef HAS_PLANAR_FILL_DEPTH
|
||||
gl_FragDepth *= PLANAR_DEPTH_PULL;
|
||||
#endif
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// BENTLEY_materials_planar_fill: Behind fill depth adjustment.
|
||||
//
|
||||
// After the proportional depth pull has been applied, sample the planar
|
||||
// fill ID texture. If the pixel already belongs to the same feature,
|
||||
// apply a small proportional push so this "behind" fill sits behind its
|
||||
// non-behind sibling. If the pixel has no stored feature, the base pull
|
||||
// still keeps us in front of non-planar geometry.
|
||||
//
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
#ifdef HAS_PLANAR_FILL_BEHIND
|
||||
{
|
||||
vec2 screenCoord = gl_FragCoord.xy / czm_viewport.zw;
|
||||
float storedEncoded = texture(czm_planarFillIdTexture, screenCoord).r;
|
||||
float storedFeatureId = storedEncoded - FEATURE_ID_OFFSET;
|
||||
float myFeatureId = float(featureIds.PLANAR_FILL_FEATURE_ID);
|
||||
|
||||
// storedFeatureId < 0 means "no planar fill at this pixel".
|
||||
if (storedFeatureId >= 0.0 && abs(storedFeatureId - myFeatureId) < FEATURE_ID_TOLERANCE) {
|
||||
// Proportional push: multiply by >1 to move away from camera.
|
||||
// Net effect: PLANAR_DEPTH_PULL * BEHIND_DEPTH_PUSH ≈ 0.9997,
|
||||
// still in front of non-planar but behind same-feature non-behind fills.
|
||||
gl_FragDepth *= BEHIND_DEPTH_PUSH;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "\n\
|
||||
precision highp float;\n\
|
||||
\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
// BENTLEY_materials_planar_fill constants\n\
|
||||
//\n\
|
||||
// These factors scale gl_FragDepth AFTER czm_writeLogDepth has run, so\n\
|
||||
// they are proportional offsets in log-depth space. The corresponding\n\
|
||||
// eye-space offset therefore varies with the fragment's distance from\n\
|
||||
// the camera (growing with distance). This is the intended behavior: it\n\
|
||||
// matches the proportional depth comparison tolerance used by the edge\n\
|
||||
// visibility system, so fills and edges stay consistently ordered at all\n\
|
||||
// viewing distances.\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
// Depth pull factor for all planar fills: scales log depth by 0.9995,\n\
|
||||
// i.e. a 0.05% pull toward the camera in log-depth space.\n\
|
||||
const float PLANAR_DEPTH_PULL = 0.9995;\n\
|
||||
// Depth push factor for behind fills: scales log depth by 1.0002, i.e. a\n\
|
||||
// 0.02% push away from the camera in log-depth space, so behind fills sit\n\
|
||||
// behind same-object siblings.\n\
|
||||
const float BEHIND_DEPTH_PUSH = 1.0002;\n\
|
||||
// Tolerance for comparing feature IDs stored as floats (integer equality).\n\
|
||||
const float FEATURE_ID_TOLERANCE = 0.5;\n\
|
||||
// Offset added to feature IDs so 0 means \"no planar fill\" in the texture.\n\
|
||||
const float FEATURE_ID_OFFSET = 1.0;\n\
|
||||
\n\
|
||||
czm_modelMaterial defaultModelMaterial()\n\
|
||||
{\n\
|
||||
czm_modelMaterial material;\n\
|
||||
material.diffuse = vec3(0.0);\n\
|
||||
material.specular = vec3(1.0);\n\
|
||||
material.roughness = 1.0;\n\
|
||||
material.occlusion = 1.0;\n\
|
||||
material.normalEC = vec3(0.0, 0.0, 1.0);\n\
|
||||
material.emissive = vec3(0.0);\n\
|
||||
material.alpha = 1.0;\n\
|
||||
return material;\n\
|
||||
}\n\
|
||||
\n\
|
||||
vec4 handleAlpha(vec3 color, float alpha)\n\
|
||||
{\n\
|
||||
#ifdef ALPHA_MODE_MASK\n\
|
||||
if (alpha < u_alphaCutoff) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
return vec4(color, alpha);\n\
|
||||
}\n\
|
||||
\n\
|
||||
void lineStyleStage()\n\
|
||||
{\n\
|
||||
#if defined(HAS_LINE_PATTERN) && !defined(HAS_EDGE_VISIBILITY)\n\
|
||||
const float maskLength = 16.0;\n\
|
||||
float dashPosition = fract(v_lineCoord / maskLength);\n\
|
||||
float maskIndex = floor(dashPosition * maskLength);\n\
|
||||
float maskTest = floor(u_linePattern / pow(2.0, maskIndex));\n\
|
||||
if (mod(maskTest, 2.0) < 1.0) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
\n\
|
||||
SelectedFeature selectedFeature;\n\
|
||||
\n\
|
||||
// Set by edge-pass fragments below; consumed by the snapId expression built\n\
|
||||
// in PickingPipelineStage (see Scene#snap).\n\
|
||||
bool isEdge = false;\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if defined(PRIMITIVE_TYPE_POINTS) && defined(HAS_POINT_DIAMETER)\n\
|
||||
// Render points as circles\n\
|
||||
float distanceToCenter = length(gl_PointCoord - vec2(0.5));\n\
|
||||
if (distanceToCenter > 0.5) {\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE\n\
|
||||
if (v_pointCloudShow == 0.0)\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_MODEL_SPLITTER\n\
|
||||
modelSplitterStage();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
czm_modelMaterial material = defaultModelMaterial();\n\
|
||||
\n\
|
||||
ProcessedAttributes attributes;\n\
|
||||
geometryStage(attributes);\n\
|
||||
\n\
|
||||
FeatureIds featureIds;\n\
|
||||
featureIdStage(featureIds, attributes);\n\
|
||||
\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
// BENTLEY_materials_planar_fill: Feature-ID pre-pass output.\n\
|
||||
//\n\
|
||||
// When HAS_PLANAR_FILL_ID_PASS is defined this command is being rendered\n\
|
||||
// into the planar fill ID framebuffer. Non-behind planar geometry writes\n\
|
||||
// its feature ID + 1 into the R channel (0 = no feature) and returns.\n\
|
||||
// No material / lighting / post-process stages are needed.\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
#ifdef HAS_PLANAR_FILL_ID_PASS\n\
|
||||
if (u_isPlanarFillIdPass) {\n\
|
||||
float fid = float(featureIds.PLANAR_FILL_FEATURE_ID) + FEATURE_ID_OFFSET;\n\
|
||||
out_FragColor = vec4(fid, 0.0, 0.0, 1.0);\n\
|
||||
// Still need to write log depth so the depth buffer is correct.\n\
|
||||
#ifdef LOG_DEPTH\n\
|
||||
czm_writeLogDepth();\n\
|
||||
#endif\n\
|
||||
return;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
Metadata metadata;\n\
|
||||
MetadataClass metadataClass;\n\
|
||||
MetadataStatistics metadataStatistics;\n\
|
||||
metadataStage(featureIds, metadata, metadataClass, metadataStatistics, attributes);\n\
|
||||
\n\
|
||||
//========================================================================\n\
|
||||
// When not picking metadata START\n\
|
||||
#ifndef METADATA_PICKING_ENABLED\n\
|
||||
\n\
|
||||
#ifdef HAS_SELECTED_FEATURE_ID\n\
|
||||
selectedFeatureIdStage(selectedFeature, featureIds);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifndef CUSTOM_SHADER_REPLACE_MATERIAL\n\
|
||||
materialStage(material, attributes, selectedFeature);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_CUSTOM_FRAGMENT_SHADER\n\
|
||||
customShaderStage(material, attributes, featureIds, metadata, metadataClass, metadataStatistics);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
lightingStage(material, attributes);\n\
|
||||
\n\
|
||||
#ifdef HAS_SELECTED_FEATURE_ID\n\
|
||||
cpuStylingStage(material, selectedFeature);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_MODEL_COLOR\n\
|
||||
modelColorStage(material);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_PRIMITIVE_OUTLINE\n\
|
||||
primitiveOutlineStage(material);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 color = handleAlpha(material.diffuse, material.alpha);\n\
|
||||
\n\
|
||||
// When not picking metadata END\n\
|
||||
//========================================================================\n\
|
||||
#else\n\
|
||||
//========================================================================\n\
|
||||
// When picking metadata START\n\
|
||||
\n\
|
||||
vec4 metadataValues = vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
metadataPickingStage(metadata, metadataClass, metadataValues);\n\
|
||||
vec4 color = metadataValues;\n\
|
||||
\n\
|
||||
#endif\n\
|
||||
// When picking metadata END\n\
|
||||
//========================================================================\n\
|
||||
\n\
|
||||
lineStyleStage();\n\
|
||||
\n\
|
||||
#ifdef HAS_CLIPPING_PLANES\n\
|
||||
modelClippingPlanesStage(color);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef ENABLE_CLIPPING_POLYGONS\n\
|
||||
modelClippingPolygonsStage();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
//========================================================================\n\
|
||||
// When not picking metadata START\n\
|
||||
#ifndef METADATA_PICKING_ENABLED\n\
|
||||
\n\
|
||||
#if defined(HAS_SILHOUETTE) && defined(HAS_NORMALS)\n\
|
||||
silhouetteStage(color);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_ATMOSPHERE\n\
|
||||
atmosphereStage(color, attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_EDGE_VISIBILITY\n\
|
||||
edgeVisibilityStage(color, featureIds);\n\
|
||||
edgeDetectionStage(color, featureIds);\n\
|
||||
// Edge-pass fragments rasterize the edge band itself. Flag them so the\n\
|
||||
// snap payload (see Scene#snap) can distinguish edges from surfaces;\n\
|
||||
// surface fragments leave isEdge false.\n\
|
||||
if (u_isEdgePass) {\n\
|
||||
isEdge = true;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#endif\n\
|
||||
// When not picking metadata END\n\
|
||||
//========================================================================\n\
|
||||
\n\
|
||||
out_FragColor = color;\n\
|
||||
\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
// Explicit log-depth write.\n\
|
||||
//\n\
|
||||
// DerivedCommand.getLogDepthShaderProgram auto-wraps only when the raw\n\
|
||||
// source does NOT already mention czm_writeLogDepth. We mention it\n\
|
||||
// above in the HAS_PLANAR_FILL_ID_PASS block, so we must also handle\n\
|
||||
// the normal code path ourselves. The LOG_DEPTH define is injected by\n\
|
||||
// that same auto-wrapper, so this block is active exactly when needed.\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
#ifdef LOG_DEPTH\n\
|
||||
czm_writeLogDepth();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
// BENTLEY_materials_planar_fill: Proportional depth adjustment.\n\
|
||||
//\n\
|
||||
// Per the spec, planar primitives must render in front of non-planar\n\
|
||||
// geometry. We use proportional depth scaling (similar to edge visibility)\n\
|
||||
// which scales naturally with logarithmic depth at all viewing distances.\n\
|
||||
//\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
#ifdef HAS_PLANAR_FILL_DEPTH\n\
|
||||
gl_FragDepth *= PLANAR_DEPTH_PULL;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
// BENTLEY_materials_planar_fill: Behind fill depth adjustment.\n\
|
||||
//\n\
|
||||
// After the proportional depth pull has been applied, sample the planar\n\
|
||||
// fill ID texture. If the pixel already belongs to the same feature,\n\
|
||||
// apply a small proportional push so this \"behind\" fill sits behind its\n\
|
||||
// non-behind sibling. If the pixel has no stored feature, the base pull\n\
|
||||
// still keeps us in front of non-planar geometry.\n\
|
||||
//\n\
|
||||
// ──────────────────────────────────────────────────────────────────────\n\
|
||||
#ifdef HAS_PLANAR_FILL_BEHIND\n\
|
||||
{\n\
|
||||
vec2 screenCoord = gl_FragCoord.xy / czm_viewport.zw;\n\
|
||||
float storedEncoded = texture(czm_planarFillIdTexture, screenCoord).r;\n\
|
||||
float storedFeatureId = storedEncoded - FEATURE_ID_OFFSET;\n\
|
||||
float myFeatureId = float(featureIds.PLANAR_FILL_FEATURE_ID);\n\
|
||||
\n\
|
||||
// storedFeatureId < 0 means \"no planar fill at this pixel\".\n\
|
||||
if (storedFeatureId >= 0.0 && abs(storedFeatureId - myFeatureId) < FEATURE_ID_TOLERANCE) {\n\
|
||||
// Proportional push: multiply by >1 to move away from camera.\n\
|
||||
// Net effect: PLANAR_DEPTH_PULL * BEHIND_DEPTH_PUSH ≈ 0.9997,\n\
|
||||
// still in front of non-planar but behind same-feature non-behind fills.\n\
|
||||
gl_FragDepth *= BEHIND_DEPTH_PUSH;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
\n\
|
||||
";
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
void silhouetteStage(inout vec4 color) {
|
||||
if(model_silhouettePass) {
|
||||
color = czm_gammaCorrect(model_silhouetteColor);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void silhouetteStage(inout vec4 color) {\n\
|
||||
if(model_silhouettePass) {\n\
|
||||
color = czm_gammaCorrect(model_silhouetteColor);\n\
|
||||
}\n\
|
||||
}";
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
void silhouetteStage(in ProcessedAttributes attributes, inout vec4 positionClip) {
|
||||
#ifdef HAS_NORMALS
|
||||
if(model_silhouettePass) {
|
||||
vec3 normal = normalize(czm_normal3D * attributes.normalMC);
|
||||
normal.x *= czm_projection[0][0];
|
||||
normal.y *= czm_projection[1][1];
|
||||
positionClip.xy += normal.xy * positionClip.w * model_silhouetteSize * czm_pixelRatio / czm_viewport.z;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void silhouetteStage(in ProcessedAttributes attributes, inout vec4 positionClip) {\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
if(model_silhouettePass) {\n\
|
||||
vec3 normal = normalize(czm_normal3D * attributes.normalMC);\n\
|
||||
normal.x *= czm_projection[0][0];\n\
|
||||
normal.y *= czm_projection[1][1];\n\
|
||||
positionClip.xy += normal.xy * positionClip.w * model_silhouetteSize * czm_pixelRatio / czm_viewport.z;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
void modelSplitterStage()
|
||||
{
|
||||
// Don't split when rendering the shadow map, because it is rendered from
|
||||
// the perspective of a totally different camera.
|
||||
#ifndef SHADOW_MAP
|
||||
if (model_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;
|
||||
if (model_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;
|
||||
#endif
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void modelSplitterStage()\n\
|
||||
{\n\
|
||||
// Don't split when rendering the shadow map, because it is rendered from\n\
|
||||
// the perspective of a totally different camera.\n\
|
||||
#ifndef SHADOW_MAP\n\
|
||||
if (model_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;\n\
|
||||
if (model_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
precision highp float;
|
||||
|
||||
czm_modelVertexOutput defaultVertexOutput(vec3 positionMC) {
|
||||
czm_modelVertexOutput vsOutput;
|
||||
vsOutput.positionMC = positionMC;
|
||||
vsOutput.pointSize = 1.0;
|
||||
return vsOutput;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Initialize the attributes struct with all
|
||||
// attributes except quantized ones.
|
||||
ProcessedAttributes attributes;
|
||||
initializeAttributes(attributes);
|
||||
|
||||
#ifdef HAS_IMAGERY
|
||||
initializeImageryAttributes();
|
||||
#endif
|
||||
|
||||
// Dequantize the quantized ones and add them to the
|
||||
// attributes struct.
|
||||
#ifdef USE_DEQUANTIZATION
|
||||
dequantizationStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_MORPH_TARGETS
|
||||
morphTargetsStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SKINNING
|
||||
skinningStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PRIMITIVE_OUTLINE
|
||||
primitiveOutlineStage();
|
||||
#endif
|
||||
|
||||
// Compute the bitangent according to the formula in the glTF spec.
|
||||
// Normal and tangents can be affected by morphing and skinning, so
|
||||
// the bitangent should not be computed until their values are finalized.
|
||||
#ifdef HAS_BITANGENTS
|
||||
attributes.bitangentMC = normalize(cross(attributes.normalMC, attributes.tangentMC) * attributes.tangentSignMC);
|
||||
#endif
|
||||
|
||||
FeatureIds featureIds;
|
||||
featureIdStage(featureIds, attributes);
|
||||
|
||||
#ifdef HAS_SELECTED_FEATURE_ID
|
||||
SelectedFeature feature;
|
||||
selectedFeatureIdStage(feature, featureIds);
|
||||
// Handle any show properties that come from the style.
|
||||
cpuStylingStage(attributes.positionMC, feature);
|
||||
#endif
|
||||
|
||||
#if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)
|
||||
// The scene mode 2D pipeline stage and instancing stage add a different
|
||||
// model view matrix to accurately project the model to 2D. However, the
|
||||
// output positions and normals should be transformed by the 3D matrices
|
||||
// to keep the data the same for the fragment shader.
|
||||
mat4 modelView = czm_modelView3D;
|
||||
mat3 normal = czm_normal3D;
|
||||
#else
|
||||
// These are used for individual model projection because they will
|
||||
// automatically change based on the scene mode.
|
||||
mat4 modelView = czm_modelView;
|
||||
mat3 normal = czm_normal;
|
||||
#endif
|
||||
|
||||
// Update the position for this instance in place
|
||||
#ifdef HAS_INSTANCING
|
||||
|
||||
// The legacy instance stage is used when rendering i3dm models that
|
||||
// encode instances transforms in world space, as opposed to glTF models
|
||||
// that use EXT_mesh_gpu_instancing, where instance transforms are encoded
|
||||
// in object space.
|
||||
#ifdef USE_LEGACY_INSTANCING
|
||||
mat4 instanceModelView;
|
||||
mat3 instanceModelViewInverseTranspose;
|
||||
|
||||
legacyInstancingStage(attributes, instanceModelView, instanceModelViewInverseTranspose);
|
||||
|
||||
modelView = instanceModelView;
|
||||
normal = instanceModelViewInverseTranspose;
|
||||
#else
|
||||
instancingStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef USE_PICKING
|
||||
v_pickColor = a_pickColor;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Metadata metadata;
|
||||
MetadataClass metadataClass;
|
||||
MetadataStatistics metadataStatistics;
|
||||
metadataStage(featureIds, metadata, metadataClass, metadataStatistics, attributes);
|
||||
|
||||
#ifdef HAS_VERTICAL_EXAGGERATION
|
||||
verticalExaggerationStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_CUSTOM_VERTEX_SHADER
|
||||
czm_modelVertexOutput vsOutput = defaultVertexOutput(attributes.positionMC);
|
||||
customShaderStage(vsOutput, attributes, featureIds, metadata, metadataClass, metadataStatistics);
|
||||
#endif
|
||||
|
||||
// Compute the final position in each coordinate system needed.
|
||||
// This returns the value that will be assigned to gl_Position.
|
||||
vec4 positionClip = geometryStage(attributes, modelView, normal);
|
||||
|
||||
#if defined(HAS_LINE_CUMULATIVE_DISTANCE) || defined(HAS_LINE_PATTERN)
|
||||
lineStyleStageVS(attributes);
|
||||
#endif
|
||||
|
||||
// This must go after the geometry stage as it needs v_positionWC
|
||||
#ifdef HAS_ATMOSPHERE
|
||||
atmosphereStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLIPPING_POLYGONS
|
||||
modelClippingPolygonsStage(attributes);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SILHOUETTE
|
||||
silhouetteStage(attributes, positionClip);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE
|
||||
float show = pointCloudShowStylingStage(attributes, metadata);
|
||||
#else
|
||||
float show = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING
|
||||
show *= pointCloudBackFaceCullingStage();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE
|
||||
v_pointCloudColor = pointCloudColorStylingStage(attributes, metadata);
|
||||
#endif
|
||||
|
||||
#ifdef PRIMITIVE_TYPE_POINTS
|
||||
#ifdef HAS_CUSTOM_VERTEX_SHADER
|
||||
gl_PointSize = vsOutput.pointSize;
|
||||
#elif defined(HAS_POINT_CLOUD_POINT_SIZE_STYLE) || defined(HAS_POINT_CLOUD_ATTENUATION)
|
||||
gl_PointSize = pointCloudPointSizeStylingStage(attributes, metadata);
|
||||
#elif defined(HAS_POINT_DIAMETER)
|
||||
gl_PointSize = u_pointDiameter;
|
||||
#else
|
||||
gl_PointSize = 1.0;
|
||||
#endif
|
||||
|
||||
gl_PointSize *= show;
|
||||
#endif
|
||||
|
||||
// Important NOT to compute gl_Position = show * positionClip or we hit:
|
||||
// https://github.com/CesiumGS/cesium/issues/11270
|
||||
//
|
||||
// We will discard points with v_pointCloudShow == 0 in the fragment shader.
|
||||
gl_Position = positionClip;
|
||||
|
||||
#ifdef HAS_EDGE_VISIBILITY
|
||||
edgeVisibilityStageVS();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE
|
||||
v_pointCloudShow = show;
|
||||
#endif
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "precision highp float;\n\
|
||||
\n\
|
||||
czm_modelVertexOutput defaultVertexOutput(vec3 positionMC) {\n\
|
||||
czm_modelVertexOutput vsOutput;\n\
|
||||
vsOutput.positionMC = positionMC;\n\
|
||||
vsOutput.pointSize = 1.0;\n\
|
||||
return vsOutput;\n\
|
||||
}\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
// Initialize the attributes struct with all\n\
|
||||
// attributes except quantized ones.\n\
|
||||
ProcessedAttributes attributes;\n\
|
||||
initializeAttributes(attributes);\n\
|
||||
\n\
|
||||
#ifdef HAS_IMAGERY\n\
|
||||
initializeImageryAttributes();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Dequantize the quantized ones and add them to the\n\
|
||||
// attributes struct.\n\
|
||||
#ifdef USE_DEQUANTIZATION\n\
|
||||
dequantizationStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_MORPH_TARGETS\n\
|
||||
morphTargetsStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_SKINNING\n\
|
||||
skinningStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_PRIMITIVE_OUTLINE\n\
|
||||
primitiveOutlineStage();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Compute the bitangent according to the formula in the glTF spec.\n\
|
||||
// Normal and tangents can be affected by morphing and skinning, so\n\
|
||||
// the bitangent should not be computed until their values are finalized.\n\
|
||||
#ifdef HAS_BITANGENTS\n\
|
||||
attributes.bitangentMC = normalize(cross(attributes.normalMC, attributes.tangentMC) * attributes.tangentSignMC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
FeatureIds featureIds;\n\
|
||||
featureIdStage(featureIds, attributes);\n\
|
||||
\n\
|
||||
#ifdef HAS_SELECTED_FEATURE_ID\n\
|
||||
SelectedFeature feature;\n\
|
||||
selectedFeatureIdStage(feature, featureIds);\n\
|
||||
// Handle any show properties that come from the style.\n\
|
||||
cpuStylingStage(attributes.positionMC, feature);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)\n\
|
||||
// The scene mode 2D pipeline stage and instancing stage add a different\n\
|
||||
// model view matrix to accurately project the model to 2D. However, the\n\
|
||||
// output positions and normals should be transformed by the 3D matrices\n\
|
||||
// to keep the data the same for the fragment shader.\n\
|
||||
mat4 modelView = czm_modelView3D;\n\
|
||||
mat3 normal = czm_normal3D;\n\
|
||||
#else\n\
|
||||
// These are used for individual model projection because they will\n\
|
||||
// automatically change based on the scene mode.\n\
|
||||
mat4 modelView = czm_modelView;\n\
|
||||
mat3 normal = czm_normal;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Update the position for this instance in place\n\
|
||||
#ifdef HAS_INSTANCING\n\
|
||||
\n\
|
||||
// The legacy instance stage is used when rendering i3dm models that\n\
|
||||
// encode instances transforms in world space, as opposed to glTF models\n\
|
||||
// that use EXT_mesh_gpu_instancing, where instance transforms are encoded\n\
|
||||
// in object space.\n\
|
||||
#ifdef USE_LEGACY_INSTANCING\n\
|
||||
mat4 instanceModelView;\n\
|
||||
mat3 instanceModelViewInverseTranspose;\n\
|
||||
\n\
|
||||
legacyInstancingStage(attributes, instanceModelView, instanceModelViewInverseTranspose);\n\
|
||||
\n\
|
||||
modelView = instanceModelView;\n\
|
||||
normal = instanceModelViewInverseTranspose;\n\
|
||||
#else\n\
|
||||
instancingStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef USE_PICKING\n\
|
||||
v_pickColor = a_pickColor;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
Metadata metadata;\n\
|
||||
MetadataClass metadataClass;\n\
|
||||
MetadataStatistics metadataStatistics;\n\
|
||||
metadataStage(featureIds, metadata, metadataClass, metadataStatistics, attributes);\n\
|
||||
\n\
|
||||
#ifdef HAS_VERTICAL_EXAGGERATION\n\
|
||||
verticalExaggerationStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_CUSTOM_VERTEX_SHADER\n\
|
||||
czm_modelVertexOutput vsOutput = defaultVertexOutput(attributes.positionMC);\n\
|
||||
customShaderStage(vsOutput, attributes, featureIds, metadata, metadataClass, metadataStatistics);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Compute the final position in each coordinate system needed.\n\
|
||||
// This returns the value that will be assigned to gl_Position.\n\
|
||||
vec4 positionClip = geometryStage(attributes, modelView, normal);\n\
|
||||
\n\
|
||||
#if defined(HAS_LINE_CUMULATIVE_DISTANCE) || defined(HAS_LINE_PATTERN)\n\
|
||||
lineStyleStageVS(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// This must go after the geometry stage as it needs v_positionWC\n\
|
||||
#ifdef HAS_ATMOSPHERE\n\
|
||||
atmosphereStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef ENABLE_CLIPPING_POLYGONS\n\
|
||||
modelClippingPolygonsStage(attributes);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_SILHOUETTE\n\
|
||||
silhouetteStage(attributes, positionClip);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE\n\
|
||||
float show = pointCloudShowStylingStage(attributes, metadata);\n\
|
||||
#else\n\
|
||||
float show = 1.0;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING\n\
|
||||
show *= pointCloudBackFaceCullingStage();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE\n\
|
||||
v_pointCloudColor = pointCloudColorStylingStage(attributes, metadata);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef PRIMITIVE_TYPE_POINTS\n\
|
||||
#ifdef HAS_CUSTOM_VERTEX_SHADER\n\
|
||||
gl_PointSize = vsOutput.pointSize;\n\
|
||||
#elif defined(HAS_POINT_CLOUD_POINT_SIZE_STYLE) || defined(HAS_POINT_CLOUD_ATTENUATION)\n\
|
||||
gl_PointSize = pointCloudPointSizeStylingStage(attributes, metadata);\n\
|
||||
#elif defined(HAS_POINT_DIAMETER)\n\
|
||||
gl_PointSize = u_pointDiameter;\n\
|
||||
#else\n\
|
||||
gl_PointSize = 1.0;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
gl_PointSize *= show;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
// Important NOT to compute gl_Position = show * positionClip or we hit:\n\
|
||||
// https://github.com/CesiumGS/cesium/issues/11270\n\
|
||||
//\n\
|
||||
// We will discard points with v_pointCloudShow == 0 in the fragment shader.\n\
|
||||
gl_Position = positionClip;\n\
|
||||
\n\
|
||||
#ifdef HAS_EDGE_VISIBILITY\n\
|
||||
edgeVisibilityStageVS();\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE\n\
|
||||
v_pointCloudShow = show;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
void morphTargetsStage(inout ProcessedAttributes attributes)
|
||||
{
|
||||
vec3 positionMC = attributes.positionMC;
|
||||
attributes.positionMC = getMorphedPosition(positionMC);
|
||||
|
||||
#ifdef HAS_NORMALS
|
||||
vec3 normalMC = attributes.normalMC;
|
||||
attributes.normalMC = getMorphedNormal(normalMC);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TANGENTS
|
||||
vec3 tangentMC = attributes.tangentMC;
|
||||
attributes.tangentMC = getMorphedTangent(tangentMC);
|
||||
#endif
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void morphTargetsStage(inout ProcessedAttributes attributes) \n\
|
||||
{\n\
|
||||
vec3 positionMC = attributes.positionMC;\n\
|
||||
attributes.positionMC = getMorphedPosition(positionMC);\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
vec3 normalMC = attributes.normalMC;\n\
|
||||
attributes.normalMC = getMorphedNormal(normalMC);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_TANGENTS\n\
|
||||
vec3 tangentMC = attributes.tangentMC;\n\
|
||||
attributes.tangentMC = getMorphedTangent(tangentMC);\n\
|
||||
#endif\n\
|
||||
}";
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
float getPointSizeFromAttenuation(vec3 positionEC) {
|
||||
// Variables are packed into a single vector to minimize gl.uniformXXX() calls
|
||||
float pointSize = model_pointCloudParameters.x;
|
||||
float geometricError = model_pointCloudParameters.y;
|
||||
float depthMultiplier = model_pointCloudParameters.z;
|
||||
|
||||
float depth = -positionEC.z;
|
||||
return min((geometricError / depth) * depthMultiplier, pointSize);
|
||||
}
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE
|
||||
float pointCloudShowStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {
|
||||
float tiles3d_tileset_time = model_pointCloudParameters.w;
|
||||
return float(getShowFromStyle(attributes, metadata, tiles3d_tileset_time));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE
|
||||
vec4 pointCloudColorStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {
|
||||
float tiles3d_tileset_time = model_pointCloudParameters.w;
|
||||
return getColorFromStyle(attributes, metadata, tiles3d_tileset_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_POINT_SIZE_STYLE
|
||||
float pointCloudPointSizeStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {
|
||||
float tiles3d_tileset_time = model_pointCloudParameters.w;
|
||||
return float(getPointSizeFromStyle(attributes, metadata, tiles3d_tileset_time));
|
||||
}
|
||||
#elif defined(HAS_POINT_CLOUD_ATTENUATION)
|
||||
float pointCloudPointSizeStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {
|
||||
return getPointSizeFromAttenuation(v_positionEC);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING
|
||||
float pointCloudBackFaceCullingStage() {
|
||||
#if defined(HAS_NORMALS) && !defined(HAS_DOUBLE_SIDED_MATERIAL)
|
||||
// This needs to be computed in eye coordinates so we can't use attributes.normalMC
|
||||
return step(-v_normalEC.z, 0.0);
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "float getPointSizeFromAttenuation(vec3 positionEC) {\n\
|
||||
// Variables are packed into a single vector to minimize gl.uniformXXX() calls\n\
|
||||
float pointSize = model_pointCloudParameters.x;\n\
|
||||
float geometricError = model_pointCloudParameters.y;\n\
|
||||
float depthMultiplier = model_pointCloudParameters.z;\n\
|
||||
\n\
|
||||
float depth = -positionEC.z;\n\
|
||||
return min((geometricError / depth) * depthMultiplier, pointSize);\n\
|
||||
}\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_SHOW_STYLE\n\
|
||||
float pointCloudShowStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n\
|
||||
float tiles3d_tileset_time = model_pointCloudParameters.w;\n\
|
||||
return float(getShowFromStyle(attributes, metadata, tiles3d_tileset_time));\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_COLOR_STYLE\n\
|
||||
vec4 pointCloudColorStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n\
|
||||
float tiles3d_tileset_time = model_pointCloudParameters.w;\n\
|
||||
return getColorFromStyle(attributes, metadata, tiles3d_tileset_time);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_POINT_SIZE_STYLE\n\
|
||||
float pointCloudPointSizeStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n\
|
||||
float tiles3d_tileset_time = model_pointCloudParameters.w;\n\
|
||||
return float(getPointSizeFromStyle(attributes, metadata, tiles3d_tileset_time));\n\
|
||||
}\n\
|
||||
#elif defined(HAS_POINT_CLOUD_ATTENUATION)\n\
|
||||
float pointCloudPointSizeStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n\
|
||||
return getPointSizeFromAttenuation(v_positionEC);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING\n\
|
||||
float pointCloudBackFaceCullingStage() {\n\
|
||||
#if defined(HAS_NORMALS) && !defined(HAS_DOUBLE_SIDED_MATERIAL)\n\
|
||||
// This needs to be computed in eye coordinates so we can't use attributes.normalMC\n\
|
||||
return step(-v_normalEC.z, 0.0);\n\
|
||||
#else\n\
|
||||
return 1.0;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
";
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
void primitiveOutlineStage(inout czm_modelMaterial material) {
|
||||
if (!model_showOutline) {
|
||||
return;
|
||||
}
|
||||
|
||||
float outlineX =
|
||||
texture(model_outlineTexture, vec2(v_outlineCoordinates.x, 0.5)).r;
|
||||
float outlineY =
|
||||
texture(model_outlineTexture, vec2(v_outlineCoordinates.y, 0.5)).r;
|
||||
float outlineZ =
|
||||
texture(model_outlineTexture, vec2(v_outlineCoordinates.z, 0.5)).r;
|
||||
float outlineness = max(outlineX, max(outlineY, outlineZ));
|
||||
|
||||
material.diffuse = mix(material.diffuse, model_outlineColor.rgb, model_outlineColor.a * outlineness);
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void primitiveOutlineStage(inout czm_modelMaterial material) {\n\
|
||||
if (!model_showOutline) {\n\
|
||||
return;\n\
|
||||
}\n\
|
||||
\n\
|
||||
float outlineX = \n\
|
||||
texture(model_outlineTexture, vec2(v_outlineCoordinates.x, 0.5)).r;\n\
|
||||
float outlineY = \n\
|
||||
texture(model_outlineTexture, vec2(v_outlineCoordinates.y, 0.5)).r;\n\
|
||||
float outlineZ = \n\
|
||||
texture(model_outlineTexture, vec2(v_outlineCoordinates.z, 0.5)).r;\n\
|
||||
float outlineness = max(outlineX, max(outlineY, outlineZ));\n\
|
||||
\n\
|
||||
material.diffuse = mix(material.diffuse, model_outlineColor.rgb, model_outlineColor.a * outlineness);\n\
|
||||
}\n\
|
||||
";
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
void primitiveOutlineStage() {
|
||||
v_outlineCoordinates = a_outlineCoordinates;
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void primitiveOutlineStage() {\n\
|
||||
v_outlineCoordinates = a_outlineCoordinates;\n\
|
||||
}\n\
|
||||
";
|
||||
Generated
Vendored
+51
@@ -0,0 +1,51 @@
|
||||
vec2 computeSt(float featureId)
|
||||
{
|
||||
float stepX = model_textureStep.x;
|
||||
float centerX = model_textureStep.y;
|
||||
|
||||
#ifdef MULTILINE_BATCH_TEXTURE
|
||||
float stepY = model_textureStep.z;
|
||||
float centerY = model_textureStep.w;
|
||||
|
||||
float xId = mod(featureId, model_textureDimensions.x);
|
||||
float yId = floor(featureId / model_textureDimensions.x);
|
||||
|
||||
return vec2(centerX + (xId * stepX), centerY + (yId * stepY));
|
||||
#else
|
||||
return vec2(centerX + (featureId * stepX), 0.5);
|
||||
#endif
|
||||
}
|
||||
|
||||
void selectedFeatureIdStage(out SelectedFeature feature, FeatureIds featureIds)
|
||||
{
|
||||
int featureId = featureIds.SELECTED_FEATURE_ID;
|
||||
|
||||
|
||||
if (featureId < model_featuresLength)
|
||||
{
|
||||
vec2 featureSt = computeSt(float(featureId));
|
||||
|
||||
feature.id = featureId;
|
||||
feature.st = featureSt;
|
||||
feature.color = texture(model_batchTexture, featureSt);
|
||||
}
|
||||
// Floating point comparisons can be unreliable in GLSL, so we
|
||||
// increment the feature ID to make sure it's always greater
|
||||
// then the model_featuresLength - a condition we check for in the
|
||||
// pick ID, to avoid sampling the pick texture if the feature ID is
|
||||
// greater than the number of features.
|
||||
else
|
||||
{
|
||||
feature.id = model_featuresLength + 1;
|
||||
feature.st = vec2(0.0);
|
||||
feature.color = vec4(1.0);
|
||||
}
|
||||
|
||||
#ifdef HAS_NULL_FEATURE_ID
|
||||
if (featureId == model_nullFeatureId) {
|
||||
feature.id = featureId;
|
||||
feature.st = vec2(0.0);
|
||||
feature.color = vec4(1.0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "vec2 computeSt(float featureId)\n\
|
||||
{\n\
|
||||
float stepX = model_textureStep.x;\n\
|
||||
float centerX = model_textureStep.y;\n\
|
||||
\n\
|
||||
#ifdef MULTILINE_BATCH_TEXTURE\n\
|
||||
float stepY = model_textureStep.z;\n\
|
||||
float centerY = model_textureStep.w;\n\
|
||||
\n\
|
||||
float xId = mod(featureId, model_textureDimensions.x); \n\
|
||||
float yId = floor(featureId / model_textureDimensions.x);\n\
|
||||
\n\
|
||||
return vec2(centerX + (xId * stepX), centerY + (yId * stepY));\n\
|
||||
#else\n\
|
||||
return vec2(centerX + (featureId * stepX), 0.5);\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
\n\
|
||||
void selectedFeatureIdStage(out SelectedFeature feature, FeatureIds featureIds)\n\
|
||||
{ \n\
|
||||
int featureId = featureIds.SELECTED_FEATURE_ID;\n\
|
||||
\n\
|
||||
\n\
|
||||
if (featureId < model_featuresLength)\n\
|
||||
{\n\
|
||||
vec2 featureSt = computeSt(float(featureId));\n\
|
||||
\n\
|
||||
feature.id = featureId;\n\
|
||||
feature.st = featureSt;\n\
|
||||
feature.color = texture(model_batchTexture, featureSt);\n\
|
||||
}\n\
|
||||
// Floating point comparisons can be unreliable in GLSL, so we\n\
|
||||
// increment the feature ID to make sure it's always greater\n\
|
||||
// then the model_featuresLength - a condition we check for in the\n\
|
||||
// pick ID, to avoid sampling the pick texture if the feature ID is\n\
|
||||
// greater than the number of features.\n\
|
||||
else\n\
|
||||
{\n\
|
||||
feature.id = model_featuresLength + 1;\n\
|
||||
feature.st = vec2(0.0);\n\
|
||||
feature.color = vec4(1.0);\n\
|
||||
}\n\
|
||||
\n\
|
||||
#ifdef HAS_NULL_FEATURE_ID\n\
|
||||
if (featureId == model_nullFeatureId) {\n\
|
||||
feature.id = featureId;\n\
|
||||
feature.st = vec2(0.0);\n\
|
||||
feature.color = vec4(1.0);\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
";
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
void skinningStage(inout ProcessedAttributes attributes)
|
||||
{
|
||||
mat4 skinningMatrix = getSkinningMatrix();
|
||||
mat3 skinningMatrixMat3 = mat3(skinningMatrix);
|
||||
|
||||
vec4 positionMC = vec4(attributes.positionMC, 1.0);
|
||||
attributes.positionMC = vec3(skinningMatrix * positionMC);
|
||||
|
||||
#ifdef HAS_NORMALS
|
||||
vec3 normalMC = attributes.normalMC;
|
||||
attributes.normalMC = skinningMatrixMat3 * normalMC;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TANGENTS
|
||||
vec3 tangentMC = attributes.tangentMC;
|
||||
attributes.tangentMC = skinningMatrixMat3 * tangentMC;
|
||||
#endif
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void skinningStage(inout ProcessedAttributes attributes) \n\
|
||||
{\n\
|
||||
mat4 skinningMatrix = getSkinningMatrix();\n\
|
||||
mat3 skinningMatrixMat3 = mat3(skinningMatrix);\n\
|
||||
\n\
|
||||
vec4 positionMC = vec4(attributes.positionMC, 1.0);\n\
|
||||
attributes.positionMC = vec3(skinningMatrix * positionMC);\n\
|
||||
\n\
|
||||
#ifdef HAS_NORMALS\n\
|
||||
vec3 normalMC = attributes.normalMC;\n\
|
||||
attributes.normalMC = skinningMatrixMat3 * normalMC;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifdef HAS_TANGENTS\n\
|
||||
vec3 tangentMC = attributes.tangentMC;\n\
|
||||
attributes.tangentMC = skinningMatrixMat3 * tangentMC;\n\
|
||||
#endif\n\
|
||||
}";
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
void verticalExaggerationStage(
|
||||
inout ProcessedAttributes attributes
|
||||
) {
|
||||
// Compute the distance from the camera to the local center of curvature.
|
||||
vec4 vertexPositionENU = czm_modelToEnu * vec4(attributes.positionMC, 1.0);
|
||||
vec2 vertexAzimuth = normalize(vertexPositionENU.xy);
|
||||
// Curvature = 1 / radius of curvature.
|
||||
float azimuthalCurvature = dot(vertexAzimuth * vertexAzimuth, czm_eyeEllipsoidCurvature);
|
||||
float eyeToCenter = 1.0 / azimuthalCurvature + czm_eyeHeight;
|
||||
|
||||
// Compute the approximate ellipsoid normal at the vertex position.
|
||||
// Uses a circular approximation for the Earth curvature along the geodesic.
|
||||
vec3 vertexPositionEC = (czm_modelView * vec4(attributes.positionMC, 1.0)).xyz;
|
||||
vec3 centerToVertex = eyeToCenter * czm_eyeEllipsoidNormalEC + vertexPositionEC;
|
||||
vec3 vertexNormal = normalize(centerToVertex);
|
||||
|
||||
// Estimate the (sine of the) angle between the camera direction and the vertex normal
|
||||
float verticalDistance = dot(vertexPositionEC, czm_eyeEllipsoidNormalEC);
|
||||
float horizontalDistance = length(vertexPositionEC - verticalDistance * czm_eyeEllipsoidNormalEC);
|
||||
float sinTheta = horizontalDistance / (eyeToCenter + verticalDistance);
|
||||
bool isSmallAngle = clamp(sinTheta, 0.0, 0.05) == sinTheta;
|
||||
|
||||
// Approximate the change in height above the ellipsoid, from camera to vertex position.
|
||||
float exactVersine = 1.0 - dot(czm_eyeEllipsoidNormalEC, vertexNormal);
|
||||
float smallAngleVersine = 0.5 * sinTheta * sinTheta;
|
||||
float versine = isSmallAngle ? smallAngleVersine : exactVersine;
|
||||
float dHeight = dot(vertexPositionEC, vertexNormal) - eyeToCenter * versine;
|
||||
float vertexHeight = czm_eyeHeight + dHeight;
|
||||
|
||||
// Transform the approximate vertex normal to model coordinates.
|
||||
vec3 vertexNormalMC = (czm_inverseModelView * vec4(vertexNormal, 0.0)).xyz;
|
||||
vertexNormalMC = normalize(vertexNormalMC);
|
||||
|
||||
// Compute the exaggeration and apply it along the approximate vertex normal.
|
||||
float stretch = u_verticalExaggerationAndRelativeHeight.x;
|
||||
float shift = u_verticalExaggerationAndRelativeHeight.y;
|
||||
float exaggeration = (vertexHeight - shift) * (stretch - 1.0);
|
||||
attributes.positionMC += exaggeration * vertexNormalMC;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
//This file is automatically rebuilt by the Cesium build process.
|
||||
export default "void verticalExaggerationStage(\n\
|
||||
inout ProcessedAttributes attributes\n\
|
||||
) {\n\
|
||||
// Compute the distance from the camera to the local center of curvature.\n\
|
||||
vec4 vertexPositionENU = czm_modelToEnu * vec4(attributes.positionMC, 1.0);\n\
|
||||
vec2 vertexAzimuth = normalize(vertexPositionENU.xy);\n\
|
||||
// Curvature = 1 / radius of curvature.\n\
|
||||
float azimuthalCurvature = dot(vertexAzimuth * vertexAzimuth, czm_eyeEllipsoidCurvature);\n\
|
||||
float eyeToCenter = 1.0 / azimuthalCurvature + czm_eyeHeight;\n\
|
||||
\n\
|
||||
// Compute the approximate ellipsoid normal at the vertex position.\n\
|
||||
// Uses a circular approximation for the Earth curvature along the geodesic.\n\
|
||||
vec3 vertexPositionEC = (czm_modelView * vec4(attributes.positionMC, 1.0)).xyz;\n\
|
||||
vec3 centerToVertex = eyeToCenter * czm_eyeEllipsoidNormalEC + vertexPositionEC;\n\
|
||||
vec3 vertexNormal = normalize(centerToVertex);\n\
|
||||
\n\
|
||||
// Estimate the (sine of the) angle between the camera direction and the vertex normal\n\
|
||||
float verticalDistance = dot(vertexPositionEC, czm_eyeEllipsoidNormalEC);\n\
|
||||
float horizontalDistance = length(vertexPositionEC - verticalDistance * czm_eyeEllipsoidNormalEC);\n\
|
||||
float sinTheta = horizontalDistance / (eyeToCenter + verticalDistance);\n\
|
||||
bool isSmallAngle = clamp(sinTheta, 0.0, 0.05) == sinTheta;\n\
|
||||
\n\
|
||||
// Approximate the change in height above the ellipsoid, from camera to vertex position.\n\
|
||||
float exactVersine = 1.0 - dot(czm_eyeEllipsoidNormalEC, vertexNormal);\n\
|
||||
float smallAngleVersine = 0.5 * sinTheta * sinTheta;\n\
|
||||
float versine = isSmallAngle ? smallAngleVersine : exactVersine;\n\
|
||||
float dHeight = dot(vertexPositionEC, vertexNormal) - eyeToCenter * versine;\n\
|
||||
float vertexHeight = czm_eyeHeight + dHeight;\n\
|
||||
\n\
|
||||
// Transform the approximate vertex normal to model coordinates.\n\
|
||||
vec3 vertexNormalMC = (czm_inverseModelView * vec4(vertexNormal, 0.0)).xyz;\n\
|
||||
vertexNormalMC = normalize(vertexNormalMC);\n\
|
||||
\n\
|
||||
// Compute the exaggeration and apply it along the approximate vertex normal.\n\
|
||||
float stretch = u_verticalExaggerationAndRelativeHeight.x;\n\
|
||||
float shift = u_verticalExaggerationAndRelativeHeight.y;\n\
|
||||
float exaggeration = (vertexHeight - shift) * (stretch - 1.0);\n\
|
||||
attributes.positionMC += exaggeration * vertexNormalMC;\n\
|
||||
}\n\
|
||||
";
|
||||
Reference in New Issue
Block a user