I am lighting my scene in opengl and there are 4 walls, only 2 of them are being lit.
I think it is something wrong with the normals but I am not sure.
This is the lighting code:
glShadeModel(GL_SMOOTH);
//glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
GLfloat lightpos0[] = {-5, 1, 0, 0.};
GLfloat AmbientLight0[] = {0.2, 0.2, 0.2,1.0};
GLfloat DiffuseLight0[] = {0.8, 0.8, 0.8,1.0};
GLfloat SpecularLight0[] = {1.0, 1.0, 1.0,1.0};
glLightfv(GL_LIGHT0, GL_POSITION, lightpos0);
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight0);
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight0);
GLfloat lightpos1[] = {5, 1, 0, 0};
GLfloat AmbientLight1[] = {0.2, 0.2, 0.2,1.0};
GLfloat DiffuseLight1[] = {0.8, 0.8, 0.8,1.0};
GLfloat SpecularLight1[] = {1.0, 1.0, 1.0,1.0};
glLightfv(GL_LIGHT1, GL_POSITION, lightpos1);
glLightfv(GL_LIGHT1, GL_AMBIENT, AmbientLight1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, DiffuseLight1);
glLightfv(GL_LIGHT1, GL_SPECULAR, SpecularLight1);
This is the code for drawing the 4 walls.
//north
glBegin(GL_QUADS);
glNormal3f(1.0,0,0);
glVertex3f(-10,0,-10);
glVertex3f( 10,0,-10);
glVertex3f( 10,5,-10);
glVertex3f(-10,5,-10);
glEnd();
//south
glBegin(GL_QUADS);
glNormal3f(-1.0, 0, 0);
glVertex3f(-10,0, 10);
glVertex3f( 10,0, 10);
glVertex3f( 10,5, 10);
glVertex3f(-10,5, 10);
glEnd();
//east
glBegin(GL_QUADS);
glNormal3f(0,0, -1.0);
glVertex3f( 10,0,-10);
glVertex3f( 10,0,10);
glVertex3f( 10,5,10);
glVertex3f( 10,5,-10);
glEnd();
//west
glBegin(GL_QUADS);
glNormal3f(0,0,1.0);
glVertex3f( -10,0,-10);
glVertex3f( -10,0,10);
glVertex3f( -10,5,10);
glVertex3f( -10,5,-10);
glEnd();
If it helps, here's and image of whats happening: http://i.stack.imgur.com/xRgVL.png
As pointed out by Vladislav Khorev, the normals must be directed out of the coordinate that is common to all points (given this special orthogonal arrangement).
But also one should consider the winding of the polygons:
// Polygon A -- north Polygon B -- south
glVertex3f(-10,0,-10); glVertex3f(-10,0, 10);
glVertex3f( 10,0,-10); glVertex3f( 10,0, 10);
glVertex3f( 10,5,-10); glVertex3f( 10,5, 10);
glVertex3f(-10,5,-10); glVertex3f(-10,5, 10);
Normal(0,0,1), Normal(0,0,-1);
The two polygons (north and south), are of different winding. The first is ClockWise observed from point 0,0,0 and the other of CCW. One should be consistent with these.
It seems that you pass wrong normal vector to walls.
If your wall got Z = -10 for all points (wall is parallel to X), then it must have normal vector directed in positive direction of Z: (0,0,1).
Same is true for all directions.
Try this:
glBegin(GL_QUADS);
glNormal3f(0,0,1);
glVertex3f(-10,0,-10);
glVertex3f( 10,0,-10);
glVertex3f( 10,5,-10);
glVertex3f(-10,5,-10);
glEnd();
//south
glBegin(GL_QUADS);
glNormal3f(0, 0, -1);
glVertex3f(-10,0, 10);
glVertex3f( 10,0, 10);
glVertex3f( 10,5, 10);
glVertex3f(-10,5, 10);
glEnd();
//east
glBegin(GL_QUADS);
glNormal3f(-1,0, -0);
glVertex3f( 10,0,-10);
glVertex3f( 10,0,10);
glVertex3f( 10,5,10);
glVertex3f( 10,5,-10);
glEnd();
//west
glBegin(GL_QUADS);
glNormal3f(1, 0, 0);
glVertex3f( -10,0,-10);
glVertex3f( -10,0,10);
glVertex3f( -10,5,10);
glVertex3f( -10,5,-10);
glEnd();
Related
So I have drawn 5 tori on my scene and a cube behind them and besides LIGHT0 I also have LIGHT1 enabled on click. I need to create two different materials where when I press on number 1 material 1 turns on, and when I press 2 material two turns on instead of material one. But what happens is, those materials get turned on only for tori, not the cube behind them. Here is everything in the code explained:
void light_1() {
GLfloat light_position[] = {1.0f, 1.0f, 1.0f, 0.0f};
GLfloat light_specular[] = {1.0f, 1.0f, 1.0f, 5.0f};
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
}
Cube and tori have same exact properties.
void drawCube() {
GLfloat mat_diffuse[] = {0.3, 0.0, 0.7, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glutSolidCube(7.5);
}
void greenTorus() {
GLfloat mat_diffuse[] = {0.0, 1.0, 0.0, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glutSolidTorus(0.08, 0.8, 30, 30);
}
Here is my display function. Ignore the variables, they are controled by different stuff and are irrelevant.
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75.0, 4.0/3.0, 1.0, 200.0);
light_1();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0+LR, 0.0+UD, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
glTranslatef(0.0+tyg/2, 0.0-tbr/2, -5.0);
glRotated(a, 0, 0, 1);
glScaled(0.5+s, 0.5+s, 0.5+s);
greenTorus();
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, -0.5, -9.0);
drawCube();
glPopMatrix();
glFlush();
glutPostRedisplay();
}
Here is the material that is used for bottom image.
void material_1() {
GLfloat m_ambient[] = {0.33f, 0.23f, 0.03f, 1.0f};
GLfloat m_diffuse[] = {0.8f, 0.6f, 0.1f, 1.0f};
GLfloat m_specular[] = {2.0f, 2.0f, 2.0f, 1.0f};
GLfloat m_shininess = 128.0f;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m_shininess);
}
Does anyone see the issue? Here is a screenshot of the scene whole program renders when lights 0 and 1 are both turned on and material_1 is turned on. Why isn't the cube also highlighted? Why does LIGHT0 light on all objects, but LIGHT1 only on tori?
Problem: Objects aren't rendering correctly.
What I tried to do: Searched Stack Overflow. Read that I needed to enable Depth_Test and did so. Still doesn't work. Read that I possibly needed glDepthFunc(GL_LEQUAL);, did not work. Is there something in the way I wrote reshape/initscene/myDisplay that causes these common approaches not to work?
Code below.
void reshape (int w, int h)
{
viewport.w = w;
viewport.h = h;
glViewport(0,0,viewport.w,viewport.h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
}
else {
glOrtho (-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void myDisplay() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the color buffer
glMatrixMode(GL_MODELVIEW); // indicate we are specifying camera transformations
glLoadIdentity(); // make sure transformation is "zero'd"
glScalef(zoom, zoom, zoom);
gluLookAt(0.0, -9.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
glRotatef(y_rotation, 0.0, 1.0, 0.0);
glRotatef(x_rotation, 1.0, 0.0, 0.0);
renderObjects();
glFlush();
glutSwapBuffers(); // swap buffers (we earlier set double buffer)
}
void initScene(){
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
reshape(viewport.w, viewport.h);
glShadeModel(GL_FLAT);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
GLfloat red[] = {1.0f, 0.2f, 0.2f, 1.0f};
GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat gray[] = {0.5f, 0.5f, 0.5f, 1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, gray);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gray);
GLfloat lightPos[] = {0.0f, 0.0f, -10.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
}
I am trying to draw a sphere and a rotating cube around it. I am able to draw both of them perfectly seperately. Nevertheless once I draw both together I get strange results.
my sphere gets disformed.
when I change the angle of my cubeon purpose (by pressing on a button) it just dissapears from my screen.
when I only draw the cube and theng change the angle everything works fine.
Why please?
image: http://imgur.com/dIngayh (the cube looks ok, but the sphere is too stretched)
My code:
void MyGLWidget::paintGL()
{
glScalef(1,1,1);
setLight();
drawSun();
drawCube();
}
void MyGLWidget::initializeGL()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
}
void MyGLWidget::drawSun()
{
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glScalef(1,1,1);
glLoadIdentity();
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
glColor3f(1,1,0);
gluSphere(quadric, 0.25, 360,360);
gluDeleteQuadric(quadric);
glPopMatrix();
}
void MyGLWidget::drawCube()
{
glTranslatef(0, 0, 0);
glRotatef(getCubeAngle(), 1.0f, 0.0f, 0.0f);
glRotatef(0, 0.0f, 1.0f, 0.0f);
glRotatef(0, 0.0f, 0.0f, 1.0f);
glTranslatef( 0.5, 0, 0);
glBegin(GL_QUADS);
//back side of cube
glColor3f(255,0,0);
glVertex3f(-0.1, 0.1,-0.1 );//upper left corner
glVertex3f(0.1, 0.1,-0.1); //uper right
glVertex3f(0.1,-0.1,-0.1 ); // down left
glVertex3f(-0.1,-0.1,-0.1); // down right
/*draws other parts of the cube in the same way*/
glEnd();
glFlush();
}
/**/
void MyGLWidget::setLight()
{
// Prepare light parameters.
float SHINE_ALL_DIRECTIONS = 1;
float lightPos[4] = {-30, 0, 0, SHINE_ALL_DIRECTIONS};
float lightColorAmbient[4] = {50, 50, 0.1, 1};
float lightColorSpecular[4] = {150, 150, 0.5, 1};
// Set light parameters.
glLightfv(GL_LIGHT1, GL_POSITION, lightPos);
glLightfv(GL_LIGHT1, GL_AMBIENT, lightColorAmbient);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightColorSpecular);
// Enable lighting in GL.
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
// Set material properties.
float rgba[3] = {0.3, 0.5, 1};
glMaterialfv(GL_FRONT, GL_AMBIENT, rgba);
glMaterialfv(GL_FRONT, GL_SPECULAR, rgba);
glMaterialf(GL_FRONT, GL_SHININESS, 0.5f);
}
try to add this one:
void MyGLWidget::resizeGL(int width, int height);
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glScalef(height *1./width, 1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
and more read here (rus)
I am trying to create a room in openGL and i have the following quads however wall2 and wall4 do not show. I am guessing this is something to do with perspectives as if i go outside of the room i can see they have been rendered.
glColor3f(0.1f, 0.9f, 0.9f);
//Wall1
glBegin(GL_QUADS);
glNormal3f(0,0,1);
glVertex3f(-10,0,-10);
glVertex3f( 10,0,-10);
glVertex3f( 10,5,-10);
glVertex3f(-10,5,-10);
glEnd();
//Wall2
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glNormal3f(0,0,1);
glVertex3f(-10,0, 10);
glVertex3f( 10,0, 10);
glVertex3f( 10,5, 10);
glVertex3f(-10,5, 10);
glEnd();
//Wall3
glColor3f(0.4f, 0.9f, 0.1f);
glBegin(GL_QUADS);
glNormal3f(-1,0, 0);
glVertex3f( 10,0,-10);
glVertex3f( 10,0,10);
glVertex3f( 10,5,10);
glVertex3f( 10,5,-10);
glEnd();
//Wall4
glColor3f(0.1f, 0.2f, 0.2f);
glBegin(GL_QUADS);
glNormal3f(1, 0, 0);
glVertex3f( -10,0,-10);
glVertex3f( -10,0,10);
glVertex3f( -10,5,10);
glVertex3f( -10,5,-10);
glEnd();
Try disabling face culling! :)
I'm having trouble being able to see objects I've created when I have enabled lighting in OpenGL. I have an object that is imported from 3D Max that the lighting works correctly on but the rest of my scene does not. I know that I need to specify normals but this hasn't seemed to have helped. Although if I create a simple polygon in my display() function that works correctly but other polygons that have been created in methods of a class and called in the display() function are not showing up
Here is my lighting code
glewInit();
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT)
glShadeModel(GL_SMOOTH);
//light position and colour
GLfloat light_position[] = { 0.0, 0.0, 20.0,0.0 };
GLfloat white_light[] = {0.8,0.8,0.8,0.0};
GLfloat diff_light[] = {1.0,1.0,1.0,0.0};
GLfloat spec_light[] = {1.0,1.0,1.0,0.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, white_light);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diff_light);
glLightfv(GL_LIGHT0, GL_SPECULAR, spec_light);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
//ambient light
GLfloat ambient[] = {0.3,0.3,0.3};
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
//diffuse material component
GLfloat diff[] = {0.6,0.6,0.6};
glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
//specular material component
GLfloat WhiteSpec[] = {1,1,1};
glMaterialfv(GL_FRONT, GL_SPECULAR, WhiteSpec);
GLfloat shininess = 50;
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
//ENABLE LIGHTING AND DEPTH TEST
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
This is my class method that is creating my sea
glColor3f(0,0,1);
glPushMatrix();
//enable texturing
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, seaTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
for(int i = 0, k = 0; i < (getWidth()/10); i++){
for(int j = 0; j < (getLength()/10); j++){
if(i >= Sea::waveLoc1 && i <= Sea::waveLoc1+Sea::sinArrayLength){
int nextK = k+1;
if(nextK == Sea::sinArrayLength){
nextK = 0;
}
if(i == Sea::waveLoc1+Sea::sinArrayLength){
//front of wave
glBegin(GL_POLYGON);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0, 1.0);glVertex3f(Sea::seaGrid[i][j].x, Sea::sinVals[nextK], Sea::seaGrid[i][j].z);
glTexCoord2f(0.0, 0.0);glVertex3f(Sea::seaGrid[i][j+1].x, Sea::sinVals[nextK], Sea::seaGrid[i][j+1].z);
glTexCoord2f(1.0, 0.0);glVertex3f(Sea::seaGrid[i+1][j+1].x, Sea::seaGrid[i+1][j+1].y , Sea::seaGrid[i+1][j+1].z);
glTexCoord2f(1.0, 1.0);glVertex3f(Sea::seaGrid[i+1][j].x, Sea::seaGrid[i+1][j].y, Sea::seaGrid[i+1][j].z);
glEnd();
}else{
//rest of wave
glBegin(GL_POLYGON);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0, 1.0);glVertex3f(Sea::seaGrid[i][j].x, Sea::sinVals[k], Sea::seaGrid[i][j].z);
glTexCoord2f(0.0, 0.0);glVertex3f(Sea::seaGrid[i][j+1].x, Sea::sinVals[k], Sea::seaGrid[i][j+1].z);
glTexCoord2f(1.0, 0.0);glVertex3f(Sea::seaGrid[i+1][j+1].x, Sea::sinVals[nextK], Sea::seaGrid[i+1][j+1].z);
glTexCoord2f(1.0, 1.0);glVertex3f(Sea::seaGrid[i+1][j].x, Sea::sinVals[nextK], Sea::seaGrid[i+1][j].z);
glEnd();
}
}else{
//draw flat sea
glBegin(GL_POLYGON);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0, 1.0);glVertex3f(Sea::seaGrid[i+1][j].x, Sea::seaGrid[i+1][j].y, Sea::seaGrid[i+1][j].z);
glTexCoord2f(0.0, 0.0);glVertex3f(Sea::seaGrid[i+1][j+1].x, Sea::seaGrid[i+1][j+1].y, Sea::seaGrid[i+1][j+1].z);
glTexCoord2f(1.0, 0.0);glVertex3f(Sea::seaGrid[i][j+1].x, Sea::seaGrid[i][j+1].y, Sea::seaGrid[i][j+1].z);
glTexCoord2f(1.0, 1.0);glVertex3f(Sea::seaGrid[i][j].x, Sea::seaGrid[i][j].y, Sea::seaGrid[i][j].z);
glEnd();
}
}
//increment k if i is in the area of the wave
if(k < Sea::sinArrayLength-1 && (i >= Sea::waveLoc1 && i <= Sea::waveLoc1+Sea::sinArrayLength)){
k++;
}else if(k == Sea::sinArrayLength){
k = 0;
}
}
if(Sea::waveLoc1 < 100 && Sea::waveInc == Sea::waveSpeedLimiter){
Sea::waveLoc1 +=1;
}else if(Sea::waveLoc1 >= 100){
Sea::waveLoc1 = 0;
}
//limits speed of wave
if(Sea::waveInc < Sea::waveSpeedLimiter){
Sea::waveInc++;
}else{
Sea::waveInc = 0;
}
//disable texturing
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
This is then called in my display() function as below
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)screenWidth/(GLfloat)screenHeight,0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camera.updateCameraPosition(mouse_x,mouse_y,screenWidth,screenHeight);
sea.buildSeaPlane();
scene.buildEdges();
glPushMatrix();
glColor3f(0,1,0);
glTranslatef(0, 20, 200);
model.speedDisplayFaceNormals();
glPopMatrix();
glPushMatrix();
plane.updatePlanePosition();
glBegin(GL_POLYGON);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(0, 25, 10);
glVertex3f(2, 25, 10);
glVertex3f(2, 25, 20);
glVertex3f(0, 25, 20);
glEnd();
glPopMatrix();
glFlush();
Any idea why I can't see any of this?
UPDATE:
I can see my sea if I disable texturing. How can I fix it so I can use textures and lighting?
UPDATE 2:
Have changed texturing to GL_MODULATE but I also had to remove the blending to make it work. Do I need blending enabled?
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
says to replace the lighting computation with the result of texturing. If you want lighting to affect texturing, us GL_MODULATE instead of GL_REPLACE.
Edit to add:
You only need blending if you want your geometry to be translucent (that's what blending is typically for). In your case, there are a number of issues in the code:
your light colors are fully transparent (all have 0. as the 4th component). So your light is making everything invisible. change it to 1.
your materials don't have a 4th component. That's even worse, as glMaterialfv expects 4 floats. That could even crash your app or reformat your disk. Add a forth component, preferably to 1. to make it fully opaque.
Try adding an ambient light for the whole scene. Something like:
GLfloat lightColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightColor);
In your glMaterialfv calls, the color parameter should have 4 values, not 3. Normally the 4th value is an alpha of 1.0. I'm not sure if it's OK to pass 0.0 as the 4th value for glLightfv either.