Opengl proper lighting problem - c++

I have written the following program to display a teapot on a table in a room with 2side walls and a floor.
#include <stdio.h>
#include <glut.h>
void wall1(float thickness)
{
glPushMatrix();
glTranslatef(100,100,0);
glRotatef(90,1,0,0);
glScalef(thickness,1,1);
glutSolidCube(100);
glPopMatrix();
}
void wall2(float thickness)
{
glPushMatrix();
glTranslatef(150,100,-50);
glScalef(1,1,thickness);
glutSolidCube(100);
glPopMatrix();
}
void floor(float thickness)
{
glPushMatrix();
glTranslatef(150,50,0);
glScalef(1,thickness,1);
glutSolidCube(100);
glPopMatrix();
}
void leg(float thickness)
{
glPushMatrix();
glScalef(thickness,.5,thickness);
glutSolidCube(100);
glPopMatrix();
}
void tableTop(float thickess)
{
glPushMatrix();
glTranslatef(150,100,0);
glScalef(.5,thickess,.5);
glutSolidCube(100);
glPopMatrix();
}
void table()
{
tableTop(.05);
glPushMatrix();
glTranslatef(125,75,-25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(175,75,-25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(175,75,25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(125,75,25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(150,110,0);
glScalef(.1,.1,.1);
glutSolidTeapot(100);
glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float pos[] = {200,200,0};
float dif[] = {.3,.3,.3,3};
float spe[] = {1,1,1,1};
float amb[] = {1,1,1,0};
glLightfv(GL_LIGHT0,GL_POSITION,pos);
glLightfv(GL_LIGHT0,GL_DIFFUSE,dif);
glLightfv(GL_LIGHT0,GL_AMBIENT,amb);
glLightfv(GL_LIGHT0,GL_SPECULAR,spe);
glTranslatef(50,50,0);
glRotatef(30,1,0,0);
glRotatef(-30,0,1,0);
wall1(.05);
wall2(.05);
floor(0.05);
table();
glFlush();
}
void reshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,400,0,400,-400,400);
glMatrixMode(GL_MODELVIEW);
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("woot");
glClearColor(1,1,1,1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
}
The problem with this is my lighting part is not working as expected. Its not illuminating evenly all my objects... What am i missing? This making even the teapot hard to sea.
My lighting part is in display function.

I was missing
glEnable(GL_NORMALIZE);
in the main function, and thus opengl was not rendering it properly! Alse #Christian's answer of using ambient only worked.
:)

OpenGL fixed function pipeline lighting is evaluated at the vertices only. glutSolidCube just creates vertices at the corners and nowhere else. So your lighting is calculated only very coarse. You could either switch to per fragment lighting by using a shader, or tesselate your objects. The latter requires you don't use glutSolidCube and instead load objects modelled in a 3D modeller or write your own primitive generators that offer a higher tesselation. I strongly recommend the first option.
glutSolidCube is just a very crude stand in function BTW.

If you want to evenly light all objects, only use ambient lighting.

Related

Rotate a simple polygon in OpenGL

I follow the code tutorial from the OpenGL programming book, but it doesn't work. It is showing white rectangle at the top left of my window. Could you please tell me what could be wrong with it?
#include<windows.h>
#include <GL/glut.h>
float yRot=0.0;
void Render()
{
//clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();//load identity matrix
glTranslatef(0.0f,0.0f,-4.0f);//move forward 4 units
//rotate along the y-axis
glRotatef(yRot,0.0f,1.0f,0.0f);
glColor3f(0.0f,0.0f,1.0f); //blue color
glBegin(GL_POLYGON);//begin drawing of polygon
glVertex3f(-0.5f,0.5f,0.0f);//first vertex
glVertex3f(0.5f,0.5f,0.0f);//second vertex
glVertex3f(1.0f,0.0f,0.0f);//third vertex
glVertex3f(0.5f,-0.5f,0.0f);//fourth vertex
glVertex3f(-0.5f,-0.5f,0.0f);//fifth vertex
glVertex3f(-1.0f,0.0f,0.0f);//sixth vertex
glEnd();//end drawing of polygon
yRot+=0.1f;//increment the yRot variable
}
//method the reshape the entire figure.
void reshape(int x, int h){
glViewport(0,0,x,h);
}
void init()
{
glClearColor(0.0,0.0,0.2,0.8);
}
int main(int argc, char** argv)
{
glutCreateWindow("simple triangles");
glutDisplayFunc(Render);
glutReshapeFunc(reshape);
init();
glutMainLoop();
}
First of all, you're not calling glutInit(&argc, argv) in main() before all the other GLUT related calls. Second of all, you're not calling glutSwapBuffers() in Render().
Besides that you aren't changing the projection matrix, and thus don't have the same resize function as the one presented in the beginning of the tutorial.
void Resize(int width, int height)
{
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
Changing those things and your code should work.

Drawing a Cone and Cylinder using GLUT

I've been trying to draw a cone and a cylinder using GLUT. The code I've written so far takes two points from the user, which represents the height of the cone/cylinder, and I want to draw a cone and a cylinder using the two points.
I looked up Google and found standard functions called glutWireCone() and gluCylinder(), but I'm unable to understand how to use these functions to draw in the manner that I want to draw. Can someone tell me how to draw a cone and a cylinder using the two points? Please let me know if you need some extra information to understand my question correctly.
Here are my init() and main() functions for you to know the settings of my program:
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, 0, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutInitWindowPosition(220, 80);
glutCreateWindow("Mini Paint - 3D");
init();
glutDisplayFunc(display);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMove);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Well lets take that gluCylinder function and apply it to your display function. Look at it's parameters:
void gluCylinder(GLU quadric* quad,
GLdouble base,
GLdouble top,
GLdouble height,
GLint slices,
GLint stacks);
So you want to draw a cylinder given the height parameter as input. I'm guessing everything else will remain constant. every time you render you'll want to use glPushMatrix and maybe glRotatef depending on how you would like its orientation, ending this call with a glPopMatrix
Ex: OnRender(float pHeight)
void OnRender(float pHeight) {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); //clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity();
gluCylinder(quadratic, 0.1f, 0.1f, pHeight, 32, 32);
glFlush();
}
declaring a quadratic object:
GLUquadricObj *quadratic;
quadratic = gluNewQuadric();
gluCylinder documentation: https://www.opengl.org/sdk/docs/man2/xhtml/gluCylinder.xml

Simple GLUT library issue

This will be my first post on stackoverflow.
So, I'm making a simple program(VISUAL STUDIO 2012), using GLUT library. I basically try to display a torus, but instead I get a black screen.
#include<gl/glut.h>
#include<math.h>
GLfloat r=8;
GLint spin=0;
GLfloat light_position[]={0.0,0.0,0.0,1.0};
GLfloat ex,ey=0, ez, upx=0, upy=0, upz=0;
void init(){
glClearColor(1.0,1.0,1.0,1.0);
glShadeModel(GL_FLAT);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_TEST);
glPushMatrix();
double sine = (float)sin((float)spin);
double cosine = (float)cos((float)spin);
ex=r*sine;
ez=r*cosine;
gluLookAt(ex,ey,-5.0,0,0,0,upx,upy,upz);
glColor3b(1.0,0,0);
glutSolidTorus(0.275,0.85,8,15);
glPopMatrix();
glFlush();
}
void reshape(int w, int h)
{
glViewport(0,0,(GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 1.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightfv( GL_LIGHT0, GL_POSITION, light_position);
}
void mouse(int button, int state, int x, int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
if( state == GLUT_DOWN){
spin = (spin+15)%360;
glutPostRedisplay();
}
break;
default:
break;
}
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(800,600);
glutInitWindowPosition(300,300);
glutCreateWindow("Light Rotating Torus");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMainLoop();
}
Can somebody modify it/give a hint, so it displays something?
Thanks
The most obvious problem is your UP vector. You set upx, upy and upz. That is not a valid up vector, try changing upy to 1.0f. Because of this, your torus was probably rendered out of screen.
Also, glClear doesn't take GL_DEPTH_TEST as a parameter.
Correct call should be:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Because of this, your screen was not cleared and stayed black (while you set glClearColor to be white).
And lastly, main function should always return int, never void (though it doesn't change anything in your case)

Using glutPassiveMotionFunc(); in GLUT

I have written a simple OpenGL program in C++ that displays a line joining the center of the window to the current position of the mouse pointer.
My code is :
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include<iostream>
using namespace std;
void passive(int,int);
void reshape(int,int);
void init(void);
void display(void);
void camera(void);
int x=3,y=3;
int main (int argc,char **argv) {
glutInit (&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(1364,689);
glutInitWindowPosition(0,0);
glutCreateWindow("Sample");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutPassiveMotionFunc(passive);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
void display(void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
camera();
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(x,y,0);
glEnd();
glutSwapBuffers();
}
void camera(void) {
glRotatef(0.0,1.0,0.0,0.0);
glRotatef(0.0,0.0,1.0,0.0);
glTranslated(0,0,-20);
}
void init(void) {
glEnable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_COLOR_MATERIAL);
}
void reshape(int w, int h) {
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)w/(GLfloat)h,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
}
void passive(int x1,int y1) {
x=x1; y=y1;
}
The problem I am facing is that the x and y values set in the passive() function is not correctly mapped into the screen which uses perspective projection. So the line drawn is joining the center to some other coordinate outside the screen. Any modifications to the code to get it working properly?
An easy way would be to create an orthographic projection matrix and then render all of your "2D" elements (including this line, using the screen coordinates provided by glutPassiveMotionFunc).
Something like this:
void display() {
// clear
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( ... ) // create 3D perspective projection matrix
glMatrixMode(GL_MODELVIEW);
// Render 3D content here
// Render 2D content
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, height, 0); // create 2D orthographic projection matrix with coordinate system roughly equivalent to window position
glMatrixMode(GL_MODELVIEW);
glBegin(GL_LINES);
glVertex2f( width / 2, height / 2 ); // now we can use "pixel coordinates"
glVertex2f( cursorX, cursorY );
glEnd();
...
}
Compare this to your modification of the perspective projection in your reshape method.
Obviously you'll also want to disable states that don't make sense for a "2D" rendering (like depth buffer checking, etc) but it should be pretty obvious. Take a look at this GDSE post for a discussion of how other people do this same task.

why does not my opengl program work?

I was writing a program to draw a square in my XY plane and make it rotate 360 degree, but it is not working.
void setupRC()
{
glClearColor(0,0,1,1);
glColor3f(1,0,0);
}
void timerfunc(int value)
{
glutPostRedisplay();
glutTimerFunc(33, timerfunc ,1);
}
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
static GLfloat rot = 0.0f,x =0.0f , y=10.0f , z=0.0f;
rot++;
x = 10 * cos(rot);
y = 10 * sin(rot);
glPushMatrix();
glRotatef(rot,0.0,1.0,0.0);
glBegin(GL_POLYGON);
glVertex3i(10,-10,0);
glVertex3i(10,10,0);
glVertex3i(-10,10,0);
glVertex3i(-10,-10,0);
glVertex3i(10,-10,0);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void ChangeSize(GLint w, GLint h)
{
if(h==0)
h = 1;
GLfloat aspectratio = (GLfloat)w/(GLfloat)h;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, aspectratio, -1.0, 400.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc , char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800,600);
glutInitWindowPosition(0,0);
glutCreateWindow("chelsea");
glutTimerFunc(33, timerfunc , 1);
setupRC();
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutMainLoop();
return 0;
}
I get no output, just a blank screen.
gluPerspective(60.0f, aspectratio, -1.0, 400.0);
Looks wrong, the near clipping plane needs to be a positive number
You should really use glRotatef for rotating, because your code is wrong if you want a plane rotating around XY (x and y will be 0 for some values of rot and you'll get to see nothing at all).
And you should perhaps give your polygons a color using the glColor commands.
As JB said, your gluPerspective call seems wrong, too. See this link for a reference.