**2**

# Why normalize it?

###
#1
Members - Reputation: **798**

Posted 08 August 2012 - 03:51 PM

Here's the HLSL code:

[source lang="cpp"]//=============================================================================// lighthelper.fx by Frank Luna © 2008 All Rights Reserved.//// Structures and functions for lighting calculations.//=============================================================================struct Light{ float3 pos; float3 dir; float4 ambient; float4 diffuse; float4 spec; float3 att; float spotPower; float range;};struct SurfaceInfo{ float3 pos; float3 normal; float4 diffuse; float4 spec;};float3 ParallelLight(SurfaceInfo v, Light L, float3 eyePos){ float3 litColor = float3(0.0f, 0.0f, 0.0f); // The light vector aims opposite the direction the light rays travel. float3 lightVec = -L.dir; // Add the ambient term. litColor += v.diffuse * L.ambient; // Add diffuse and specular term, provided the surface is in // the line of site of the light. float diffuseFactor = dot(lightVec, v.normal); [branch] if( diffuseFactor > 0.0f ) { float specPower = max(v.spec.a, 1.0f); float3 toEye = normalize(eyePos - v.pos); float3 R = reflect(-lightVec, v.normal); float specFactor = pow(max(dot(R, toEye), 0.0f), specPower); // diffuse and specular terms litColor += diffuseFactor * v.diffuse * L.diffuse; litColor += specFactor * v.spec * L.spec; } return litColor;}float3 PointLight(SurfaceInfo v, Light L, float3 eyePos){ float3 litColor = float3(0.0f, 0.0f, 0.0f); // The vector from the surface to the light. float3 lightVec = L.pos - v.pos; // The distance from surface to light. float d = length(lightVec); if( d > L.range ) return float3(0.0f, 0.0f, 0.0f); // Normalize the light vector. lightVec /= d; // Add the ambient light term. litColor += v.diffuse * L.ambient; // Add diffuse and specular term, provided the surface is in // the line of site of the light. float diffuseFactor = dot(lightVec, v.normal); [branch] if( diffuseFactor > 0.0f ) { float specPower = max(v.spec.a, 1.0f); float3 toEye = normalize(eyePos - v.pos); float3 R = reflect(-lightVec, v.normal); float specFactor = pow(max(dot(R, toEye), 0.0f), specPower); // diffuse and specular terms litColor += diffuseFactor * v.diffuse * L.diffuse; litColor += specFactor * v.spec * L.spec; } // attenuate return litColor / dot(L.att, float3(1.0f, d, d*d));}float3 Spotlight(SurfaceInfo v, Light L, float3 eyePos){ float3 litColor = PointLight(v, L, eyePos); // The vector from the surface to the light. float3 lightVec = normalize(L.pos - v.pos); float s = pow(max(dot(-lightVec, L.dir), 0.0f), L.spotPower); // Scale color by spotlight factor. return litColor*s;} [/source]

note SurfaceInfo is the vertex that is not getting his color computed

As you can see there are 3 types of light defined above.But to create the spotlight,it creates a pointlight and then it needs to actually make that pointlight a spotlight,the thing is,I don't understand why on this line:

float3 lightVec = normalize(L.pos - v.pos)

it uses normalize?Why use normalize? Wouldn't it be the same thing without normalize?!

###
#3
Members - Reputation: **327**

Posted 08 August 2012 - 04:21 PM

###
#4
Members - Reputation: **751**

Posted 09 August 2012 - 09:54 AM

###
#5
Members - Reputation: **401**

Posted 09 August 2012 - 11:31 AM

Say L.pos = {10, 10, 10} & V.pos = {5, 5, 5}

L.pos - V.pos = {5, 5, 5}

The light vector is a direction, it just points in a certain direction, hence it should have no length, so you normalize it... and it becomes a unit directional vector {1, 1, 1}. Now you can do the dot product for your lighting without it being over scaled.

Further more, the dot product requires both vectors to be unit vectors to acquire the cosine angle between them.

Remember that when you calculate a "directional vector", you will most of the time want it normalized.

For the point light, you can see that it isn't normalized right away since the equation needs the length from the light position to the vector position to validate its range first. If it does pass, it just divides by the distance to normalize. This is done for efficiency reasons since the normalize function would need to recalculate the length of the vector anyways.

Just to be clear: normalized V = V / length(V).

Also, due to interpolation done by the GPU from the vertex shader to pixel shader, you will need to re-normalize your vectors in the pixel shader.

It is rough to get used to the linear algebra required for 3d graphics. But once you understand the general idea of what each function does visually, you won't really need to remember the exact formulas to do what you envision.

Cheers.

**Edited by french_hustler, 09 August 2012 - 11:37 AM.**

###
#7
Members - Reputation: **798**

Posted 09 August 2012 - 12:04 PM

**Edited by noatom, 09 August 2012 - 12:13 PM.**

###
#8
Crossbones+ - Reputation: **3482**

Posted 09 August 2012 - 12:30 PM

float3 lightVec = L.pos - v.pos; // The distance from surface to light. float d = length(lightVec); if( d > L.range ) return float3(0.0f, 0.0f, 0.0f); // Normalize the light vector. lightVec /= d;

lightVec is actually normalised

###
#9
Members - Reputation: **798**

Posted 09 August 2012 - 01:18 PM

Also on ParallelLight too: float diffuseFactor = dot(lightVec, v.normal); as you can see there lightVec is not normalized.

I don't understand....

###
#10
Members - Reputation: **401**

Posted 09 August 2012 - 02:00 PM

and it becomes a unit directional vector {1, 1, 1}

Sorry to be nitpicky but that should be {1/sqrt(3), 1/sqrt(3), 1/sqrt(3)}

What a silly mistake. Thank you for catching that.

Let's write it out so we don't confuse OP.

if V = [5,5,5], its length = sqrt(25+25+25) = sqrt(75)

Normalized(V) = [5/sqrt(75), 5/sqrt(75), 5/sqrt(75)] = [1/sqrt(3), 1/sqrt(3), 1/sqrt(3)]

But at spotlight at the dot product L.dir is not normalized...?! float s = pow(max(dot(-lightVec, L.dir), 0.0f), L.spotPower);

Also on ParallelLight too: float diffuseFactor = dot(lightVec, v.normal); as you can see there lightVec is not normalized.

I don't understand....

L.dir is a member of the light. It is set in the C++ side, and it must be normalized there. So the shader assumes it already is normalized (which it should be anyways).

Again, if you want proper cos angle out the dot product, both vectors must be normalized. In your shader, it is assumed that the light direction is already normalized.

###
#12
Crossbones+ - Reputation: **3482**

Posted 09 August 2012 - 03:07 PM

I'd say if you're confident in programming you will grasp the math pretty easily.

###
#13
Crossbones+ - Reputation: **2399**

Posted 09 August 2012 - 03:41 PM

No, there are plenty of cases where you don't want to normalize a vector used in a dot product. It depends on what you're trying to do. In this case you're interested in the angle between the vectors, the dot product of two normalized vectors gives you the cosine of that angle. So in this case, you want both vectors to be normalized.So the final advice is to normalize every vector that I use in dot product no matter what?

**Edited by Mussi, 09 August 2012 - 03:43 PM.**