I am finally starting to work with lighting in OpenGL, but I can't seem to get the lights to work properly. I am originally going off XoaX's tutorial #4, but I am trying to implement mine into objects. In my code I have a "Light" that extends a basic class called "Object" so I do not have to re-implement moving, pointing commands, etc. There is a sub class in "Light" called "LightSettings" where the settings and some actions are done with Specular, Diffuse and ambient light for that particular light. And since OpenGL cannot create an infinite supply of lights, I created a manager called "LightStudio" to help handle who has what light handle as well as the global light commands.
Moving right along, I am drawing a tessellated sheet (50 by 50 squares) that constrained to 4 different coordinates as a solid 0x0000FF blue. This sheet curves to hopefully get the full effect of lighting. In my program, I set up some default and standard lighting settings as so:
These commands are only called once (at the init of OpenGL):
My code for drawing the tessellated "plane" is below:Code:glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_LIGHTING); glShadeModel(GL_SMOOTH); glFrontFace(GL_CCW);
For those that need to see how I set up my normals:Code:void Plane3D::drawTessellated(int tessCountX, int tessCountY) { Point3D *pts,left,right; int pos,x,y; if (tessCountX<0 || tessCountY<0){return;} pts = new Point3D[(tessCountX+1)*(tessCountY+1)]; if (!pts) { errLog.print("Could not malloc. [Plane3D::drawTessellated(int,int)]"); assert(!"Could not malloc. [Plane3D::drawTessellated(int,int)]"); } pos = 0; for (y=0;y<=tessCountY;y++) { avg(a,d,y/(float)tessCountY,left); avg(b,c,y/(float)tessCountY,right); for (x=0;x<=tessCountX;x++) { avg(left,right,x/(float)tessCountX,pts[pos]); pos++; } } glBegin(GL_QUADS); for (y=0;y<tessCountY;y++) { for (x=0;x<tessCountX;x++) { GameLib::calculateNormalTrangle(pts[x +( y *(tessCountX+1))], pts[x +((y+1)*(tessCountX+1))], pts[x+1+((y+1)*(tessCountX+1))]); pts[x +( y *(tessCountX+1))].useAsVertex(); pts[x +((y+1)*(tessCountX+1))].useAsVertex(); pts[x+1+((y+1)*(tessCountX+1))].useAsVertex(); pts[x+1+( y *(tessCountX+1))].useAsVertex(); } } glEnd(); delete []pts; }
And finally my Lights:Code:void GameLib::calculateNormalTrangle(Point3D &va,Point3D &vb,Point3D &vc) { Direction3D normal; Point3D a,b,normalPt; a=va; a-=vb; b=vb; b-=vc; normalPt.setX((a.getY() * b.getZ()) - (a.getZ() * b.getY())); normalPt.setY((a.getZ() * b.getX()) - (a.getX() * b.getZ())); normalPt.setZ((a.getX() * b.getY()) - (a.getY() * b.getX())); // normalize normal.setFromLength(normalPt.getX(), normalPt.getY(), normalPt.getZ()); glNormal3f(normal.getI(),normal.getJ(),normal.getK()); } Direction3D& Direction3D::setFromLength(double dx,double dy,double dz) { double total; total=dx+dy+dz; i=dx/total; j=dy/total; k=dz/total; return *this; }
Light.h
Light.cppCode:#pragma once #include "Object.h" #include "Point3D.h" class Light : public Object { private: int lightNum;//-1 if no light GLenum getLightEnum(); bool requestControl(); public: static GLenum getLightEnum(int num); class LightSettings { private: bool use; float intensity,r,g,b; public: LightSettings(); ~LightSettings(); float getRed(); float getGreen(); float getBlue(); float getIntensity(); LightSettings& setIntensity(float intensity); LightSettings& setColor(int hexColor); LightSettings& setColor(float r, float g, float b); LightSettings& disable(); LightSettings& enable(); void drawMe(GLenum lightEnum);//only call from Light() }ambient,diffuse,specular; Light(); ~Light(); bool hasLightControl(); void draw(); }; class LightStudio { private: Light *inUse[8];//array of pointers int ambientLight; public: LightStudio(); ~LightStudio(); int requestLightControl(Light *light);//should only be called from Light bool releaseLightControl(Light *light);//should only be called from Light LightStudio& setAmbientLight(int hexColor); int getAmbientLight(); }; extern LightStudio lightStudio;
Happy fun time with lights isn't soCode:#include "Light.h" /*some more includes here*/ #define DEFAULT_INTENSITY_AMBIENT 0.2f #define DEFAULT_INTENSITY_DIFFUSE 1.0f - DEFAULT_INTENSITY_AMBIENT #define DEFAULT_INTENSITY_SPECULAR 1.0f LightStudio lightStudio; ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// //// L I G H T :: L I G H T S E T T I N G S //// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// Light::LightSettings::LightSettings() { disable(); intensity=0; r=g=b=1.0; } Light::LightSettings::~LightSettings(){} float Light::LightSettings::getRed(){return r;} float Light::LightSettings::getGreen(){return g;} float Light::LightSettings::getBlue(){return b;} float Light::LightSettings::getIntensity(){return intensity;} Light::LightSettings& Light::LightSettings::setIntensity(float intensity) { this->intensity=intensity; return *this; } Light::LightSettings& Light::LightSettings::setColor(int hexColor) { r = (float)(hexColor & 0xFF0000)/(float)0xFF0000; g = (float)(hexColor & 0x00FF00)/(float)0x00FF00; b = (float)(hexColor & 0x0000FF)/(float)0x0000FF; return *this; } Light::LightSettings& Light::LightSettings::setColor(float r, float g, float b) { this->r=r; this->g=g; this->b=b; return *this; } Light::LightSettings& Light::LightSettings::disable() { use = false; return *this; } Light::LightSettings& Light::LightSettings::enable() { use = true; return *this; } void Light::LightSettings::drawMe(GLenum lightEnum) { // Set lighting intensity and color GLfloat color[4]; color[0] = color[1] = color[2] = intensity; color[3] = 1.0f; glLightfv(lightEnum, GL_AMBIENT, color); // Set material properties GLfloat cc[4]; cc[0]=r; cc[1]=g; cc[2]=b; cc[3]=1.0f; glMaterialfv(GL_FRONT, GL_AMBIENT, cc); } ///////////////////////////////////// ///////////////////////////////////// //// L I G H T //// ///////////////////////////////////// ///////////////////////////////////// Light::Light() { requestControl(); ambient.setIntensity(DEFAULT_INTENSITY_AMBIENT); diffuse.setIntensity(DEFAULT_INTENSITY_DIFFUSE); specular.setIntensity(DEFAULT_INTENSITY_SPECULAR); } Light::~Light() { lightStudio.releaseLightControl(this); } bool Light::requestControl() { lightNum = lightStudio.requestLightControl(this); return lightNum==-1?false:true; } void Light::draw() { if (hasLightControl()) { if (gameController.isLightingEnabled()) { // Set the light position GLfloat pos[4]; GLenum lightEnum; lightEnum = getLightEnum(); //GLfloat dir[4]; pos[0] = (float)position.getX(); pos[1] = (float)position.getY(); pos[2] = (float)position.getZ(); pos[3] = 1.0f; glLightfv(lightEnum, GL_POSITION, pos); /*dir[0] = (float)direction.getI(); dir[1] = (float)direction.getJ(); dir[2] = (float)direction.getK(); glLightfv(getLightEnum(), GL_SPOT_DIRECTION, dir);*/ ambient.drawMe(lightEnum); diffuse.drawMe(lightEnum); specular.drawMe(lightEnum); } } else { requestControl(); } } bool Light::hasLightControl() { return lightNum==-1?false:true; } GLenum Light::getLightEnum() { switch (lightNum) { case 0: return GL_LIGHT0; case 1: return GL_LIGHT1; case 2: return GL_LIGHT2; case 3: return GL_LIGHT3; case 4: return GL_LIGHT4; case 5: return GL_LIGHT5; case 6: return GL_LIGHT6; case 7: return GL_LIGHT7; default: errLog.print("trying to use a non existant light in Light::getLightEnum"); assert(!"trying to use a non existant light in Light::getLightEnum"); return 0; } } GLenum Light::getLightEnum(int num) { switch (num) { case 0: return GL_LIGHT0; case 1: return GL_LIGHT1; case 2: return GL_LIGHT2; case 3: return GL_LIGHT3; case 4: return GL_LIGHT4; case 5: return GL_LIGHT5; case 6: return GL_LIGHT6; case 7: return GL_LIGHT7; default: errLog.print("trying to use a non existant light in Light::getLightEnum(int)"); assert(!"trying to use a non existant light in Light::getLightEnum(int)"); return 0; } } ///////////////////////////////////////////////// ///////////////////////////////////////////////// //// L I G H T S T U D I O //// ///////////////////////////////////////////////// ///////////////////////////////////////////////// LightStudio::LightStudio() { for (int i=0;i<8;i++) {inUse[i] = 0;} } LightStudio::~LightStudio(){} int LightStudio::requestLightControl(Light *light) { for (int i=0;i<8;i++) { if (inUse[i]==0) { inUse[i]=light; glEnable(Light::getLightEnum(i)); mainLog(Str()<<"Enabling LIGHT"<<i<<" control to a new light"); return i; } } return -1;//full } bool LightStudio::releaseLightControl(Light *light) { for (int i=0;i<8;i++) { if (inUse[i]==light) { inUse[i]=0; mainLog(Str()<<"Disabling LIGHT"<<i<<" for an object"); glDisable(Light::getLightEnum(i)); return true; } } return false; } LightStudio& LightStudio::setAmbientLight(int hexColor) { ambientLight = hexColor; float cc[4]; cc[0]=(hexColor&0xFF0000)/(float)0xFF0000; cc[1]=(hexColor&0x00FF00)/(float)0x00FF00; cc[2]=(hexColor&0x0000FF)/(float)0x0000FF; cc[3]=1.0f; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cc); return *this; } int LightStudio::getAmbientLight() { return ambientLight; }
The plane shows up as pure white! I'm sorry for such a book of a post, but I don't think leaving anything out would prove to be useful as a reader. In fact some more code might be required, but this should be decent enough for now. I appreciate the help, I don't want to get to a point where I just add stuff in to see if it might work. If requested, I will provide the git repo.
Thanks again



LinkBack URL
About LinkBacks



