-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apply correct fog+blending in shaders #10496
Conversation
Here's a brief rundown of the effect of gamma. I think I was fairly wrong about it. It wasn't the source of the antialiasing/opacity problems (it was premultiplied alpha). As for the difference in color, it's quite noticeable but somewhat arbitrary, depending on the fog settings and color. The overall lightness is different though. I tried fog opacity normal/squared as well as gamma correct/incorrect. The set of four isn't particularly interesting. Instead, two roughly equivalent things (since gamma correction is very roughly a square root) are:
Here's a gif which flips back and forth between these two. The lighter one is with incorrect gamma, and the darker one is with gamma-corrected application of fog. It's subtle, but I think this is the kind of thing where correct gamma prevents annoying side effects like unexpected/unnatural changes in brightness when blending. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Testing the gamma in more details now.
src/shaders/_prelude_fog.vertex.glsl
Outdated
vec3 fog_position(vec3 pos) { | ||
vec4 p = u_cam_matrix * vec4(pos, 1); | ||
return p.xyz / p.w; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you positive we need / p.w
? I thought u_cam_matrix would ensure w == 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I guess as long as it's strictly affine, that is the case. I try to at least add a comment noting it's a stated assumption.
src/shaders/_prelude.fragment.glsl
Outdated
#endif | ||
} | ||
|
||
vec3 gammaMix(vec3 a, vec3 b, float x) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in favor of leaving it gamma correct. The best test case is black fog on a white style, making these transitions a lot darker than they should be:
without GAMMA_CORRECT
with GAMMA_CORRECT
Which acts exactly as the issue we could see with a simple gradient:
Concerning cost, the simple pow function are good enough here, I don't think we should use the more accurate versions (It's hard to notice a difference using them), and may only be a critical choice for complex lighting.
One nit: we don't have a linter in shader code, but it seems like snake_case is prevalent for function names/variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for adding gamma correction on the fog, the greater spread definitely adds to the effect for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@karimnaaji in the black-to-white gradients above, is the top one gamma-incorrect and the bottom gamma-correct? The bottom one looks unreasonably light, on average.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The medium part of second gradient is at (0.73,0.73,0.73) srgb, which is exactly (0.5,0.5,0.5) linear.
I still had the shader around to generate these:
out vec4 out_color;
uniform vec2 resolution;
@color3
uniform vec3 color_1;
@color3
uniform vec3 color_2;
vec3 linear2srgb(vec3 color) {
return pow(color, vec3(1.0 / 2.2));
}
vec3 srgb2linear(vec3 color) {
return pow(color, vec3(2.2));
}
void main() {
vec2 uv = gl_FragCoord.xy / resolution;
if (uv.y >= 0.5) {
out_color = vec4(1.0);
vec3 color = mix(color_1, color_2, uv.x);
out_color = vec4(color, 1.0);
} else {
vec3 color = mix(srgb2linear(color_1), srgb2linear(color_2), uv.x);
out_color = vec4(linear2srgb(color), 1.0);
}
}
The bottom one was was generated with gamma correct mixing between black and white, which is exactly what we do with fog now.
While looking at that I remember comparing the heatmap as well, which is another place we'd benefit from the same process (top is gamma corrected):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bottom one sort of looks like it has a dark ring where the opacity fades. This might be too much of a breaking change, but I do think it is objectively better by a small margin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @rreusser, I like the gamma correction
src/shaders/_prelude.fragment.glsl
Outdated
#endif | ||
} | ||
|
||
vec3 gammaMix(vec3 a, vec3 b, float x) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for adding gamma correction on the fog, the greater spread definitely adds to the effect for me.
|
||
#if defined( FOG ) && !defined( RENDER_TO_TEXTURE ) | ||
out_color = fog_apply(out_color, v_fog_pos); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inlining named chunks via a pragma can be applied here too
691e4da
to
eabc0a3
Compare
@karimnaaji @arindam1993 I've worked through the feedback and made the requested changes, apart from things maybe handled in subsequent work. I checked and ensured that the color picker color (and not some gamma-dependent variant) is what makes it though the mixing function and onto the screen. I haven't added render tests, which I think are best handled later, once we commit to things. I don't currently have other additions. EDIT: Hold on, circles. Sorry, dog is barking, gonna need to handle that in just a few minutes. |
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization
* Add fog stylespec * Add fog type specification * Add fog stylespec validation Lint * Add setFog() and getFog() APIs * Add debug page * Add note to validate fog * Add Fog preludes and inject preprocessor defines when enabled Fix Lint Fix Flow drop: Test Fog define * Inject shader preludes and connect to globally defined fog uniforms Fixup * Apply fog to sky layers Remove unnecessary shader statement * Apply fog to terrain render * Fix fog on sky gradient layers * Apply fog to fill-extrusion layer * Apply fog to fill layer * Apply fog to fill-extrusion-pattern layer Fixup shader statement * Apply fog to fill-outline, fill-outline-pattern, fill-pattern layers * Apply fog to background layer * rename posMatrix to projMatrix * Add cameraMatrix * add separate cameraMatrix * Calculate worldsize for cameraMatrix based on camera distance distance to sealevel Fix flow and lint errors * Simplify shader statement, remove extra division by w u_cam_matrix is not projective and w is always 1 for points * Add fading in of fog around 60 deg pitch Fix lint errors * Improve fog demo example and add GUI controls * Fog tile culling in tile cover Fixup comment * Remove extraneous mult Remove unused * Simplify fog tile culling Fix lint and flow * Apply correct fog+blending in shaders (#10496) * Make an attempt to implement consistent fog logic * Add comments * Apply premultiplied fix across shaders * Clean up gamma correction * Simply GLSL defines and fix shader compile error * Fix syntax error and remove unused gamma correction * Add fog to circles * Apply fog to background pattern and hillshade * Clean up a small shader optimization * Add dithering to fog (#10506) * Add basic dithering to fog * Add temporal offset for fog * Make uniform naming consistent * Code golf the shaders just a little * Separate dithering from fog function * Rework the fog falloff function (#10515) * Rework the fog falloff function * Rework the fog function * Add some spec validation * Support fog on markers (#10516) * Apply fog to Markers * Fix lint flow and cleanup * Fix opacity not updating for terrain and fog after updating the spec properties * Add map.getFogOpacity API * Code style * Evaluate opacity less often * Update per rebased changes * Minor tweak * Update src/style/fog.js Co-authored-by: Ricky Reusser <[email protected]> * Update src/ui/marker.js Co-authored-by: Ricky Reusser <[email protected]> * Update src/ui/map.js Co-authored-by: Ricky Reusser <[email protected]> * Update variable name per review * Fixup invalid commit from github * Address review comments * Update per review Co-authored-by: Ricky Reusser <[email protected]> Fix popup tip not being occluded * Fog-sky blending (#10527) * Improve fog blending * Clean up blending * Remove fog-sky blending fix Fix tests and low * Do not cull tiles crossing over the horizon during fog culling phase This prevents sudden pop in and out for tiles within the fog culling range * Use fog color as default context clear color when enabled This prevents unaffected fragments resulting in empty holes in location where we do not draw fragments * Cull at 80% of the distance between fog start end fog end This leaves a non-noticeable 2% fog opacity change threshold and reduces the distance before we start culling * Add style diffing support and unit tests fog setFog and getFog * Cutoff fog-opacity from the style specification * Fix a bug using stale tile cover result due missing update to fog ranges This issue was visible when updating fog properties and an incorrect tile cover run would potentially leave invalid tiles on the viewport * Switch fog to use window-scaled units (#10533) * Switch fog to use window-scaled units * Update style spec for fog range * Update fog validation tests to match new limits * Update fog validations * Add haziness property to fog (#10537) * Add haziness to fog * Fix flow types * Apply PR feedback * Update marker opacity to use viewport-scaled height (#10542) * Update marker opacity to use viewport-scaled height * add units to variable names to make intent clear * Code cleanup: Simplify getDistanceToSeaLevel + remove extraneous transform variable * Add unit tests for furthestTileCorner * Add unit tests for coveringTiles with fog culling * Add basic symbol clipping when fog opacity is high (#10541) * Rename cameraMatrix --> fogMatrix (#10544) * Offload terrain fog to vertex shader (#10549) * Offload terrain fog to vertex shader * Don't set haze uniforms unless haze is present * Remove haze varying unless haze is used * Disable fog code path on the 2d case * Remove redundant uniforms * Simplify fog render logic Co-authored-by: Karim Naaji <[email protected]> * Add documentation of the public facing fog APIs + revise defaults (#10545) * Add documentation of the public facing APIs * Fixup missing `}` * Update fog range docs * Disable haze by default and fix mixed up haze properties * Update src/style-spec/reference/v8.json Co-authored-by: Ricky Reusser <[email protected]> * Update src/style-spec/reference/v8.json Co-authored-by: Ricky Reusser <[email protected]> * Update src/style-spec/reference/v8.json Co-authored-by: Ricky Reusser <[email protected]> * Update src/style-spec/reference/v8.json Co-authored-by: Ricky Reusser <[email protected]> * Update src/ui/map.js Co-authored-by: Ricky Reusser <[email protected]> Co-authored-by: Ricky Reusser <[email protected]> * Extract getAABBPointSquareDist from fog culling and add unit tests * Use implicit vec3.transformMat4 division by w instead of explicit one * Add fog as part of the release testing * Add fog culling render test * Add sky-blend render tests * Add more style diffing unit tests and coverage around setFog/getFog public APIs * Add unit tests for getFogOpacity * Add basic terrain render tests * Add fog marker occlusion unit tests Remove extraneous note * Add 2D tests for fog (#10566) * Add 2D render tests for fog * Test fog shaders * Swap raster test * Add half float heatmap render test image * Increase test allowance for raster test * Add more fog style spec render test coverage * Fix shader preprocessor define leading to invalid shaders on production build variants (#10582) * Prevent shader stripping issue on production builds Always use same function signature independently of shader variant * Use const for the unused param * Directly use inlined parameter * Fixup * Fix render tests Cannot use const as 'out' or 'inout' parameters. * Fog style spec changes (#10590) * Clean up fog style properties * Present a more reasonable example * Fix fog tests and validations * Improve haze wording * Apply review feedback: getFogOpacity -> queryFogOpacity * Apply review feedback: Keep seperation of DOM-based and non-DOM based map element updates Defer marker opacity update in DOM task queue * Fix fog sky blending (#10578) * Clean up fog sky blending * Add fog sky blending fix to cpu side Fix post rebase flow * Better consistency in naming conventions * Apply review feedback: Remove extraneous function call * Apply review feedback: Rename sky-blend -> horizon-blend * Apply review feedback: Increase range of pitch fading to be less aggressive * Simplify haze evaluation (#10606) * Simplify fog evaluation * Switch to approximate gamma conversion * Factor out haze application * Document the haze_apply function * Remove backticks * Update src/shaders/_prelude_fog.fragment.glsl * Apply review feedback: Consolidate shader code that can be shared in shared prelude * Remove haze (#10613) * Remove haze * Remove density * Catch a couple more small cleanup items * Fix broken shader * Tighten/restore fog culling * Update src/render/painter.js * Revert fog opacity regression from #10578 with CPU side evaluation of horizon blend * Demo: Update default location * Revise comments and cleanup shader code for readability - Also removes extraneous branching with min in fog_apply_premultiplied * Share fog varying globally in new shader prelude * Revise comments and naming * Code cleanup for better readability * Fix validation error on complex style expression of fog color validation * Fix validation error on complex style expression of fog range validation and add validation tests * Simplify fog validation checks for expression(s) * Switch fog from percentage window height to CSS vh units (#10632) * Switch fog from percentage window height to CSS vh units * Fix tests * Fix more tests * Fix still more tests * Update src/style-spec/reference/v8.json * Don't leave alpha of fog color unused (#10633) * Don't leave alpha of fog color unused * Apply review comments: Simplify flow, reduce uniforms * Fix naming * Update docs * Fix flow * Update all render tests to use new units * Fixup consistent naming * Add symbol clipping render test * Sample terrain to estimate de facto camera scale (#10621) * Continuously adjust the fog scale by raycasting * Remove unused function * Fix linter errors * Name thresholds for clarity * Hard-code sampling pattern * Rearrange conditional * Adjust sampling by horizon line * Replace arbitrary constant with epsilon * Remove stray import * Simplify logic * Only calc fog matrices on avg elevation change * Fix cloning of transform * Fix bug in state management * Fix linter errors * Remove debug code * Move samples points inside function * Fix accidental call to calcMatrices * We still love you, flow * Clarify code * Add tests for EasedVariable * Add one more test * Fix default per latest changes and add render tests * Fix alpha composing of horizon blend with sky gradient (#10640) Make sure to un/post multiply alpha before/after applying sky gradient contribution, as color ramps are premultiplied-alpha colors. This prevents washed out colors when using transparency. * Account for FOV in fog (#10629) * Account for FOV in fog * Fix a typo * Fix flow errors * Fix a factor of two to make tests pass * Fix bad merge * Fix tests * Shift fog range zero to the map center * Fix debug * Fix ranges to account for fov * Remove unused variable * Apply review feedback: Directly update marker style opacity * Update per latest discussion: Use nameless units to prevent confusion when trying to reason about them. As the units of the range are representing 3d distances on a sphere centered around camera center point, they can hardly be reasoned about in terms of window height. * Fixup naming consistency * Fix race condition in fog terrain sampling (#10642) * Fix race condition in fog terrain sampling * Use frame start time stamp * Update render test expectation * Remove fog vh units (#10648) * Remove fog vh units * Fix floating point errors in test expectations * Fix geo test * Add fog demo and transition fixes (#10649) * Skip unnecessary uniform code path when terrain is rendering to texture On a typical frame with terrain this was called ~200 times, where only 20 were necessary (~10%) * Fix invalid transition evaluation When `delay` was undefined but not `now`, properties.begin and properties.end were assigned incorrect values, leading to an immediate transition interpolation. This was noticed when testing transitions on fog. * Fix style.hasTransition() when fog is transitioning values * Add a fog demo for release * Directly use DOM queue rencently introduced by #10530 * Apply review feedback: Directly clear the timer here instead of unsetting it * Apply review feedback: Fix nits, mark queryFogOpacity private until we need to expose it publicly * Update src/util/util.js Co-authored-by: Ricky Reusser <[email protected]> * Update src/util/util.js Co-authored-by: Ricky Reusser <[email protected]> * Apply review feedback: Fix nits * Apply review feedback: Simplify matrix initialization * make private methods private for docs Co-authored-by: Arindam Bose <[email protected]> Co-authored-by: Ricky Reusser <[email protected]> Co-authored-by: Ansis Brammanis <[email protected]>
This PR applies fog to most of the shaders (exhaustive list to follow before merging).
To do:
#if defined( FOG ) && !defined( RENDER_TO_TEXTURE )
conditionalNotes/explanations:
fog_apply_premultiplied
function.The conditional
#if defined( FOG ) && !defined( RENDER_TO_TEXTURE )
got the terrain/no-terrain behavior correct (while checking forTERRAIN
did not, for reasons I didn't fully figure out), but it’d be nice if this condition weren’t so verbose since it’s repeated a lotI think the fog depends on the aspect ratio… need to revisit but perhaps outside of this PR
most of the layers (including: heatmap, excluding: symbols and a couple exceptions like circles which I just haven’t addressed yet) work… correctly, I think?? :party-face: Here’s quite a few of them at least…