Jump to content
  • Advertisement
Sign in to follow this  
lipsryme

Lighting Calculation in View Space

This topic is 2310 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

I just can't get my head around this lighting in view space. Can someone explain how this works in comparison to world space calculation ?
Because it doesn't work at all for me. A simple multiplication with the inverseView Matrix doesn't seem to do the trick of transforming my position back to world space.
I'm storing my depth and normals in view space.

Depth is stored like this:
output.Depth = length(input.Depth.z) / farClip;

And my lighting calculation looks like this:
// Get Depth
float Depth = tex2D(DepthBuffer, input.UV).r;
float3 viewRay = input.vPosition.xyz;
float3 PositionVS;
PositionVS = viewRay * Depth;

// Calculate Phong Shader
output = Phong_DirectionalLight(PositionVS.xyz, normal,
specularMaterial);

Share this post


Link to post
Share on other sites
Advertisement

A simple multiplication with the inverseView Matrix

You should keep all your calculations in view space and avoid transforming them back into world space. The problem is, that your inverse view matrix will transform into object and not world space.

The standard view matrix is V= invC * M
with invC = inverse camera matrix and M = model matrix.
The model matrix alone transforms your model from object space into world space. So, to get a vector from view space into world space you need to apply the camera matrix alone, but this matrix is not available out of the box, you need to upload it yourself to your shader.

Share this post


Link to post
Share on other sites
Can you show us how [font=courier new,courier,monospace]Phong_DirectionalLight[/font] works? Is your light direction also in view-space?
Also, how are you transforming your normals into view space?
[font=courier new,courier,monospace]length(input.Depth.z)[/font] looks fishy - why are you calculating the length of a 1D variable?

The standard view matrix is V= invC * M
with invC = inverse camera matrix and M = model matrix.
The view matrix is simply the inverse camera matrix by itself.
The "world view" matrix is the inverse-camera and model/world matrix multiplied together.

Share this post


Link to post
Share on other sites
Isn't the Camera Matrix the same as the View Matrix ?

I transform the normal in the GBuffer pass by the WorldViewInverseTranspose.
I guess the length is unnecessary but the rest should be fine right(?), with input.Depth.z being (-viewPosition.z) passed to the PS.
What do you mean by light direction in view space ? Do I need to multiply that normalized Vector with the View Matrix ?

The DirectionalPhong looks like this (updated):

PSO_Lighting Phong_DirectionalLight(float3 Position, float3 L, float3 N, SpecularMaterial material)
{
PSO_Lighting output = (PSO_Lighting)0;
float3 V = LightDir - Position;

//Calculate N.L
float NL = dot(N, L);

//Calculate Diffuse
float3 Diffuse = LightColor.xyz * LightIntensity;
// Specular Color
float3 SpecColor;
// If the Specular Color is the same as the Light, use the Lights Color
if(Diffuse.r == material.SpecularColor.r &&
Diffuse.g == material.SpecularColor.g &&
Diffuse.b == material.SpecularColor.b)
{
SpecColor = Diffuse;
}
else
{
// If both Light and Material Color is different then combine them
SpecColor = (Diffuse + material.SpecularColor) / 2;
}
//Calculate Reflection vector
float3 R = normalize(reflect(-L, N));
// Calculate R dot V
float RV = pow(saturate(dot(R, V)), material.SpecularPower);

output.Lighting = float4(NL * Diffuse.r,
NL * Diffuse.g,
NL * Diffuse.b,
1);



output.Specular = float4(RV * NL * SpecColor.r,
RV * NL * SpecColor.g,
RV * NL * SpecColor.b,
1);

return output;
}

Share this post


Link to post
Share on other sites
So from the most recent code I've got there, the Light itself seems to work I guess (I still don't get why (0, 1, 0) shines from top to down, every other direction works and my camera is looking up (0, 1, 0) and towards positive Z) but I've been having problems with the reflection. In the way I've set up V = LightDir - ViewPosition the reflection stays still no matter the view angle which is wrong, right ?

Share this post


Link to post
Share on other sites
Alright so, still hoping I'm not doing a monologue here ;) the Light definitely works now (N.L Term), meaning the Normals are 100% correct. But the Specular unfortunately not.
I wrote a simple forward renderer to try out my Phong shader and there everything works just fine (completly in view space).
It seems the only problem I've got now is correctly reconstructing the View Space Position from Linear ViewSpace Depth.
viewRay * Depth does not work for me. Assuming the Depth is correct (which I think it is) the viewRay itself has to be wrong.
I haven't tried calculating it with FrustumCorners yet but MJP's solution says I can just pass in the viewPosition from the VertexShader in my FullscreenQuad pass like this:
float4 viewPosition = mul(input.Position, inverseProjection);

What am I doing wrong ? I've been at this for weeks now with no resolution :(

Share this post


Link to post
Share on other sites
Ok finally "some" good news. I've got it working with both Phong/Blinn-Phong now.
The problem was that I had to normalize a lot of the vectors for it to work (kinda stupid but that was the problem).
Anyway here's the code for the Directional Light with Blinn-Phong (+ energy conserving):
PSO_Lighting BlinnPhong_DirectionalLight(float3 Position, float3 L, float3 N, SpecularMaterial material)
{
PSO_Lighting output = (PSO_Lighting)0;

// Transform LightDirection to View Space
L = normalize(mul(normalize(L), View));
//Calculate N.L
float NL = saturate(dot(N, -L));
//Calculate Diffuse
float3 Diffuse = LightColor.xyz * LightIntensity;
// Specular Color
float3 SpecColor;
// If the Specular Color is the same as the Light, use the Lights Color
if(Diffuse.r == material.SpecularColor.r &&
Diffuse.g == material.SpecularColor.g &&
Diffuse.b == material.SpecularColor.b)
{
SpecColor = Diffuse;
}
else
{
// If both Light and Material Color is different then combine and average them
SpecColor = (Diffuse + material.SpecularColor) / 2;
}
// Normalized View Direction
float3 V = normalize(normalize(mul(CameraPosition, View)) - normalize(Position));
// Calculate Half-Vector
float3 H = normalize(V - L);
// Calculate Normalization Factor for Energy Conserving BRDF
float NormalizationFactor = (material.SpecularPower + 8) / (8 * 3.14159265);
// Calculate N dot H
float NH = pow(saturate(dot(N, H)), material.SpecularPower * specularBias);

output.Lighting = float4(NL * Diffuse.r,
NL * Diffuse.g,
NL * Diffuse.b,
1);

output.Specular = float4(NL * NH * NormalizationFactor * SpecColor.r,
NL * NH * NormalizationFactor * SpecColor.g,
NL * NH * NormalizationFactor * SpecColor.b,
1);

return output;
}


What's left now is to get it working with point light geometry, can anyone see a flaw in this solution ? :
PSO_Lighting BlinnPhong_PointLight(float3 Position, float3 L, float3 N, SpecularMaterial material)
{
PSO_Lighting output = (PSO_Lighting)0;
L = mul(L, View);
// Calculate Attenuation
float Attenuation = saturate(1.0f - max(.01f, length(L)) / (LightRadius / 2));

L = normalize(L);
// Transform LightDirection to View Space
L = L - normalize(Position);

//Calculate N.L
float NL = saturate(dot(N, -L));
//Calculate Diffuse
float3 Diffuse = LightColor.xyz * LightIntensity;
// Specular Color
float3 SpecColor;
// If the Specular Color is the same as the Light, use the Lights Color
if(Diffuse.r == material.SpecularColor.r &&
Diffuse.g == material.SpecularColor.g &&
Diffuse.b == material.SpecularColor.b)
{
SpecColor = Diffuse;
}
else
{
// If both Light and Material Color is different then combine and average them
SpecColor = (Diffuse + material.SpecularColor) / 2;
}
// Normalized View Direction
float3 V = normalize(normalize(mul(CameraPosition, View)) - normalize(Position));
// Calculate Half-Vector
float3 H = normalize(V - normalize(L));
// Calculate Normalization Factor for Energy Conserving BRDF
float NormalizationFactor = (material.SpecularPower + 8) / (8 * 3.14159265);
// Calculate N dot H
float NH = pow(saturate(dot(N, H)), material.SpecularPower * specularBias);
output.Lighting = float4(NL * Diffuse.r * Attenuation,
NL * Diffuse.g * Attenuation,
NL * Diffuse.b * Attenuation,
1);

output.Specular = float4(NL * NH * NormalizationFactor * SpecColor.r,
NL * NH * NormalizationFactor * SpecColor.g,
NL * NH * NormalizationFactor * SpecColor.b,
1);

return output;
}


Position = straight ViewPosition output of point light geometry from the VS

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!