Skip to content
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

FOG_EXP2: Avoid possible over-/underflow when squaring on mediump #17324

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

EliasHasle
Copy link
Contributor

No description provided.

@EliasHasle
Copy link
Contributor Author

EliasHasle commented Aug 23, 2019

Context: 69a8d3b#diff-70001492be345858ece4ba692249de2c

Before that commit, there was independent potential for overflow and underflow.

Using the/a square function would improve readability and likely not affect performance. Should I modify to square( fogDensity * fogDepth )? Edit: No, apparently square is not defined anywhere. (and pow is implemented differently and not defined for non-positive x, according to this source: https://community.khronos.org/t/pow-x-2-different-then-x-x/70839)

Hm, I believe reintroducing square will also be useful, but always make sure to chain multiplications before squareing.

@WestLangley
Copy link
Collaborator

Why not write it like so?

float fogFactor = 1.0 - exp( - pow2( fogDensity * fogDepth ) );

@EliasHasle
Copy link
Contributor Author

EliasHasle commented Aug 24, 2019

@WestLangley Quoting https://community.khronos.org/t/pow-x-2-different-then-x-x/70839 (which refers to the docs)

it is implemented as:
pow(x,y) = exp2 (y * log2 (x))

Would you want to replace all squares with this? log2(x) will fail for non-positive x, and exp and log are more demanding to calculate than simple multiplications, right? pow is made to be general, but for squaring, only multiplication is needed.

@EliasHasle
Copy link
Contributor Author

EliasHasle commented Aug 25, 2019

More support for my PR:
https://docs.nvidia.com/drive/nvvib_docs/NVIDIA%20DRIVE%20Linux%20SDK%20Development%20Guide/baggage/GLSL_ES_Specification_3.00.4.pdf states that the operators are, as expected, left-associative.

Here are descriptions (non-official source) of float precisions and a mention of the problem that @WestLangley tackles with #17323 : http://asawicki.info/news_1596_watch_out_for_reduced_precision_normalizelength_in_opengl_es.html

Now consider the task of multiplying small,small,big,big in some order. If any part of the calculation fails, the whole calculation fails. small*small can cause underflow when the scale of the product is too small to be represented by the exponent bits. big*big can cause overflow if the scale of the product is too large to be represented by the exponent bits. small*big (or big*small) gives the best chance of avoiding extremes on the exponent bits. And the other two multiplicands can be grouped the same way without introducing more risks of overflow. Eventually (small*big)*(small*big) must be evaluated, and this will eventually work in many cases where (small*small)*(big*big) would fail.

But it is not exactly elegant to write out all squares as products where all factors are repeated. This would be more elegant:

float xy = x*y;
float xysq = xy*xy;

And this would be more elegant, and be about as easy for the compiler to optimize:

//In common lib:
float square(float x) {
    return x*x;
}

//In shader:
float xysq = square(x*y);

Apparently, square was defined as a macro earlier, and removed by the same commit that made the underflow-unsafe expression for the fog: 69a8d3b

I believe a function is much better than a macro for this, because a macro will expand the argument and evaluate it two times, whereas a function will evaluate the argument and then square only the result.

I am beginning to feel that I should include a new square function and use it in this PR. Is that OK @mrdoob ?

@WestLangley
Copy link
Collaborator

#17324 (comment).

@EliasHasle
Copy link
Contributor Author

I answered that above.pow(x,2) is less readable than square(x), and the pow function is more general (less optimizable at compile time), yet does not support non-positive x.

@WestLangley
Copy link
Collaborator

https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/common.glsl.js#L13

@@ -3,7 +3,7 @@ export default /* glsl */`

#ifdef FOG_EXP2

float fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );
float fogFactor = 1.0 - exp( - pow2( fogDensity * fogDepth) );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

float fogFactor = 1.0 - exp( - pow2( fogDensity * fogDepth ) );

For clarity, can you please fix the formatting and squash the commits?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have fixed the formatting, but don't know how to squash the commits. I made the edit in the online editor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I failed to squash the commits, but achieved the intended outcome by using the sledgehammer of force-push. 😨 Looks right, although the "Thank you, @WestLangley!" disappeared. Thanks, anyway. 😄

EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Aug 26, 2019
Also correct TS docstring and misspelled name in test file for FogExp2. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Aug 26, 2019
Also correct TS docstring and misspelled name in test file for FogExp2. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Aug 26, 2019
Also correct TS docstring and misspelled name in test file for FogExp2, and doc for standard Fog. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Aug 26, 2019
Also correct TS docstring and misspelled name in test file for FogExp2, and doc for standard Fog. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.
@EliasHasle
Copy link
Contributor Author

EliasHasle commented Aug 26, 2019

Abandoning in favor of #17355. EDIT: Or not.

@EliasHasle EliasHasle closed this Aug 26, 2019
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Aug 27, 2019
Also correct TS docstring and misspelled name in test file for FogExp2, and doc for standard Fog. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Also correct TS docstring and misspelled name in test file for FogExp2, and doc for standard Fog. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
author Elias Hasle <elias.hasle@gmail.com> 1566822048 +0200
committer Elias Hasle <elias.hasle@gmail.com> 1569597690 +0200

RangeFog(color, near, far) and DensityFog(color, density, squared)

Added fog types example.
Currently includes some extra examples that show functionality of legacy signatures, and mediump and lowp operation for all fog types.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fix legacy example and mediump example

Attempted fixes for editor
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.
Currently includes some extra examples that show functionality of legacy signatures, and mediump and lowp operation for all fog types.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fix legacy example and mediump example

Attempted fixes for editor

Formatting + typos
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.
Currently includes some extra examples that show functionality of legacy signatures, and mediump and lowp operation for all fog types.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fix legacy example and mediump example

Attempted fixes for editor

Formatting + typos
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.
Currently includes some extra examples that show functionality of legacy signatures, and mediump and lowp operation for all fog types.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fix legacy example and mediump example

Attempted fixes for editor

Formatting + typos
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.
Currently includes some extra examples that show functionality of legacy signatures, and mediump and lowp operation for all fog types.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fix legacy example and mediump example

Attempted fixes for editor

Formatting + typos

Fixed TS declarations (Not sure I am using IFog right)
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.
Currently includes some extra examples that show functionality of legacy signatures, and mediump and lowp operation for all fog types.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fix legacy example and mediump example

Attempted fixes for editor

Formatting + typos

Fixed TS declarations (Not sure I am using IFog right)

Fixed support for scene.fog=null
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fixed support for scene.fog=null

Fixed TS declarations

New best guess is `fog: IFog | null`
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Sep 27, 2019
Added fog types example.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fixed support for scene.fog=null

Fixed TS declarations

New best guess is `fog: IFog | null`
@EliasHasle EliasHasle deleted the patch-16 branch September 27, 2019 23:33
EliasHasle added a commit to EliasHasle/three.js that referenced this pull request Jan 3, 2020
Added fog types example.

Includes the change to distance-based depth, as well as corrections to better support mediump. Makes mrdoob#17316 and mrdoob#17324 obsolete.

Force update when squared is changed.

Fixed support for scene.fog=null

Fixed TS declarations

New best guess is `fog: IFog | null`
@EliasHasle EliasHasle restored the patch-16 branch March 24, 2023 09:42
@EliasHasle
Copy link
Contributor Author

EliasHasle commented Mar 24, 2023

I would like to reopen this, since it has merit on its own, as described in the discussion above. The large, neglected and currently outdated #17592 should not be holding back a bug fix.

I should add that this is now more properly called a Draft PR, since the newest version is completely untested. It theoretically prevents some overflow/underflow situations that may arise with mediump.

@EliasHasle EliasHasle reopened this Mar 24, 2023
@github-actions
Copy link

github-actions bot commented Mar 24, 2023

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize Gzipped Diff from dev
617.5 kB 154.5 kB -17 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Filesize Gzipped Diff from dev
409.2 kB 100.6 kB -17 B

@EliasHasle EliasHasle marked this pull request as draft March 27, 2023 10:27
EliasHasle referenced this pull request Mar 27, 2023
…5498)

* Nodes: Rework ShaderNodeElements and make some other refactorings

* Fixes

* fix add assign

* Fix circular dependency and clean up

* Rename addNode -> addNodeElement and LightsNode.setReference -> addLightNode, add addNodeClass and addNodeMaterial

---------

Co-authored-by: sunag <sunagbrasil@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants