Related
I read similar suggested questions and their solutions, but could not find an answer.
I'm trying to draw a scene with an isometric view in OpenGL.
Draw func:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
glPopMatrix();
In the end, I get this result. The camera does have an isometric projection, but for some reason polygons are clipped.
If I add glTranslatef(-0.8f, 0, -0.8f) before drawing the quad, the result is as follows:
The problem is that I don't apply any optimization to OpenGL render. But why do polygons have to be cut off?
The polygons are clipped by the near or far plane of the viewing volume.
When you do not set a projection matrix, then view space, clip space and normalized device space are the same. The normalized device space is a unique cube with the left, bottom, near of (-1, -1, -1) and right, top, far of (1, 1, 1). All the geometry which is not inside this cube is clipped.
Actually you draw a quad with a side length of 1. One vertex of the quad is at the origin of the view (0, 0, 0). The quad is rotated around the origin by glRotate. Since the length of the diagonal of the quad is sqrt(2.0), one vertex of the rotated quad is clipped by either the near plane or the far plane.
If you construct and rotate a quad whose center is (0, 0 ,0), it will not be clipped, because the length form the center to each vertex is sqrt(2.0)/2.0. That is less than 1 (distance to near and far plane form the center of the viewing volume)
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-0.5f, 0.0f, -0.5f);
glVertex3f( 0.5f, 0.0f, -0.5f);
glVertex3f( 0.5f, 0.0f, 0.5f);
glVertex3f(-0.5f, 0.0f, 0.5f);
glEnd();
respectively
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
glTranslate(-0.5f, 0.0f, -0.5f);
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
Alternatively you can set an Orthographic projection, which enlarges the viewing volume by glOrtho:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
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).
In many demoscene productions you can see the effect of flashing white screen when percussion beat happens (https://www.youtube.com/watch?v=2SbGffUzHSs). I have coded such effect and in works fine. Code of fading function (it ie executed in the render() function):
void fade()
{
glLoadIdentity();
glTranslatef (0.0f, 0.0f, -5.0f);
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE);
if (alpha <= 1)
{
glColor4f(1.0, 1.0, 1.0, alpha);
glBegin(GL_QUADS);
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();
alpha += 0.0025;
}
else
{
glColor4f(1.0, 1.0, 1.0, alpha_inv);
glBegin(GL_QUADS);
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();
alpha_inv -= 0.0025;
}
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
return;
}
I have two issues:
I need some kind of parameter for white flash duration control (ie. 1st flash lasts 1 second, 2 flash lasts only 0,25 second)
The effect has to have the same speed on each computer (slow and fast).
What can I do in the code above to achieve it?
Aha! It seems my problem was that my zNear value given to gluPerspective had to be greater than 0, and I had to enable the depth buffer to get it working. Ive updated the code below to be working.
I've tried to do this a lot, and always thought I was defining my quad vertices in the wrong order, but now, I know its something else.
I've tried enabling Culling, changing frontFace to clockwise, disabling Blending, adding normals, but I always get a cube that looks like this;
Hopefully, you won't even have to look at my code to know what the problem is, as it wasn't too hard to get it like this.
If you don't immediately know what the problem is, here's the code used to set up and draw the cube.
// FIXED CODE.
// reshape, called on init, and window resize
void reshape(int w, int h) {
scrw=w;
scrh=h;
glClearColor(0.8,0.8,0.8,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(cfov,(float) scrw/ (float) scrh,1,1000); // this is also a part of the fix.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST); // this is a part of the fix
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glViewport(0,0,scrw,scrh);
}
// drawQuadCube(), called every frame.
void drawQuadCube() {
glPushMatrix();
glTranslated(0.5,0.5,0.5);
glRotated(xangle,0,1,0);
glRotated(yangle,1,0,0);
glRotated(zangle,0,0,1);
glTranslated(-0.5,-0.5,-0.5);
glBegin(GL_QUADS);
// bottom
glColor4ub(30,30,255,255);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// top
glColor4ub(40,40,255,255);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// left
glColor4ub(60,60,255,255);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
// right
glColor4ub(60,60,200,255);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
// near
glColor4ub(70,70,100,255);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// far
glColor4ub(20,20,90,255);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glNormal3f(0,0,0);
glNormal3f(0,0,1);
glNormal3f(0,1,0);
glNormal3f(1,0,0);
glNormal3f(1,0,1);
glNormal3f(1,1,0);
glNormal3f(1,1,1);
glNormal3f(0,1,1);
glEnd();
glPopMatrix();
}
// if that isn't enough, this is the function used to set up the view.
void setView(void) {
glLoadIdentity();
gluLookAt(0.5,0.5,-5,0.5,0.5,0.5,0,1,0);
}
Your winding mode is incorrect.
glFrontFace defaults to GL_CCW, but your "front-facing quad", in this example the "near" one, is wound clockwise (from the frame of reference of your camera position; note that it's at negative Z, and looking along positive Z). glCullFace defaults to GL_BACK, so it's getting culled. Set it correctly with:
glFrontFace(GL_CW);
See also http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml
Once you've got that setup, then you'll want to enable depth-buffering, so your quads overpaint correctly without relying on paint ordering. See: http://www.opengl.org/archives/resources/faq/technical/depthbuffer.htm
Try:
glCullFace(GL_FRONT);
See http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml
or:
glEnable(GL_CULL_FACE);
See http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
You didn't specify what windowing mechanism you were using but incase you are using glut, don't forget to set the GLUT_DEPTH flag while creating the window. Thats a simple common error frequently overlooked.