• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
noatom

Why normalize it?

12 posts in this topic

Ok,I'm rereading the Introduction to 3D Game Programming with Dx10,and I'm at the Lightning chapter.

Here's the HLSL code:

[source lang="cpp"]//=============================================================================
// lighthelper.fx by Frank Luna (C) 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?!
0

Share this post


Link to post
Share on other sites
My bet is that they normalise it so that the dot product in the next line isn't unnecessarily scaled.
0

Share this post


Link to post
Share on other sites
From the mathematical point of view it is not the same. L.pos - v.pos is calculating the vector from v.pos to L.pos so you end up with a vector which has a length that is the distance between those two points. Normalizing it brings it to the length of one. So as jeffery said the dotproduct in the spotlight factor will be scaled and will have a different value.
1

Share this post


Link to post
Share on other sites
When you normalize the light vector and dot it with the surface normal of a poly, you get the angle of between the light and surface which determines the intensity of the light. If the light vector wasn't unit length, you'd the the light vector projected along the surface normal, which isn't the same.
2

Share this post


Link to post
Share on other sites
People above pretty much nailed it.

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
0

Share this post


Link to post
Share on other sites
[quote name='french_hustler' timestamp='1344533495' post='4967851']
and it becomes a unit directional vector {1, 1, 1}
[/quote]

Sorry to be nitpicky but that should be {1/sqrt(3), 1/sqrt(3), 1/sqrt(3)} [img]http://public.gamedev.net//public/style_emoticons/default/wink.png[/img]
1

Share this post


Link to post
Share on other sites
One last question,is it needed that at least 1 vectorin the dot product is normalized? If you look above in the sourcecode you will see that in every dot product there is one simple vector and a normalized one. Edited by noatom
0

Share this post


Link to post
Share on other sites
Not just one but every vector. If you look closely you will see that
[code]
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;
[/code]

lightVec is actually normalised
1

Share this post


Link to post
Share on other sites
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....
0

Share this post


Link to post
Share on other sites
[quote name='Madhed' timestamp='1344535321' post='4967862']
[quote name='french_hustler' timestamp='1344533495' post='4967851']
and it becomes a unit directional vector {1, 1, 1}
[/quote]

Sorry to be nitpicky but that should be {1/sqrt(3), 1/sqrt(3), 1/sqrt(3)} [img]http://public.gamedev.net//public/style_emoticons/default/wink.png[/img]
[/quote]

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)]

[quote]
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....
[/quote]

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.
1

Share this post


Link to post
Share on other sites
So the final advice is to normalize every vector that I use in dot product no matter what?
0

Share this post


Link to post
Share on other sites
I'm sorry to say, but you will need to learn at least the basics of linear algebra to understand what's going on there in the pixel shader. On the other hand it's not that complicated.
I'd say if you're confident in programming you will grasp the math pretty easily.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0