I have been attempting to use OpenGL with C++ lately and I have come a cross a problem when trying to render a cube with lighting, but it doesn't appear I believe this is due to some kinda of clipping error.
Here is my code. The initialization function:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING); //Enable lighting
glEnable(GL_LIGHT0); //Enable light #0
glEnable(GL_LIGHT1); //Enable light #1
glEnable(GL_NORMALIZE); //Automatically normalize normals
and here is the draw code
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.0f, 0.0f, -8.0f);
//Add ambient light
GLfloat ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f}; //Color (0.2, 0.2, 0.2)
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
//Add positioned light
GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color (0.5, 0.5, 0.5)
GLfloat lightPos0[] = {4.0f, 0.0f, 8.0f, 1.0f}; //Positioned at (4, 0, 8)
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
//Add directed light
GLfloat lightColor1[] = {0.5f, 0.2f, 0.2f, 1.0f}; //Color (0.5, 0.2, 0.2)
//Coming from the direction (-1, 0.5, 0.5)
GLfloat lightPos1[] = {-1.0f, 0.5f, 0.5f, 0.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
glRotatef(Rotation, 0.0f, 1.0f, 0.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
//Front
glNormal3f(0.0f, 0.0f, 1.0f);
//glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, -1.0f, 1.5f);
//glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, -1.0f, 1.5f);
//glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, 1.0f, 1.5f);
//glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, 1.0f, 1.5f);
//Right
glNormal3f(1.0f, 0.0f, 0.0f);
//glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, -1.0f, -1.5f);
//glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, 1.0f, -1.5f);
//glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, 1.0f, 1.5f);
//glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, -1.0f, 1.5f);
//Back
glNormal3f(0.0f, 0.0f, -1.0f);
//glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, -1.0f, -1.5f);
//glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, 1.0f, -1.5f);
//glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, 1.0f, -1.5f);
//glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, -1.0f, -1.5f);
//Left
glNormal3f(-1.0f, 0.0f, 0.0f);
//glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, -1.0f, -1.5f);
//glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, -1.0f, 1.5f);
//glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, 1.0f, 1.5f);
//glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, 1.0f, -1.5f);
glEnd();
SwapBuffers(hDC);
Sleep (1);
after following the advice of Keith i attempted to use the gluLookAt like this:
void gluLookAt ( 10.0 , 10.0 , 10.0 , 1.5, -1.0, 1.5, 0.0, 0.0, 1.0 );
but I get an error
|74|error: variable or field `gluLookAt' declared void|
You may need to define the projection matrix.
This can be done with, for example, gluLookAt()
After your edit: gluLookAt is a function just like glVertex3f and such. Therefore invoke it by just calling:
gluLookAt(10.0 , 10.0 , 10.0 , 1.5, -1.0, 1.5, 0.0, 0.0, 1.0 );
Note that there is no void involved in this line of code!
What the compiler sees if there is a void in front of this line is a variable declaration named gluLookAt of type void initialized (constructed) with a bunch of doubles.
Related
This code is to draw one pyramid and one cube. I am trying to colour them using GL_SMOOTH type by glShadeModel. But the result is that only the pyramid can be smooth while another one cube was only colored like a GL_FLAT one.
It seems that there are some problems with the normal vectors but I was poor at this aspect.
Here are my codes below:
void initGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_SMOOTH); // Enable smooth shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(1.5f, 0.0f, -7.0f);
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd(); // End of drawing color-cube
// Render a pyramid consists of 4 triangles
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(-1.5f, 0.0f, -6.0f); // Move left and into the screen
glBegin(GL_TRIANGLES); // Begin drawing the pyramid with 4 triangles
// Front
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
// Right
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
// Back
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f);
// Left
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd(); // Done drawing the pyramid
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
Can someone tell me how could this happen?
When you draw the pyramid, then you've one color associated to each vertex coordinate of the triangle primitives. e.g:
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
This causes that the colors of the vertices (corner) are interpolated on the triangle.
When you draw the cube then you've set one color fro each quad. Each corner of the quad is associated to the same color:
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
This causes that the entire quad primitiv is uniform colored. If you want a color gradient, then you've to associate different colors to the vertices (corners).
I'm trying to draw a "transparent" cube (with only edges) and place a pyramid inside this cube, the problem is that the edges of the cube are drawing over pyramid when I rotate it.
Here is an example
I understand why this is happening (because I draw pyramid first and then a cube), but I want that these edges to not be drawn over the pyramid when this is not needed.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QOpenGLWindow>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <QTimer>
#ifdef _DEBUG
# include <QDebug>
#endif
class MainWindow: public QOpenGLWindow
{
Q_OBJECT
public:
MainWindow();
private:
QOpenGLContext *m_context;
QTimer m_timer;
GLfloat m_angle;
private slots:
void rotate();
protected:
void initializeGL() override;
void paintGL() override;
void paintEvent(QPaintEvent *event) override;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow():
QOpenGLWindow(),
m_angle(0.0f)
{
QSurfaceFormat sf;
sf.setProfile(QSurfaceFormat::CompatibilityProfile);
sf.setVersion(2, 1);
setFormat(sf);
setSurfaceType(QWindow::OpenGLSurface);
create();
m_context = new QOpenGLContext();
m_context->setFormat(sf);
m_context->create();
m_context->makeCurrent(this);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(rotate()));
m_timer.start(33);
}
void MainWindow::rotate()
{
m_angle += 0.5f;
if (m_angle >= 360.0f) {
m_angle = 0.0f;
}
update();
}
void MainWindow::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
void MainWindow::paintGL()
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
glScalef(0.3f, 0.3f, 0.3f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// bottom
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
// The cube (only edges)
glScalef(1.5f, 1.5f, 1.5f);
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_LINE_LOOP);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glEnd();
glFlush();
}
void MainWindow::paintEvent(QPaintEvent*)
{
paintGL();
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.resize(480, 480);
w.show();
return a.exec();
}
... after that I got vice-versa behavior, take a look at this screenshot It seems like the front edges behave like back edges.
The triangles of your pyramid are set clockwise, but default, counterclockwise polygons are taken to be front-facing. Set glFrontFace(GL_CW) or change the order of glVertex3f.
Could someone explain me why triangle is rendering over quad please ?
When Depth Testing is active, the fragments will be displayed depending on their depth. The depth value from the fragment is compared to the depth value from the matching sample currently in the framebuffer. The conditional test is specified by the function glDepthFunc. The initial value of glDepthFunc is GL_LESS.
In your example the depth of the triangle's fragments is LESS than that of the quad's fragments, so the triangle is over the quad.
Setting minimal depth buffer didn't changed anything for me (likely because platform setting was already 24, but checking those defaults is not without merit). The problem is that displayed order of cube's edges still look wrong: the edge that supposed to be closer is painted over by pyramid.
Because you don't do anything about visibility of edges it causes illusion that cube must be rotating in direction opposite and perpendicular to rotation of pyramid.
The problem is that it's pyramid which is actually wrong. Let me prove that:
glBegin(GL_QUADS);//(GL_LINE_LOOP);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
Resulting image is:
Cube rotates in supposed direction, it isn't inside out. That means that pyramid is. One reason of that is that we actually see back faces, not front ones.
If I convert your code to emulate transparent pyramid, , but save default culling settings:
void MainWindow::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
/*...*/
glFrontFace(GL_CCW);
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 0.3f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(0.0f, 1.0f, 0.0f, 0.3f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor4f(0.0f, 0.0f, 1.0f, 0.3f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(1.0f, 1.0f, 0.0f, 0.3f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// bottom
glColor4f(0.0f, 1.0f, 1.0f, 0.3f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
glFrontFace(GL_CW);
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 0.6f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(0.0f, 1.0f, 0.0f, 0.6f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor4f(0.0f, 0.0f, 1.0f, 0.6f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor4f(1.0f, 1.0f, 0.0f, 0.6f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// bottom
glColor4f(0.0f, 1.0f, 1.0f, 0.6f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
I get image
I still see how pyramid rotates, all of its edges and that line of cube that is "behind" is clipped (because blending does nothing to depth test).
But now if you look at the "bold" faces of pyramid - I intentionally made faces that are invisible without blending bold by giving them larger alpha value - you'll see that they rotate properly, in same direction as cube does. That means that your mesh, the pyramid, is actually inverted, "inside out". With non-convex figures that would be more obvious, with convex ones that creates illusion of opposite rotation.
All you should do is change order of vertices or switch to GL_CW for pyramid (GL_CCW is default).
I surmise that this is expected look of the pyramid, if the face colors are taken in account. If it isn't, that means that you assumed that vertices with greater Z-coordinate is further away from projection plane. With Identity projection matrix and GL_LESS depth test function it's opposite. Be advised, if you switch direction of only one axis, that literally inverts all rules that related to direction of rotation, counterclockwise becomes clockwise.
NB: Trick I used for transparency illusion doesn't work that well with non-convex figures. Why? To use color blending you have to draw faces in order of their depth test doing this manually. My dirty trick does draw all faces twice, but culling removes those which face camera during first pass, and removes those which face away during second pass. For non-convex that doesn't match the order - there are faces that face camera but are further away than some "hidden" ones, wrong order. More work is required. Usage of flexible pipeline really changes how OpenGL can handle this.
I've finally done it:
#include "mainwindow.h"
MainWindow::MainWindow():
QOpenGLWindow(),
m_angle(0.0f)
{
QSurfaceFormat sf;
sf.setProfile(QSurfaceFormat::CompatibilityProfile);
sf.setDepthBufferSize(24);
sf.setVersion(2, 1);
setSurfaceType(QWindow::OpenGLSurface);
setFormat(sf);
create();
m_context = new QOpenGLContext(this);
m_context->setFormat(sf);
m_context->create();
m_context->makeCurrent(this);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(rotate()));
m_timer.start(33);
}
void MainWindow::rotate()
{
m_angle += 0.5f;
if (m_angle >= 360.0f) {
m_angle = 0.0f;
}
update();
}
void MainWindow::initializeGL()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearDepth(-1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
}
void MainWindow::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// The Pyramid
glLoadIdentity();
glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
glScalef(0.33f, 0.33f, 0.33f);
glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_TRIANGLES);
// Front
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
// Left
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
// Bottom
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
// The Cube (edges)
glLoadIdentity();
glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
glScalef(0.5f, 0.5f, 0.5f);
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
// Front
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Back
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
// Left
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
// Right
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glEnd();
glFlush();
}
void MainWindow::paintEvent(QPaintEvent*)
{
paintGL();
}
Probably this solution is far from ideal, but it does exactly what I need (any tips would be appreciated).
demo image
I'd like to thank #Swift - Friday Pie and #Asaq for such detailed answers which helped me a bit more to understand how opengl works.
If anyone is interested - I'm on Linux (Fedora 28), graphic card is Intel HD Graphics 530 (Skylake GT2).
I have to rotate an object in front of a background. I have to light it with a spotlight and show the shadow on the object and on the background.
My problem is when I rotate the object the shadow doesn't change.
Here is my code:
#include "stdafx.h"
#include <windows.h>
#include <GL/glut.h>
#include <stdlib.h>
GLfloat qaBlack[] = { 0.0, 0.0, 0.0, 1.0 }; //Black Color
GLfloat qaGreen[] = { 0.0, 1.0, 0.0, 1.0 }; //Green Color
GLfloat qaWhite[] = { 1.0, 1.0, 1.0, 1.0 }; //White Color
GLfloat qaRed[] = { 1.0, 0.0, 0.0, 1.0 }; //White Color
GLfloat angleShape = 0.0f;
void CreateShape()
{
// Set material properties
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, qaGreen);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, qaGreen);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, qaWhite);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20);
glBegin(GL_TRIANGLES); // Begin drawing the pyramid with 4 triangles
// Front
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
// Right
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
// Back
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f);
// Left
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glEnd(); // Done drawing the pyramid
}
void Spotlight()
{
glEnable(GL_LIGHTING);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 15.f);
glLightModelf(GL_LIGHT_MODEL_AMBIENT, 0.2f);
GLfloat light0Pos[] = { -3,-3,10,1 };
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
GLfloat light0Diffuse[] = { 1,1,1 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diffuse);
GLfloat light0Specular[] = { 1,1,1 };
glLightfv(GL_LIGHT0, GL_SPECULAR, light0Specular);
glEnable(GL_LIGHT0);
//glDisable(GL_LIGHTING);
}
void display2()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Spotlight();
glTranslatef(-0.5f, 0.0f, -6.0f);
glRotatef(angleShape, 1.0f, 1.0f, 0.0f);
CreateShape();
angleShape -= 5.f;
glLoadIdentity();
glTranslatef(2.0f, 2.5f, -7.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 1.0f, 0.5f);
glVertex3f(0.5f, -3.0f, -5.0f);
glVertex3f(-7.0f, -6.0f, -5.0f);
glVertex3f(1.0f, -6.0f, -5.0f);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(-6.5f, -3.0f, -5.0f);
glVertex3f(0.5f, -3.0f, -5.0f);
glVertex3f(-7.0f, -6.0f, -5.0f);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(-6.5f, -3.0f, -5.0f);
glVertex3f(0.5f, -3.0f, -5.0f);
glVertex3f(0.5f, 2.0f, -5.0f);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(-6.5f, -3.0f, -5.0f);
glVertex3f(-6.5f, 2.0f, -5.0f);
glVertex3f(0.5f, 2.0f, -5.0f);
glEnd();
glutSwapBuffers();
}
void initGL() {
glClearColor(0.0, 0.7, 1.0, 1.0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void reshape(GLsizei width, GLsizei height) {
if (height == 0) height = 1;
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowPosition(50, 50);
glutInitWindowSize(640, 480);
glutCreateWindow("OpenGL #1");
glutDisplayFunc(display2);
glutReshapeFunc(reshape);
initGL();
glutMainLoop();
return 0;
}
This question already has an answer here:
No spot of light on cube
(1 answer)
Closed 5 years ago.
I created a 3D scene where I added a light source and a 3D box, which should be illuminated by the light source. Both Ambient and Diffuse colors seem to work properly, but the specular color does not seem to be calculated correctly. When moving the camera in front of the side with the light source, no specular 'dot' can be seen. But when i move the camera towards the top of the cube and look at the origin (0, 0, 0), a faint specular 'dot' can be seen on the illuminated side of the cube.
My question is the following: what am I doing wrong?
Everything in the code below happens in the modelMatrix, and the _nav member manages the camera movement.
Here's the code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(_nav->getCamPosx(), _nav->getCamPosy(), _nav->getCamPosz(),
_nav->getCamViewx(), _nav->getCamViewy(), _nav->getCamViewz(),
_nav->getCamUpx(), _nav->getCamUpy(), _nav->getCamUpz());
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat qaAmbientLight[] = {0.2f, 0.2f, 0.2f, 1.0f};
GLfloat qaDiffuseLight[] = {0.8f, 0.8f, 0.8f, 1.0f};
GLfloat qaSpecularLight[] = {1.0f, 0.0f, 0.0f, 1.0f}; //red for testing
glLightfv(GL_LIGHT0, GL_AMBIENT, qaAmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, qaDiffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, qaSpecularLight);
// Set the light position
GLfloat qaLightPosition[] = {0.5f, 0.5f, 1.2f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition);
GLfloat cyan[] = {0.f, .8f, .8f, 1.f};
GLfloat white[] = {0.8f, 0.8f, 0.8f, 1.0f};
//GLfloat dark[] = {0.0, 0.0, 0.0, 1.0};
glMaterialfv(GL_FRONT, GL_AMBIENT, cyan);
glMaterialfv(GL_FRONT, GL_DIFFUSE, cyan);
glMaterialfv(GL_FRONT, GL_SPECULAR, white);
GLfloat shininess[] = {80};
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
glBegin(GL_QUADS);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(0.1f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.1f, 0.0f, 1.0f);
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(0.1f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 0.1f);
glVertex3f(1.0f, 1.0f, 0.1f);
glVertex3f(0.1f, 1.0f, 0.1f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(0.1f, 0.0f, 0.1f);
glVertex3f(0.1f, 0.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 0.1f);
//face that gets illuminated
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.1f, 0.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.1f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.1f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.1f, 1.0f, 0.1f);
glVertex3f(1.0f, 1.0f, 0.1f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.1f, 1.0f, 1.0f);
glEnd();
Facing cube side with light source:
Top view of the cube, the faint red is the specular 'dot':
In fixed function OpenGL illumination is calculated only at the vertices and the resulting colour then interpolated across the faces. For specular reflexes to show up then you need sufficiently many vertices so that there's actually enough spatial sampling.
Obviously it's not very efficient to subdivide meshes, just to provide enough sampling points for illumination purposes. So over the years a number of per-pixel-illumination techniques were developed. It's pretty straightforward to implement using shaders ( https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php ).
I want to set a light in my 3d world, positioned in a corner and when I move with my mouse I want it to stay there and just be.
When I use the function from glut: glutSolidSphere, everything looks okay.
But when I add a quad in my world and I move with my mouse, the lighting on the quad changes. Any idea how to solve this?
void World::paint(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
float no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
float mat_ambient[] = {0.7f, 0.7f, 0.7f, 1.0f};
float mat_ambient_color[] = {0.8f, 0.8f, 0.2f, 1.0f};
float mat_diffuse[] = {0.1f, 0.5f, 0.8f, 1.0f};
float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
float no_shininess = 0.0f;
float low_shininess = 5.0f;
float high_shininess = 100.0f;
float mat_emission[] = {0.3f, 0.2f, 0.2f, 0.0f};
camera->setup();
light->assignComponentsToGLLightX();
glEnable(GL_LIGHTING);
glMatrixMode( GL_MODELVIEW );
// WORKS
float temp[] = {0.7f, 0.0f, 0.0f, 1.0f};
glPushMatrix();
glTranslatef(3.75f, 3.0f, 0.0f);
glMaterialfv(GL_FRONT, GL_AMBIENT, temp);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, low_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glutSolidSphere( 3.0, 25, 25 );
glPopMatrix();
// Doesn't work
glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.0f);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, low_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glBegin(GL_QUADS);
//Front
//glNormal3f(0.0f, 0.0f, 1.0f);
glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, -1.0f, 1.5f);
glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, -1.0f, 1.5f);
glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, 1.0f, 1.5f);
glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, 1.0f, 1.5f);
//Right
//glNormal3f(1.0f, 0.0f, 0.0f);
glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, -1.0f, -1.5f);
glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, 1.0f, -1.5f);
glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, 1.0f, 1.5f);
glNormal3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.5f, -1.0f, 1.5f);
//Back
//glNormal3f(0.0f, 0.0f, -1.0f);
glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, -1.0f, -1.5f);
glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, 1.0f, -1.5f);
glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, 1.0f, -1.5f);
glNormal3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.5f, -1.0f, -1.5f);
//Left
//glNormal3f(-1.0f, 0.0f, 0.0f);
glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, -1.0f, -1.5f);
glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, -1.0f, 1.5f);
glNormal3f(-1.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, 1.0f, 1.5f);
glNormal3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.5f, 1.0f, -1.5f);
glEnd();
glPopMatrix();
void Camera::setup() const
{
glRotatef(_rotX, 1.0,0.0,0.0);
glRotatef(_rotY, 0.0,1.0,0.0);
glTranslated(-_moveX,-_moveY,-_moveZ);
gluLookAt(3.0 , 5.0 , 25.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0 );
}
void Light::assignComponentsToGLLightX() const
{
glLightfv(_light, GL_AMBIENT, _ambientLight);
glLightfv(_light, GL_DIFFUSE, _diffuseLight);
glLightfv(_light, GL_SPECULAR, _specularLight);
glLightfv(_light, GL_POSITION, _position);
}
So I setted the light call after the camera_setup()
But now the quad is still not working as I want it to. The light still changes and I am pretty sure that my normals are correct (checked them twice).
I was thinking, is this possible because I don't change my _camPosX, Y, Z values when I move/rotate?
Calling gluLookAt before glRotate / glTranslate should help...
Other thoughts :
call glMatrixMode and glLoadIdentity only once, in camera::setup.
don't call glRotate and glTranslate in camera::setup. This has nothing to do with the camera. This is your object's tranformation
Wrap glRotate and glTranslate inside glPushMatrix/glPopMatrix. This way, the next time you draw an object, transformations won't be cummulated.
glTranslatef(0.0f, 0.0f, 0.0f) is useless. It means : add a null displacement to the current matrix. In other words: don't do anything
wrapping pushmatrix/popmatrix around this is thus useless
As datenwolf said, I don't see where you actually indicate the light's position
You must set the lights' positions after moving the world / setting the camera i.e. add
glLightfv(GL_LIGHT0+n, GL_POSITION, light_position)
calls right after
camera->setup();