Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Etwinox

OpenGL OpenGL Lighting problems

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

Can somebody tell me how to specify the normal for each vertex? The book I have tells me how to get just the one normal (giving me flat shaded polygons. :<) Also, anybody know how to gourand shade polygons using materials? Please keep in mind that I''m real new to OpenGL... Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Specifing a normal for each vertex is easy - just call glNormalxxx() before each glVertexxxx(). Later, when you get better with using OpenGL, you''ll start using vertex arrays, but for learning purposes, you''ll probably eventually wrap every vertex with:
glNormal();
glTexCoords();
glVertex();

Share this post


Link to post
Share on other sites
Uhh, I''m not trying to be ungrateful but...

How do I "get" the normal for each vertex...that OpenGL book I got only shows how to get the one normal and then it cheats on the rest of the examples and uses aux functions and therefor not telling me how to get them...

Share this post


Link to post
Share on other sites
Well, you calculate it based on the object you''re trying to render.

If it''s a sphere, the normal is a vector pointing directly away from the center of the sphere.

If it''s a terrain or flatish polygonal model, people generally average the face normals of all the faces which share the vertex.

If you''re drawing some kind of mathematically defined surface, you can figure out the normal based on the derivative of the surface''s equation.

Share this post


Link to post
Share on other sites
Oh, and don't forget about glShadeModel();

It accepts one of 2 parameters:
GL_FLAT for flat shading,
GL_SMOOTH of smooth shading.

At initialization, gl has glShadeModel set to GL_SMOOTH, so as long as you didn't call glShadeMode(), specifying a normal per vertex will give you smooth shading, so long as each normal is the normal to the surface, and not the polygon. Here is an example of the difference between a normal to the surface and the normals to the polygons apporximating the surface.



Edited by - succinct on November 2, 2001 3:15:28 PM

Share this post


Link to post
Share on other sites
A sphere is definitely the easiest, because, as cheesegrater said, the normal for any point on a sphere is the line from the line from the center of the sphere to the point, normalized.

For an arbitrary mesh of polygons, you keep track of what polygons use what vertices and for each vertex computer the average of all the polygon normals that use that vertex. The necessary data structures for figuring this out are somewhat tricky, because each polygon must reference it's composing vertices, and each vertex must reference all of the polygons that reference it. It becomes a "chicken or the egg" type of problem, but you can solve it.

And, to my knowledge, the only other type of surface is a mathematically defined one. If you can define a surface parametrically, such that it is in terms of two variables, usually u and v, you can find the normal using a little calculus. For a given ( u,v ) on the surface, the surface normal is the unit tangent of the u curve crossed with the unit tangent of the v curve.

Basically, seperate the equation into it's f( u ) and g( v ) parts, expressed as vector functions. Find f'( u ) and g'( v ). Normalize them. Cross them. This is your unit normal vector.

Here is a visual explanation for the normals for a parametric torus.

The torus is just a circle (g(v)) swept around another curve (f(u)). The normal at any given point is the unit gradient of the sweeping curve crossed by the unit gradient of the swept curve.

For a circle defined as
x = r*cos( t )
y = r*sin( t )

the derivitaves (gradients) are
x' = r*-sin( t )
y' = r*cos( t )

just like you learn in highschool (and hopefully you've been to highschool and have had calculus!)

For further explanation, the picture generated used the following function.

    
void gl::RenderTorus(
int Majors, // number of major subdivisions (along the greater circle)

int Minors, // number of minor subdivisions (along the lesser circle)

float MrX, // major x radius

float MrY, // major y radius

float mrX, // minor x radius

float mrZ, // minor z radius

float Msa, // major start angle

float Mea, // major end angle

float msa, // minor start angle

float mea, // minor end angle

bool InvertNormals
)
{
// the vector class uses the operator ^ as a cross product

// the member function .Unit() normalizes the vector.


int NumMajorVertices = Majors + 1;
int NumMinorVertices = Minors + 1;

if( NumMajorVertices <= 2 )
NumMajorVertices = 3;

if( NumMinorVertices <= 2 )
NumMinorVertices = 3;

// calc angle deltas

float MajorAngleDelta = (Mea - Msa)*M_PI/(180*(NumMajorVertices - 1));
float MinorAngleDelta = (mea - msa)*M_PI/(180*(NumMinorVertices - 1));

float MajorAngle1 = Msa*M_PI/180;
float MajorAngle2 = MajorAngle1 + MajorAngleDelta;
for( int i = 0; i < NumMajorVertices - 1; ++i )
{
// calc major coordinates and normals

float uS1x = cos( MajorAngle1 );
float uS1y = sin( MajorAngle1 );
float uS2x = cos( MajorAngle2 );
float uS2y = sin( MajorAngle2 );

Vector uS1 = Vector( MrX*uS1x,MrY*uS1y,0 );
Vector uN1 = Vector( -MrX*uS1y,MrY*uS1x,0 ).Unit() ^ Vector( 0,0,1 );

Vector uS2 = Vector( MrX*uS2x,MrY*uS2y,0 );
Vector uN2 = Vector( -MrX*uS2y,MrY*uS2x,0 ).Unit() ^ Vector( 0,0,1 );

// calc rotation angles for minor ellipse (so it lines up with major normal)

float RotationAngle1 = acos( uN1.x );
if( ((-M_PI < MajorAngle1) && (MajorAngle1 < 0 ))
|| ((2*M_PI > MajorAngle1) && (MajorAngle1 > M_PI)) )
RotationAngle1 = -RotationAngle1;

float RotationAngle2 = acos( uN2.x );
if( ((-M_PI < MajorAngle2) && (MajorAngle2 < 0 ))
|| ((2*M_PI > MajorAngle2) && (MajorAngle2 > M_PI)) )
RotationAngle2 = -RotationAngle2;

// cache rotation coefficients

float ct1 = cos( RotationAngle1 );
float st1 = sin( RotationAngle1 );
float ct2 = cos( RotationAngle2 );
float st2 = sin( RotationAngle2 );

glBegin( GL_QUAD_STRIP );
float MinorAngle = msa*M_PI/180;
for( int j = 0; j < NumMinorVertices; ++j )
{
// v == minor param

float vSx = cos( MinorAngle );
float vSz = sin( MinorAngle );

// rotate minor ellipse so it is aligned with the normal of the major ellipse at this point

Vector vS = Vector( mrX* vSx,0,mrZ*vSz );
Vector vT = Vector( mrX*-vSz,0,mrZ*vSx );

Vector vS1r = Vector( ct1*vS.x,st1*vS.x,vS.z );
Vector vT1r = Vector( ct1*vT.x,st1*vT.x,vT.z );
Vector vS2r = Vector( ct2*vS.x,st2*vS.x,vS.z );
Vector vT2r = Vector( ct2*vT.x,st2*vT.x,vT.z );

Vector vN1 = ((vT1r ^ vS1r).Unit() ^ vT1r).Unit();
Vector vN2 = ((vT2r ^ vS2r).Unit() ^ vT2r).Unit();

if( InvertNormals )
{
vN1 = -vN1;
vN2 = -vN2;
}

glNormal3fv( vN1 );
glVertex3fv( uS1 + vS1r );
glNormal3fv( vN2 );
glVertex3fv( uS2 + vS2r );

MinorAngle += MinorAngleDelta;
}
glEnd();

MajorAngle1 += MajorAngleDelta;
MajorAngle2 += MajorAngleDelta;
}
}


I hope that helps,
-- Succinct

Edited by - succinct on November 2, 2001 5:14:11 PM

Share this post


Link to post
Share on other sites
Uhh, hmm.

Ok, you guys are really being nice and putting lots of time into this but, all this info is really confusing...how do I "smooth shade" a cube? I thought you had to give a "normal" for each vertex...



>just like you learn in highschool (and hopefully you''ve been to >highschool and have had calculus!)
Hmm, uhh... In highschool.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you have the object in a .3ds file you can use
a software named 3DExploration (search with www.google.com)
and this software give you a file (see "Save as..") with
all information about texturing normals vertex position...
as .cpp file for OpenGL.
That''s all

Share this post


Link to post
Share on other sites
Hi,

When you have already the normal for a polygon it is
not difficult to find the vertex-normals.
take a vertex, go through your polygons, take the Face(polygon)-Normal from all the polygons who share that vertex,
add them and normalize it, so can get the vertex-normals.

Try a Cube, becaue a cube only has eight corners, vertices

Share this post


Link to post
Share on other sites
Etwinox:

After you figure out the vertex issues, to gourand shade a polygon you can do the following:

//----------------------------------------

//define light and material properties
float ambientLight[] = {0.5f,0.5f,0.5f,1.0f}; // ambient light
float specularLight[]= {1.0f,1.0f,1.0f,1.0f }; //specular light

//material reacting to ambient light
float matAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f};

then add the following to your scene initialization

glEnable (GL_LIGHTING); // Enable lighting
glEnable (GL_COLOR_MATERIAL); //enable materials
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

//Set the lighting materials
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
glMateriali (GL_FRONT, GL_SHININESS, 128); //strong shiny effect

//Setup LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); //ambient light
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);//specular light
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);//light position

glEnable (GL_LIGHT0); //enable light0

glShadeModel (GL_SMOOTH);//enable gourand shading

/---------------------------------/

Hope it helps

Share this post


Link to post
Share on other sites

  • 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!