iDevGames Forums
Understanding glColorMaterial - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: Understanding glColorMaterial (/thread-2108.html)



Understanding glColorMaterial - PhysicsGuy - Nov 24, 2008 07:05 PM

As an excuse to learn OpenGL I wanted to create a program to plot in 3D the nested magnetic flux surfaces of our Stellarator experiment. So far I have been able to create and color them correctly. This is what it looks like without lighting.

http://homepage.mac.com/cianci66/UnLighted.jpg

The colors are important. They represent the strength of the magnetic field. I want to add some lighting so that the 3D structures are more distinct. I'm trying to use glColorMaterial to add some highlight on top of the colors. My code is

Code:
- (void)prepareOpenGL {
    if(dataLoaded) {
        [self compileFluxSurfaces];
    }
    
    glLoadIdentity();
    glViewport(0, 0, [self bounds].size.width, [self bounds].size.height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0*xScale, 1.0*xScale, -1.0*yScale, 1.0*yScale, 1.0, -1.0);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    glShadeModel(GL_SMOOTH);
    
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glClearDepth(1.0);
    
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    
    glEnable(GL_LIGHTING);
    
    glEnable(GL_LIGHT0);
    float specular[] = {1.0, 1.0, 1.0, 0.1};
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
    float diffuse[] = {1.0, 1.0, 1.0, 0.01};
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    float ambient[] = {1.0, 1.0, 1.0, 0.1};
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    float position[] = {1.0, 1.0, 1.0, 1.0};
    glLightfv(GL_LIGHT0, GL_POSITION, position);
    
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT, GL_DIFFUSE);
    glColorMaterial(GL_FRONT, GL_AMBIENT);
    glColorMaterial(GL_FRONT, GL_SPECULAR);
    
    glLineWidth(1.0);
}

The code to draw the surfaces striped down to just the OpenGL calls. Note that I'm converting from cylindrical coordinates to cartesian that's why my vertexes have z and y flipped.

Code:
- (void)drawFluxSurface:(int)flux from:(int)phiStart to:(int)phiStop {
    ...
    
    for(int phi = phiStart; phi < phiStop; phi++) {
        ...
        
        glBegin(GL_QUAD_STRIP);
        
        for(int theta = 1; theta <= NUM_PHI; theta++) {
            ...
            
            if(theta%2 == 1) {
                glNormal3d((z2-z1)*(y2-y1)-(y3-y1)*(z3-z1),
                           (y2-y1)*(x2-x1)-(x3-x1)*(y3-y1),
                           (x2-x1)*(z2-z1)-(z3-z1)*(x3-x1));
            }
            
            ...
                
            glColor4d(red, green, blue, 1.0);
            glVertex3d(x1, z1, y1);
            
            ...
                
            glColor4d(red, green, blue, 1.0);
            glVertex3d(x2, z2, y2);
            
            ...
        }
        
        ...
                
        glColor4d(red, green, blue, 1.0);
        glVertex3d(r1*cos(phi1R), z1, r1*sin(phi1R));
            
        ...
                
        glColor4d(red, green, blue, 1.0);
        glVertex3d(r2*cos(phi2R), z2, r2*sin(phi2R));
            
        glEnd();
    }
}

However this is what gets rendered.

http://homepage.mac.com/cianci66/Lighted.jpg

I have been playing around with it turning on and off various things. I have three conclusions.

1. glColorMaterial(GL_FRONT, GL_DIFFUSE) has no effect. If I set it up to have Diffuse light the only light all I get is black regardless of what value I set the light intensity too.

2. Using only specular light I get the color on the highlights and black everywhere else. This is what I would expect. When I turn on ambient the highlights become blown out. The light intensity appears to have no effect on how bright the model is.

3. Setting GL_FRONT or GL_BACK also seems to have no effect. I not sure if the vector in glnormal3d has to be normalized or not.

Am I using this correctly? I haven't found a tutorial on the web that really explains glColorMaterial aside from saying it's an alternative to setting glMaterial. Is there a way to control how bright the specular highlights are? Why aren't the diffuse lights working.


Understanding glColorMaterial - Najdorf - Nov 24, 2008 07:39 PM

Yeah normals must be normalized or you get lighting proportionally stronger-weaker based on the length of the vector.

just use

glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);

if you're not sure which side is the front

GL_SPECULAR values should be much lower than the diffuse light if i recall, if you're not using very high shininess (with glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess))

Your diffuse light alpha is way too low, much lower than your ambient light.

Also there's always some ambient light if you don't turn glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); to (0,0,0,1)

Also you usually keep the GL_SPECULAR value materials white (as specular light is intended to reflect light completely without the absorbing that causes colors to appear), so you don't call glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR), keeping the specular component to the white default and not affected by glColor4d (you can still change it with glMaterialfv)


Understanding glColorMaterial - TomorrowPlusX - Nov 25, 2008 09:27 AM

This may be beyond the scope of what you're doing, but in my experience, dropping glColor/glColorMaterial/etc in favor of GLSL and passing material properties as uniforms and attributes simplified my code greatly.


Understanding glColorMaterial - PhysicsGuy - Nov 25, 2008 06:25 PM

Najdorf Wrote:Yeah normals must be normalized or you get lighting proportionally stronger-weaker based on the length of the vector.

Thanks normalizing the vector fixed all the problems I was having.