Why would glShadeModel(GL_FLAT) not work? - opengl

To my understanding, GL_FLAT is supposed to make a face a single color. I can't get GL_FLAT to actually work though; it's as though my program is only using GL_SMOOTH. I'm using light sources, but both look the same.
The triangle should be just one color. Here's my scene rendering code. I no where mention GL_SMOOTH, and I've tried GL_FLAT everywhere (inits, main, before light/material definitions, before drawing, while drawing, after drawing, etc.)
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_LIGHTING);
//Light
glEnable(GL_LIGHT1);
//Define Light source ...
//Define Material ...
//Draw Triangle
glShadeModel(GL_FLAT);
glNormal3f(0,0,1);
glBegin(GL_POLYGON);
glVertex3f( -.5, -.5, 0);
glVertex3f( 0, .5, 0);
glVertex3f( .5, -.5, 0);
glEnd();
glFlush();
That's it. Everything else in the program is the bare minimum it needs to run. Is GL_FLAT broken or something?

Related

Adding a Light Source to 3D objects in OpenGL

I was wondering if anyone could help me figure out how to add a light source to my 3D objects. I have four objects that are rotating and I want the light source to be at a fixed position, and I want to be able to see lighting on the object.
I tried doing this (********):
//*******Initializing the light position
GLfloat pos[] = {-2,4,5,1};
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
//*******adding the light to the display method
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, pos);
// rectangle
glPushMatrix();
glTranslatef(0.0f, 2.5f, -8.0f);
glRotatef(angleRectangle, 0.0f, 1.0f, 0.0f);
drawRectangle();
glPopMatrix();
//small cylinder
glPushMatrix();
glTranslatef(0.0f, 2.0f, -8.0f);
glRotatef(90, 1, 0, 0);
glRotatef(anglePyramid, 0.0f, 0.0f, 1.0f);
drawCylinder(0.2, 0.7);
glPopMatrix();
//big cylinder
glPushMatrix();
glTranslatef(0.0f, 1.5f, -8.0f);
glRotatef(90, 1, 0, 0);
glRotatef(anglePyramid, 0.0f, 0.0f, 1.0f);
drawCylinder(0.7, 2.7);
glPopMatrix();
//pyramid
glPushMatrix();
glTranslatef(0.0f, -2.2f, -8.0f);
glRotatef(180, 1, 0, 0);
glRotatef(anglePyramid, 0.0f, 1.0f, 0.0f);
drawPyramid();
glPopMatrix();
glutSwapBuffers();
anglePyramid += k * 0.2f; //- is CW, + is CCW
angleRectangle += -k * 0.2f;
}
//******* Then i added these to the main method
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
However when I do this and I run the entire program, my objects turn gray, and at certain points in the rotation they turn white. And this isnt what I want. I want to keep my colorful objects, but I want to be able to see the light source on them.
Any help would be greatly appreciated. Also let me know if you need to see more of my code to figure out the issue. Thanks
When lighting (GL_LIGHTING) is enabled, then the color is taken from the material parameters (glMaterial).
If you still want to use the current color, the you have to enable GL_COLOR_MATERIAL
and to set the color material paramters (glColorMaterial):
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
See also Basic OpenGL Lighting.
But note, that drawing by glBegin/glEnd sequences, the fixed function pipeline matrix stack and fixed function pipeline per vertex light model, is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.

OpenGL texture with transparency (alpha)

I'm trying to render a texture with part opaque color and other part with transparency.
This is my draw function for the object:
void drawHighGrass(){
glDisable(GL_LIGHTING);
glClearColor(1.0, 1.0, 1.0, 1.0);
glColor4f(1.0, 1.0, 1.0, 1.0);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texturas[HIGH_GRASS]);
glPushMatrix();
//glTranslatef(1000, 0, 1000);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0, 0, 0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(100, 0, 0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(100, 40, 0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0, 40, 0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
}
The problem is that in the transparent part it's showing solid white. I can make the texture transparent by using glColor4f(1.0, 1.0, 1.0, 0.5) but that's not what I want because it makes the entire texture transparent and not only the transparent part.
I've checked, my texture files is a PNG with transparency.
Restating the solution here so others can find it easily.
Your rendering code seems to be correct, so what seems to have been the problem was the texture loading code. When loading a texture, you must be sure that you are passing in the correct flags for the internal texture pixel format (GL_RGBA8, GL_RGBA16, etc.) as well as the source image pixel format (GL_RGBA or GL_BGRA, etc.).

qt + open Gl= paintgl function for drawing a triangle

i have coded what i have read in previous post about a well known subject but i continue to get a green window without any triangle inside.
Here is my paint function :
void mGLWidget::paintGL()
{
glClearColor( Qt::green );
QSize viewport_size = size();
glViewport(0, 0, viewport_size.width(), viewport_size.height());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1, 1, -1, 1, 5, 7); // near and far match your triangle Z distance
glMatrixMode(GL_MODELVIEW);
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glTranslatef(-1.5f,0.0f,-15.0f);
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd();
// Finished Drawing The Triangle
// swapBuffers();
}
I only get a green window without any triangle. My QT is qt4.8 and opengl 4.0.
What am I doing wrong ?-\
your near and far value for your glfrustrum is quite a small range, make it 1, 100 instead of 5, 7. might not be the actual solution but it will help if its not
Your near and far value is small and you are translating the triangle very far by -15f unit that means your triangle is not draw or act as a point. So you only see the window color.

gl_lines and gl_clear in QGLWidget

I got a problem with drawing on a QGLWidget. I have several quads on the widget which I can move around when pressing some keys. As long as I just draw quads, everything works fine but now I want to add some lines using:
glBegin(GL_LINE);
glColor3f(c[0], c[1], c[2]);
glVertex3f(v1.x, v1.y, v1.z);
glVertex3f(v2.x, v2.y, v2.z);
glEnd;
The drawing also works fine, but the clearing of the glwidget doesn't work anymore. Means that I see everything I ever drawed on it. Just to mention.
I tried the same with GLUT using the same initializations and it worked, but since I have switched to Qt it doesn't work anymore.
paintGL(), resizeGL() and initializeGL() are below.
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 0.0f, 0.0f, -10.0f, -20.0f, 0.0f, 20.0f, -10.0f);
glTranslatef(0.0f, -30.0f, -40.0f);
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glRotatef(s_deg, 0.0f, 0.0f, 1.0f);
glRotatef(s_deg2, cos(DEGRAD(s_deg)), sin(DEGRAD(s_deg)), 0.0f);
float colors[8][3] = {
0.5, 0.0, 0.0,
0.0, 0.5, 0.0,
0.0, 0.0, 0.5,
1.0, 0.5, 0.5,
0.5, 1.0, 0.5,
0.5, 0.5, 1.0,
0.9, 0.9, 0.9,
0.1, 0.1, 0.1,
}; //red, green, blue, red shiny, green shiny, blue shine, light grey, dark grey
for(int i=0;i<glBoxes.size();i++) {
glBoxes.at(i).setColor(colors[i]);
glBoxes.at(i).drawCuboid();
glBoxes.at(i).drawCuboidGrid();
}
}
void GLWidget::initializeGL() {
glDepthFunc(GL_LESS);
glClearColor(0.2, 0.2, 0.2, 0.2);
glClearDepth(1.0);
}
void GLWidget::resizeGL(int width, int height) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0.0f, 0.0f, (float)width, (float)height);
glLoadIdentity();
gluPerspective(45.0f, (float)width/(float)height, 0.5f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
any Ideas?
The tokens accepted by glBegin are
GL_POINTS
GL_LINES
GL_TRIANGLES
GL_TRIANGLE_FAN
GL_TRIANGLE_STRIP
GL_QUADS
GL_QUAD_STRIP
and
GL_POLYGON
The token used by you, GL_LINE (not the missing trailing S) is not valid for glBegin.
The statement glEnd; will evaluate the address of the function glEnd and silently discard the result. Could it be, that you have a Pascal or Delphi background? In C like languages you have to add a matched pair of parentheses to make it a function call. Functions that don't take a parameter are called with an empty pair of parentheses. E.g. in your case glEnd();.
Not related to your problem. All of the code in resizeGL should go to the head of paintGL (use the widget's width() and height() getters). Also what you have in initializeGL belongs to paintGL.
The proper use of initializeGL is to do one-time initialization, like loading textures, and shaders, preparing FBOs and such.
resizeGL is meant to re-/initialize stuff that depends on the window's size and which is quite time consuming to change, like renderbuffers and/or textures used as attachment in FBOs used for window sized post-processing or similar. Setting the projection matrix does not belong there, and neither does the viewport. Those go into paintGL.
glDepthFunc, glClearColor and glClearDepth directly influence the drawing process and as such belong with the drawing code.
Also you should not use the immediate mode (glBegin … glEnd) at all. It's been outdated ever since OpenGL-1.1 was released over 15 years ago. Use Vertex Arrays, with the possible addition of Buffer Objects.
glEnd; should be glEnd();. This may actually fix your problem.
GL_LINE isn't a valid token for glBegin. To draw lines, you need GL_LINES (that's subtle, and you're in good company - this is a common mistake).
GL_LINE is used to control how polygons are rendered, which is controlled by the glPolygonMode function.
It must be GL_LINES instead of GL_LINE. The symbols accepted by glBegin are plural (i.e. GL_QUADS, GL_LINE_STRIPS...).

glColor coloring all textures

I'm fairly new to OpenGL so maybe the answer will be obvious. I am currently trying to make a blue circle using GL_TRIANGLE_FAN in C++. My problem is that when I set the color using glColor4f, it sets all my other textures to have a blue color over them such as shown below (this is supposed to be silvery metal).
I draw the textures using the method shown below.
glLoadIdentity();
glTranslatef(x,y,0);
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
I'm not sure whether I just have to clear a flag for it to work, but I've been stuck for a few days now.
After drawing your blue circle, you should set the color back to white (default value) using glColor4f(1.f, 1.f, 1.f, 1.f);. Please note that by default the texture gets modulated by the currently set color (blue in your case) and that's the reason why your silver material gets a bluish tone (final color = blue color * texture color).
Unbind the texture and set the color back to white after you're done drawing:
glLoadIdentity();
glTranslatef(x,y,0);
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
glColor4f(1, 1, 1, 1);
glBindTexture(GL_TEXTURE_2D, 0);
And if you aren't rendering textures on the next object, disable texturing:
glDisable( GL_TEXTURE_2D );
When You have enabled glEnable(GL_COLOR_MATERIAL) and changed a color by glColor, then all your textures will be affected by this color. This is because by default the texture is displayed in modulate mode (glColor multiplied by texture colors).
If you don't have lighting enabled, to restore the original texture color is simple - just set glColor to white: glColor4f(1.0, 1.0, 1.0, 1.0).
The problem comes, when you have lighting enabled on your texture. Then, setting the color to white or changing texture mode to REPLACE doesn't help at all - your lighting effects will be removed! (which nobody seems to be noticing!) The reason for this is because with enabling GL_COLOR_MATERIAL by default you're getting behaviour, where glColor commands changes both Ambient and Diffuse colours at the same time - thus your ambient and diffuse material properties will be affected (lost). So all you have to do, to restore the material state (and thus lighting effects), which you had before applying glEnable(GL_COLOR_MATERIAL), is the following:
glDisable(GL_COLOR_MATERIAL); //disable color influence
GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; //default material has this ambient color!
GLfloat diffuse[] = { 0.8f ,0.8f ,0.8f, 1.0f }; //default material has this diffuse color!
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); //restore default material ambient color
glMaterialfv(GL_FRONT, GL_AMBIENT, diffuse); //restore default material diffuse color
Please note, what are the default ambient and diffuse colors for default material! There is no pure white there!
This way, all the textures, that you use from this point will be drawn as intended (with the correct color and lighting effects).
Took me some time to find this stuff, so I suppose it's nice to mention it here.
Before binding a texture, you need to enable it. And normally, you should disabled it when you are done with it. Something like this :
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
glDisable( GL_TEXTURE_2D );