Add isNaN, isFinite, null, and undefined support to GLSL styling backend #8621
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #8615
Local sandcastle
The goal of this PR is to make
isNaN
,isFinite
,null
, andundefined
usable in point clouds styles so that a style written for 3D buildings withnull
properties won't throw an error if also applied to point clouds.isNaN
-isnan
is not available in GLSL 1.0 so the approximation isvalue != value
. The Sandcastle confirms that this check works.isFinite
-isinf
is not available in GLSL 1.0 so the approximation isvalue < czm_infinity
. GLSL doesn't have an infinity constant and floating point precision is not predictable enough across the board to use the actual max float.czm_infinity
is5906376272000.0
, the distance from the Sun to Pluto in meters, and is "big enough".null
- uses sentinelczm_infinity
. Would have preferred to use NaN but GLSL doesn't have a NaN constant. You can sometimes fake a NaN by doing an operation likesqrt(-20.0)
but I read that it's not reliable across all drivers/GPUs.undefined
- uses sentinelczm_infinity
. Same as above.This PR does not attempt to make GLSL follow the same casting and comparison rules as JavaScript. E.g.
Boolean(null)
is false in JS whilebool(5906376272000.0)
is true in transcoded GLSL. Not to mention all the math operations and edge cases likeisNaN(null)
. I think it's possible to fix nearly all of these with some ternaries like forBoolean(value)
getting transcoded to'(' + left + ' === ' + nullSentinel + ' ? false : bool(' + left + ')'
, and I started doing that, but it's not super important and was holding up this PR.But in the end I'm not too worried about this because per-point properties are stored in binary and can never be null or undefined. The user would need to write a meaningless style like
${temperature} < 10.0 === Boolean(undefined)
to trigger one of the edge cases.