Files
random_tools/node_modules/@cesium/engine/Source/Shaders/Model/ModelFS.glsl
T
2026-08-11 09:53:42 -04:00

262 lines
10 KiB
GLSL

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
}