Files
filament/shaders/src/depth_main.fs
T
Mathias Agopian 11adcbed25 fix VSM's high precision option on mobile (#6873)
the math needs to be maintained in highp, including during the blur
pass.

we add the ability to specify a "precision" qualifier to the "output"
of a post-process material.

we also remove the mediump clamping we used to do on mobile, it shouldn't
be done automatically behind the scenes, it's up to the shaders to do
it if it makes sense.
2023-06-07 21:57:17 -07:00

96 lines
3.0 KiB
GLSL

#if defined(VARIANT_HAS_VSM)
layout(location = 0) out highp vec4 fragColor;
#elif defined(VARIANT_HAS_PICKING)
# if __VERSION__ == 100
highp vec4 outPicking;
# else
# if MATERIAL_FEATURE_LEVEL == 0
layout(location = 0) out highp vec4 outPicking;
# else
layout(location = 0) out highp vec2 outPicking;
# endif
# endif
#else
// not color output
#endif
//------------------------------------------------------------------------------
// Depth
//
// note: VARIANT_HAS_VSM and VARIANT_HAS_PICKING are mutually exclusive
//------------------------------------------------------------------------------
highp vec2 computeDepthMomentsVSM(const highp float depth);
void main() {
filament_lodBias = frameUniforms.lodBias;
initObjectUniforms(object_uniforms);
#if defined(BLEND_MODE_MASKED) || ((defined(BLEND_MODE_TRANSPARENT) || defined(BLEND_MODE_FADE)) && defined(MATERIAL_HAS_TRANSPARENT_SHADOW))
MaterialInputs inputs;
initMaterial(inputs);
material(inputs);
float alpha = inputs.baseColor.a;
#if defined(BLEND_MODE_MASKED)
if (alpha < getMaskThreshold()) {
discard;
}
#endif
#if defined(MATERIAL_HAS_TRANSPARENT_SHADOW)
// Interleaved gradient noise, see dithering.fs
float noise = interleavedGradientNoise(gl_FragCoord.xy);
if (noise >= alpha) {
discard;
}
#endif
#endif
#if defined(VARIANT_HAS_VSM)
// interpolated depth is stored in vertex_worldPosition.w (see main.vs)
// we always compute the "negative" side of ELVSM because the cost is small, and this allows
// EVSM/ELVSM choice to be done on the CPU side more easily.
highp float depth = vertex_worldPosition.w;
depth = exp(frameUniforms.vsmExponent * depth);
fragColor.xy = computeDepthMomentsVSM(depth);
fragColor.zw = computeDepthMomentsVSM(-1.0 / depth); // requires at least RGBA16F
#elif defined(VARIANT_HAS_PICKING)
#if MATERIAL_FEATURE_LEVEL == 0
outPicking.a = float((object_uniforms.objectId / 65536) % 256) / 255.0;
outPicking.b = float((object_uniforms.objectId / 256) % 256) / 255.0;
outPicking.g = float( object_uniforms.objectId % 256) / 255.0;
outPicking.r = vertex_position.z / vertex_position.w;
#else
outPicking.x = float(object_uniforms.objectId);
outPicking.y = vertex_position.z / vertex_position.w;
#endif
#if __VERSION__ == 100
gl_FragData[0] = outPicking;
#endif
#else
// that's it
#endif
}
highp vec2 computeDepthMomentsVSM(const highp float depth) {
// computes the moments
// See GPU Gems 3
// https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-8-summed-area-variance-shadow-maps
highp vec2 moments;
// the first moment is just the depth (average)
moments.x = depth;
// compute the 2nd moment over the pixel extents.
moments.y = depth * depth;
// the local linear approximation is not correct with a warped depth
//highp float dx = dFdx(depth);
//highp float dy = dFdy(depth);
//moments.y += 0.25 * (dx * dx + dy * dy);
return moments;
}