Horde3D

Next-Generation Graphics Engine
It is currently 29.03.2024, 11:32

All times are UTC + 1 hour




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: 30.11.2008, 13:47 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
I'm currently attempting to create a more optimal deferred renderer using mostly 8-bit RBGA textures.

I've become stuck trying to reconstruct positions from depth though:
marciano wrote:
As stated in another thread, the deferred shading implementation could quite easily be optimized using 8 bit targets and reconstructing fragment position from depth (google for this).


Has anyone done this before, and could provide me with advice?

I'm using the following modifications to write depth to the G-Buffer:
Code:
      <VertexShader>
...
            varying vec4 vsPos;
            void main( void )
            {
...               
               // Calc eye space pos
               vsPos = calcViewPos( pos );
...
      </VertexShader>
      <FragmentShader>
...
            varying vec4 vsPos;
            void main( void )
            {
...
               setDepth( -vsPos.z / 1000.0 );
            //   setPos( vsPos ); // <-- for debugging
...
      </FragmentShader>
...
...
float getDepth( const vec2 coord )    { return texture2D( tex9,  coord ).a; }
void setDepth( const float depth )    { gl_FragData[1].a   = depth; }


The above code works fine. I'm having trouble in the lighting shader reconstructing a (view space) position from these depth values.

My (attempted, but incorrect) algorithm is to construct a ray that passes through the current pixel, and then scale that ray by the depth value. When I compare my results against the actual view-space position though, my results are slightly wrong.
Code:
               vec4 ray; ray.w = 1.0;
               float fov = radians(45.0);
               float off = 0.5;
               float sca = 2.0;
               vec2 screen = vec2( 640.0, 480.0 );
               float aspect = screen.x / screen.y;
               float farPlane = 1000.0;
               float xratio = gl_FragCoord.x/screen.x;
               float yratio = gl_FragCoord.y/screen.y;
               ray.x = (xratio-off) * sca * sin(fov);
               ray.y = (yratio-off) * sca * sin(fov / aspect);
               ray.z = cos( asin(ray.y) );
               ray *= getDepth(texCoords) * farPlane;
               //   ray.rgb = getPos(texCoords); ray.z = ray.z * -1.0; // <-- for debugging
               gl_FragColor = ray;


Top
 Profile  
Reply with quote  
PostPosted: 30.11.2008, 16:11 
Offline
Engine Developer

Joined: 10.09.2006, 15:52
Posts: 1217
Honestly I have not yet tried it myself but maybe this thread has some helpful information:

http://www.gamedev.net/community/forums/topic.asp?topic_id=506573


Top
 Profile  
Reply with quote  
PostPosted: 30.11.2008, 17:51 
Offline

Joined: 16.01.2008, 00:24
Posts: 73
Location: Canada/Quebec
Ive used this code to get the eye position in one of my project. It is taken from an NVidia example.

Code:

const float fovy               = 40.0 * 3.14159265 / 180.0; // 40 deg in radian
const float invFocalLenX   = tan(fovy * 0.5) * width / height;
const float invFocalLenY   = tan(fovy * 0.5);

vec3 uv_to_eye(vec2 uv, float eye_z)
{
   uv = (uv * vec2(2.0, -2.0) - vec2(1.0, -1.0));
   return vec3(uv * vec2(invFocalLenX, invFocalLenY) * eye_z, eye_z);
}

vec3 fetch_eye_pos(vec2 uv)
{
   float z = texture2D(tex1, uv).a; // Depth/Normal buffer
   return uv_to_eye(uv, z);
}



Top
 Profile  
Reply with quote  
PostPosted: 01.12.2008, 02:49 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
Thanks, that works perfectly.


Top
 Profile  
Reply with quote  
PostPosted: 01.12.2008, 07:45 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
I'm now able to reconstruct world-space positions from the depth data as well, using the following:
Code:
vec4 vsPos = vec4( uv_to_eye( texCoords, depth ), 1.0 );
vec4 wsPos = gl_ModelViewMatrixInverse * vsPos;

But to get this to work, I had to change some C++ code in Renderer::drawFSQuad to make the camera's Model-View-Matrix available to full-screen-quads:
Code:
   glMatrixMode( GL_MODELVIEW );
//   glLoadIdentity(); //I removed this line
   glLoadMatrixf( _curCamera->_invTrans.x );//new code

As far as I know, this change shouldn't break anything, because none of the shaders used on full-screen quads use the Model-View-Matrix at all anyway.

Picture: World-positions reconstructed from depth


Top
 Profile  
Reply with quote  
PostPosted: 06.12.2008, 22:07 
Offline
Engine Developer

Joined: 10.09.2006, 15:52
Posts: 1217
It really makes sense to give access to the camera tranformation for post processing effects. We will add that...


Top
 Profile  
Reply with quote  
PostPosted: 08.03.2010, 13:28 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
I was asked in a PM about my depth-reconstruction code, so I'll post it here.
N.B. there is a hard-coded FOV of 45 degrees in this code -- you will most likely want to change that for a real demo/game ;)
Code:
vec4 floatToRGBA8(const float value)
{
    const vec4 bitSh = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
    const vec4 mask = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
    vec4 res = fract(value * bitSh);//error on ATI here?
    res -= res.xxyz * mask;
    return res;
}
void setDepth( const float depth )
{
   vec4 pAcked = floatToRGBA8( depth / 1000.0 );
   gl_FragData[1] = pAcked;
}
void setPos( const vec3 pos )
{
   float depth = (gl_ModelViewMatrix * vec4(pos,1)).z * -1.0;
   setDepth( depth );
}
Code:
float getFloatFromRGBA8(const vec4 value)
{
    const vec4 bitSh = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0);
    return(dot(value, bitSh));
}
float getDepth( const vec2 coord )
{
   vec4 vec = texture2D( buf1, coord );
   return getFloatFromRGBA8(vec) * 1000.0;
}
vec3 uv_to_eye(vec2 uv, float eye_z)
{
   float fovy = radians(45.0);
   float aspect = frameBufSize.x / frameBufSize.y;
   float invFocalLenX   = tan(fovy * 0.5) * aspect;
   float invFocalLenY   = tan(fovy * 0.5);
   uv = (uv * vec2(2.0, 2.0) - vec2(1.0, 1.0));
   return vec3(uv * vec2(invFocalLenX, invFocalLenY) * eye_z, eye_z);
}
vec3 getPos( const vec2 coord )
{
   float depth = getDepth( coord );
   vec3 pos = uv_to_eye( coord, depth );
   pos.z *= -1.0;
   return (gl_ModelViewMatrixInverse * vec4(pos,1.0)).xyz;
}


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 29 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group