Jump to content
  • Advertisement
Sign in to follow this  
Nairou

Reconstructing view-space position using light volumes (deferred shading)

This topic is 2564 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My first attempt at deferred shading was only partially successful. It appeared correct if the game window was square, but distorted otherwise. I eventually found that this was due to my lighting position calculations being done in projection (clip) space rather than view space. Since then, I've been trying to start over and "re-learn" how to do the calculations properly in view space. I've been reading many forum posts over the last few days (such as this one by MJP, as well as his blog posts), and a lot of them talk about using the view frustum corners to calculate the view space position of the sample.

However, these methods all assume that you are rendering the final output using a fullscreen quad. But I am instead using a light volume (sphere geometry surrounding the light position), and only drawing on the screen where the light volume is visible. Originally, I used gl_FragCoord to determine the screen position in order to sample from the G-buffer textures, since I was working in clip space. However, I'm uncertain how to determine the sample position in view space instead. Given that the illuminated area is defined by a light volume, and not just an arbitrary point on a quad, I would think there would be a way to determine the position using the light volume's position (or the position of the triangle on the light volume that covered the current sample), however I'm having trouble making the leap to actually determine the math to pull it off.

I know there are others doing deferred shading using light volumes instead of fullscreen quads. How did you do it? Any references or examples would be great. :)

Share this post


Link to post
Share on other sites
Advertisement
I'm using the unprojecting technique where you build a projected position from clip space position and then multiply by the projection inverse matrix to go to world space. This might be a bit more expensive than the view space rays on which you can interpolate but suits me better for now as i allready got all the data i need to provide for this so it is easier to play around with for someone who is new to deferred.

Here's the shader i'm using while rendering my point light's spheres, it probably contains some redundant calculations and things that can be done easier / faster but it should be easy to understand:
[source]

Shader LPPPoint
{
Properties
{
Matrix WorldViewProj
Matrix ProjInverse
Vec3 LightPosition
Vec3 LightColor
Vec3 LightDistances

Texture Texture0 : NORMAL
Texture Texture1 : DEPTH
}
Pass p0 : UNLIT
{
VertexShader
{
#version 110
uniform mat4 WorldViewProj;
varying vec3 projectedPos;
void main()
{
gl_Position = WorldViewProj * gl_Vertex;
projectedPos = gl_Position.xyw;
}
}
FragmentShader
{
#version 110
uniform sampler2D Texture0;//normal
uniform sampler2D Texture1;//depth
uniform mat4 ProjInverse;
varying vec3 projectedPos;

uniform vec3 LightPosition;
uniform vec3 LightColor;
uniform vec3 LightDistances;

void main()
{
vec2 clipPos = ( projectedPos.xy / projectedPos.z ) / 2.0 + 0.5;
float depth = texture2D( Texture1, clipPos ).r;
depth = 2 * depth - 1;
vec3 normal = (texture2D( Texture0, clipPos ).rgb - 0.5)*2;

vec4 posProj = vec4( 1.0 );
posProj.x = clipPos.x * 2 - 1;
posProj.y = clipPos.y * 2 - 1;
posProj.z = depth;

vec4 posVS4d = ProjInverse * posProj;
vec3 posVS3d = posVS4d.xyz / posVS4d.w;
vec3 toLight = normalize( LightPosition - posVS3d );
float lit = max( 0.0, dot( toLight, normal ) );

float range = distance( LightPosition, posVS3d ) - LightDistances.x;
//We need the light falloff range (1 / (maxDistance - minDistance)) to calculate
//where we are in this range, this calculation is done on the cpu and provided
//trough the z channel.
float atten = clamp( 1 - LightDistances.z * range, 0.0, 1.0 );
lit *= atten;
gl_FragData[ 0 ] = vec4( LightColor * lit, 1.0 );
}
}
}
}
[/source]

I actually dont got a deferred spot light shader yet but i'm sure it can be mutated from this easilly.

p.s. this is light prepass rendering, almost the same, i'm sure you can add whatever you need to make it work in your implementation. If not dont hesistate to ask.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!