greggman / twgl.js

A Tiny WebGL helper Library
http://twgljs.org
MIT License
2.67k stars 260 forks source link

Getting world space from screen space. #147

Closed baturinsky closed 4 years ago

baturinsky commented 4 years ago

It's not exactly a TWGL issue, but... I'm trying to implement deferred shading with TWGL, everything works more or less than expecting, but I got weird result when converting from screen space.

I use this formula:

u_InverseWorldViewProjection * vec4(v_texCoord*2. - 1., depth.r * 2. - 1., 1.)

Here v_texCoord is texture coordinate on gFrame and depth is a DEPTH24_STENCIL8 texture. u_InverseWorldViewProjection is m4.inverse of the view projection matrix.

Result (can be seen on https://vvv-js.netlify.com , source at https://github.com/baturinsky/vvv-js) is somewhat weird. Looks like some mix of world space and screen space, and is in [0.,1.] range, instead of ~[-150, 150] range like world is.

Btw, would be great if there were example of deferred shading among other TWGL examples. Maybe with some effects, like SSAO or screen space reflection.

baturinsky commented 4 years ago

I finally figured the issue. I should have divide that vector by it's w component afterwards. I.e. vec4 p1 = vec4(v_texCoord*2. - 1., depth.r*2. -1., 1.); vec4 p2 = u_InverseWorldViewProjection * p1; p2 = p2 / p2.w;

greggman commented 4 years ago

Sorry I wasn't helpful. I was going to suggest doing the math in JavaScript and plugging in easy values for depth.z (0, 1)

Glad you found the issue

baturinsky commented 4 years ago

From the end of this article http://www.codinglabs.net/article_world_view_projection_matrix.aspx :

"GPU takes care of dividing by w, clipping those vertices outside the cuboid area, flattening the image dropping the z component, re-mapping everything from the -1 to 1 range into the 0 to 1 range and then scale it to the viewport width and height"

So, basically other than multiplying u_InverseWorldViewProjection, everything in above formula is undoing what WebGL is doing "stealthily"

greggman commented 4 years ago

Yea, this article also covers that.

My point is when debugging math sometimes doing it manually can help verify your math. You know that a depth of 0 should produce z = -zNear and a depth of 1 should produce a z = -zFar so you can plugin all the math you're doing and check you get the correct values.

Regardless of what you're doing it's one way to check for math sanity when. Figure out the easy cases and test them.