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

Update envmap_fragment.glsl #11508

Merged
merged 1 commit into from
Jun 14, 2017
Merged

Update envmap_fragment.glsl #11508

merged 1 commit into from
Jun 14, 2017

Conversation

NNskelly
Copy link
Contributor

@NNskelly NNskelly commented Jun 14, 2017

Per #11367 (comment)
Equirectangular U sampling update to intuitively equiangular-per-raster sampling.

A quick visual test shows no change from the old version, which worries me a bit, since I'm not getting the trig-on-paper to give identical results. If the math DOES work out provably identically, the original version is certainly more efficient.

Edit: Ok, I'm dumb. Was looking at a straight-up UV-mapped skysphere, not an actual reflection map :-P Change in a proper reflection is subtle, but I think it's there.

Per mrdoob#11367 (comment)
Equirectangular U sampling update to intuitively equiangular-per-raster sampling.

A quick visual test shows no change from the old version, which worries me a bit, since I'm not getting the trig-on-paper to give identical results.  If the math DOES work out provably identically, the original version is certainly more efficient.
@WestLangley
Copy link
Collaborator

WestLangley commented Jun 14, 2017

The current code may be incorrect, but we have to use a formula to decode the map that is consistent with the formula used to encode the map. Do you have a reference and justification for this change?

/ping @MiiBond (original author)
/ping @bhouston
/ping @Mugen87

Also, if this change is correct, you have to at least do this:

sampleUV.y = asin( clamp( flipNormal * reflectVec.y, - 1, 1 ) ) * RECIPROCAL_PI + 0.5;

You can't take the arc-sin of a quantity whose absolute value may exceed 1.

@NNskelly
Copy link
Contributor Author

The current code may be incorrect, but we have to use a formula to decode the map that is consistent with the formula used to encode the map.

Agreed.

Do you have a reference and justification for this change?

I asked the question on the thread cited; @mrdoob asked for a pull request with the change proposal. I do not have any further reference that it is consistent with the intent of the existing codebase, hence the original question.

You can't take the arc-sin of a quantity whose absolute value may exceed 1.

Good catch, although I believe the reflectVec is already normalized, and flipNormal is explicitly defined to +/-1. If protocol is not to assume prior input sanitization may change at a future date, then adding saturate would be appropriate.

@WestLangley
Copy link
Collaborator

I believe the reflectVec is already normalized

Can you show where that is happening?

Roundoff can produce values greater than 1. That is why we clamp prior to calling asin.

@NNskelly
Copy link
Contributor Author

Line 5

vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );

explicitly normalizes cameraToVertex, which is then reflected/refracted about additional vectors to get reflectVec. I'm not working in an IDE that gives me a quick way to call up reflect() or refract(), but I would not expect those to change a vector's length other than, as you note, perhaps through fp rounding error.
That said, on closer inspection, there is an else fallthrough where reflectVec is simply set to vReflect, and I cannot in fact cite that vReflect is explicitly arriving normalized.

The only place a quick find-in search of the shaders directory is showing vReflect being assigned to is envmap_vertex.glsl, where all paths likewise generate vReflect by reflecting/refracting the normalized cameraToVertex from line 9

vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );

but I suppose that doesn't cover all possible places where the envmap chunk may be subsequently included.

I'm not against adding the saturate if the line is otherwise correct; or it may still be a moot point if the original design intent was for images that were angular-sampled on x but linear-sampled on y.

Wolfram looks like it has less information than Wikipedia on what constitutes a "proper" equirectangular projection, but if Wikipedia is right in that the y sampling is literally (phi - phi_1) where phi is an angular degrees latitude, I would think that each raster of the map would correspond to an angular wedge of the vertical arc, and thus be more accurately sampled based on the vertical angle of the reflection vector rather than simply the vertical component of the vector (which, at least by my intuition, would vertically squish data near the poles and stretch data near the equator).
https://en.wikipedia.org/wiki/Equirectangular_projection

@WestLangley
Copy link
Collaborator

which, at least by my intuition, would vertically squish data near the poles and stretch data near the equator

That is exactly why I think the current code is incorrect and your proposal makes sense.

@mrdoob mrdoob merged commit e60ad0b into mrdoob:dev Jun 14, 2017
@mrdoob
Copy link
Owner

mrdoob commented Jun 14, 2017

Yep. I confirm the previous code was incorrect.

Before:
screen shot 2017-06-14 at 11 13 31 am

After:
screen shot 2017-06-14 at 11 13 48 am

@mrdoob
Copy link
Owner

mrdoob commented Jun 14, 2017

Thanks!

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.

3 participants