View Full Version : A 3d math question for you gurus.
Backov
05-08-2007, 06:56 PM
I am stuck. It's annoying not having the math to figure this crap out on your own.
Anyway, I have the screen position of a pixel (from -1,-1 to +1,+1) and the Z position (depth) of that pixel in world space.
I need to be able to take that data, plus any relevant camera matrices, and recreate the world position of that pixel in my pixel shader. I know it can be done, because it's the way the pros do it - I just can't find the part where they explain how they do it. :)
I've gotten to the point where I have a ray vector from the screen position, but not past that - anyone have the math chops to help me out?
Spaceman Spiff
05-08-2007, 07:57 PM
Backov,
Are you doing deferred shading?
andrew
05-08-2007, 08:24 PM
What do you mean "recreate the world position of that pixel"? If you're shading a pixel in a pixel shader, you already have the pixel's position -- because that's the input to the shader program.
A 2D screen pixel is essentially a ray in 3D. The ray start is your 3D camera position, and the ray passes through a point on the near plane which corresponds to the screen (X,Y) coordinate. The 3D coordinate of that near plane point depends on your resolution, camera FOV, and camera transform. Then you just use that ray direction to project forward "Z" distance (where Z is your z-depth based on your buffer). You do have to take into account your znear and zfar settings, the bit-depth of your z-buffer, how it's set up in the projection matrix, etc. In general it's a lot of math, are you sure there's not some other way you can't approach it? (Such as doing a ray-collide with your geometry?)
Backov
05-08-2007, 08:47 PM
Backov,
Are you doing deferred shading?
I sure am. It works great, but I'm trying to eliminate a GBuffer by not storing the position and just recreating it from the depth buffer/screen position, etc..
Backov
05-08-2007, 08:47 PM
What do you mean "recreate the world position of that pixel"? If you're shading a pixel in a pixel shader, you already have the pixel's position -- because that's the input to the shader program.
A 2D screen pixel is essentially a ray in 3D. The ray start is your 3D camera position, and the ray passes through a point on the near plane which corresponds to the screen (X,Y) coordinate. The 3D coordinate of that near plane point depends on your resolution, camera FOV, and camera transform. Then you just use that ray direction to project forward "Z" distance (where Z is your z-depth based on your buffer). You do have to take into account your znear and zfar settings, the bit-depth of your z-buffer, how it's set up in the projection matrix, etc. In general it's a lot of math, are you sure there's not some other way you can't approach it? (Such as doing a ray-collide with your geometry?)
Unfortunately no - it's an optimization for deferred shading.. The previous way to do it is store a big fat GBuffer with the position data in it, but it's not necessary..
Bad Sector
05-08-2007, 08:57 PM
You have to reverse the projection. You have:
screen_pixel_X
screen_pixel_Y
world_pixel_Z (depth)
and you need
world_pixel_X
world_pixel_Y
remember that the projection is actually
screen_pixel_X = world_pixel_X/world_pixel_Z
screen_pixel_Y = world_pixel_Y/world_pixel_Z
so the reverse is just
world_pixel_X = screen_pixel_X * world_pixel_Z
world_pixel_Y = screen_pixel_Y * world_pixel_Z
Your projection matrix may be a bit different, so you need to apply the inverse of the projection matrix (it's available in your pixel shader i think - at least in GLSL) to the vector V(screen_pixel_X, screen_pixel_Y, 1) and then put V.z = world_pixel_Z. Or something like that... i have to try it in code to be sure, but it's something along these lines :-).
Spaceman Spiff
05-08-2007, 10:24 PM
If someone here doesn't answer, I'll look up some of my old code. (Dang my mind is going - I spoke at GDC about deferred shading while in the midst of developing an engine that used it and today I can't recall the specifics to save my life).
One thing I remember being a big problem was precision on pre-shader 3.0 cards. On the ATI 3xx chips (Radeon 9500+, pixel shader 2.0b) the FP registers only had 24-bit internal precision instead of 32. After transforms and taking a necessary reciprocal (which I believe also sacrificed precision for speed) to recover the screen space position (whth Shader 3.0 we just use the oPos register), the precision losses meant we could be off our X,Y target by up to 2 pixels. Something to watch out for on older cards.
Backov
05-08-2007, 10:29 PM
If someone here doesn't answer, I'll look up some of my old code. (Dang my mind is going - I spoke at GDC about deferred shading while in the midst of developing an engine that used it and today I can't recall the specifics to save my life).
One thing I remember being a big problem was precision on pre-shader 3.0 cards. On the ATI 3xx chips (Radeon 9500+, pixel shader 2.0b) the FP registers only had 24-bit internal precision instead of 32. After transforms and taking a necessary reciprocal (which I believe also sacrificed precision for speed) to recover the screen space position (whth Shader 3.0 we just use the oPos register), the precision losses meant we could be off our X,Y target by up to 2 pixels. Something to watch out for on older cards.
Good to know. I have no idea what my eventual target with this is going to be, probably just high end PCs and the 360, but definitely good to know.
I didn't want to start with any SM3 stuff because I know this can work without and I wanted to get it going that way first. I've got ShaderX3 sitting here and it describes a PS3 deferred shading model, but one of the requirements is "We assume you already have your PS2 deferred shading model working".. So, I'm at that part of it still. :)
Bad Sector
05-08-2007, 10:30 PM
IMHO, it makes no sense to use deferred shading in older (pre GeForce6 era - such as mine :-/) cards. They are way too inaccurate and slow for that. Well generally deferred shading is a can of worms by itself...
Backov
05-09-2007, 09:47 AM
I really need to read my "3d math primer..." cover to cover.
Ok, so I have two ways that I can try to do this - Bad Sectors way, which involves using the inverse projection matrix. Now here comes my confusion - Is it the inverse projection matrix, the inverse viewprojection matrix, or the inverse worldviewprojection matrix - I've now seen all 3, in Unproject parameters as well as suggestions here.
I have another bit of code that does some funky stuff directly with the inverseViewWorld matrix and produces a ray - the start point and vector.. Now normally that would be great, but since I only know one coord, I don't think I can get the other two without walking down the vector, and I don't want to do that in a shader. Or at all really.
So, I guess it comes to this - Spiff, if you can dig up that code, would you please? :)
Cheers,
Jason
vBulletin v3.6.0, Copyright ©2000-2009, Jelsoft Enterprises Ltd.