PDA

View Full Version : Quick shading/shadowing question



Richard145
11-08-2006, 11:17 AM
Please help,

I am trying to build a Display list with a simple "cube" that is the color RED. I have a function that builds a display list called buildWidget(GL gl). A copy of the code follows:

float red[] = { 0.8f, 0.1f, 0.0f, 1.0f };
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0);
gl.glEnable(GL.GL_CULL_FACE);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_LIGHT0);
gl.glEnable(GL.GL_DEPTH_TEST);
solidWidget = gl.glGenLists(1);
gl.glNewList(solidWidget, GL.GL_COMPILE);

gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, red, 0);
buildWidget(gl);

gl.glEndList();

gl.glEnable(GL.GL_NORMALIZE);

public static void buildWidget(GL gl) {
gl.glShadeModel(GL.GL_FLAT);
gl.glNormal3f(0.0f, 0.0f, 1.0f);
gl.glBegin(GL.GL_POLYGON);
// Front Face
gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glVertex3f(1.0f, -1.0f, 1.0f);
gl.glVertex3f(1.0f, 1.0f, 1.0f);
gl.glVertex3f(-1.0f, 1.0f, 1.0f);
gl.glEnd();
gl.glBegin(GL.GL_POLYGON);
// Back Face
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(-1.0f, 1.0f, -1.0f);

gl.glVertex3f(1.0f, 1.0f, -1.0f);
gl.glVertex3f(1.0f, -1.0f, -1.0f);
gl.glEnd();

gl.glBegin(GL.GL_POLYGON);
// Top Face
gl.glVertex3f(-1.0f, 1.0f, -1.0f);
gl.glVertex3f(-1.0f, 1.0f, 1.0f);
gl.glVertex3f(1.0f, 1.0f, 1.0f);
gl.glVertex3f(1.0f, 1.0f, -1.0f);
gl.glEnd();

gl.glBegin(GL.GL_POLYGON);
// Bottom Face
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(1.0f, -1.0f, -1.0f);
gl.glVertex3f(1.0f, -1.0f, 1.0f);
gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glEnd();

gl.glBegin(GL.GL_POLYGON);
// Right face
gl.glVertex3f(1.0f, -1.0f, -1.0f);
gl.glVertex3f(1.0f, 1.0f, -1.0f);
gl.glVertex3f(1.0f, 1.0f, 1.0f);
gl.glVertex3f(1.0f, -1.0f, 1.0f);
gl.glEnd();

gl.glBegin(GL.GL_POLYGON);
// Left Face
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glVertex3f(-1.0f, 1.0f, 1.0f);
gl.glVertex3f(-1.0f, 1.0f, -1.0f);
gl.glEnd();
}

The problem is that the red cube is created, but the shadow is cast across the "whole" cube as one Object instead of one face being brighter than another because it is facing the light source.

Can somebody please tell me how to do this? I am sure it is probably simple, but I am just learning.

Thanks in advance.

memfr0b
11-08-2006, 11:27 AM
For lighting purposes, the surface normal specifies the orientation of the surface and thus controls the intensity of the reflected/scattered light by the surface.

OpenGL doesn't compute surface normals by itself. You have to provide the surface normal via glNormal[bsifd][v] or glNormalPointer. Setting the surface normal only once for the whole cube basically tells OpenGL that all sides of the cube face the same direction (which, of course, they don't, but OpenGL just assumes you know what you're doing).

You need to set an appropriate normal for each side of the cube.

Richard145
11-08-2006, 11:57 AM
memfr0b,

Thank you VERY much. What you wrote makes perfect sense. I will give it a try.

Richard145
11-09-2006, 03:17 AM
Quick follow-up to my question.

I have been given a text file, which I am parsing and using OpenGL to display. the file is listed as a section of nodes (x, y, z values) and cooresponding triangular elements (node1, node2, node3 connectivity). Given that I don't know ahead of time the exact orientation of any triangular polygon, is there a quick way to find the orientation of a given polygon so that I can apply the glNormalf(Nx, Ny, Nz) to it?

Thanks in advance.

jide
11-09-2006, 04:03 AM
yeah, with doing some maths it is quiete easy. Simply do the cross product between 2 vectors of your triangles (in the same winding as your triangle) and you'll get what you want. The result is simply the face normal of your triangle.

Richard145
11-09-2006, 05:12 AM
Thank you jide. This is great information for a OpenGL newbie.

Given that OpenGL breaks everything down into triangles (I think - is this correct?), if I wanted to calculate the normal vector using elements with 4 points (instead of 3, as for my triangles) can I still just do a cross-product between any 2 points of the 4 for each polygon being rendered then apply the result to glNormalf(Nx, Ny, Nz)?

Overmind
11-09-2006, 05:27 AM
You don't take the cross product of the points, you take it of two edge vectors. So you need three points.

For a triangle:
(p1 - p0) x (p2 - p0)

For quads, it shouldn't make a difference which three points you take, because all points of a quad have to be on the same plane.

You just have to take care to use the correct order of points. When the normals point in the wrong direction, you have to switch the vectors in the cross product.

Richard145
11-09-2006, 07:11 AM
Thank you VERY Much. I will give your suggestions a try and see what I get.

Richard145
11-09-2006, 08:04 AM
It worked perfectly. Thanks to everybody for helping out a newbie like myself.