I'm making a skybox in openGL c++, now I followed some tutorials on skyboxes, I have the image's all set up but my skybox doesn't get drawn at all! (I only see black opengl background)
So here is my code, what can be the problem? I'm looking at it for hours and can't find a thing, I'm new at openGL so if you spot any bad code please do tell! Thanks!
#include <iostream>
#include <stdlib.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include "imageloader.h"
using namespace std;
//angle of rotation
GLfloat xpos = 0, ypos = 0, zpos = 0, xrot = 0, yrot = 0, angle=0.0;
GLuint _textureId; //The OpenGL id of the texture
GLuint _skybox[5];
float lastx, lasty;
bool leftMouseButton = false;
float PI = 3.141592654f;
//Makes the image into a texture, and returns the id of the texture
GLuint __loadTexture(Image* image) {
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
image->width, image->height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
image->pixels);
return textureId;
}
GLuint __loadMipmappedTexture(Image *image) {
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
gluBuild2DMipmaps(GL_TEXTURE_2D,
GL_RGB,
image->width, image->height,
GL_RGB,
GL_UNSIGNED_BYTE,
image->pixels);
return textureId;
}
void initRendering() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_CULL_FACE);
glShadeModel (GL_SMOOTH); //set the shader to smooth shader
Image* image = loadBMP("artesis.bmp");
_textureId = __loadMipmappedTexture(image);
image = loadBMP("skybox/deep_ft.bmp");
_skybox[0] = __loadMipmappedTexture(image);
image = loadBMP("skybox/deep_lf.bmp");
_skybox[1] = __loadMipmappedTexture(image);
image = loadBMP("skybox/deep_bk.bmp");
_skybox[2] = __loadMipmappedTexture(image);
image = loadBMP("skybox/deep_rt.bmp");
_skybox[3] = __loadMipmappedTexture(image);
image = loadBMP("skybox/deep_up.bmp");
_skybox[4] = __loadMipmappedTexture(image);
image = loadBMP("skybox/deep_dn.bmp");
_skybox[5] = __loadMipmappedTexture(image);
delete image;
}
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 100.0);
glViewport (0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
void mouseMovement(int x, int y) {
if (leftMouseButton == true)
{
GLfloat diffx = (x-lastx)/20; //check the difference between the current x and the last x position
GLfloat diffy = (y-lasty)/20; //check the difference between the current y and the last y position
lastx = x; //set lastx to the current x position
lasty = y; //set lasty to the current y position
xrot += (float) diffy; //set the xrot to xrot with the addition of the difference in the y position
yrot += (float) diffx; //set the xrot to yrot with the addition of the difference in the x position
}
else if( leftMouseButton == false)
{
GLfloat diffx = x-lastx; //check the difference between the current x and the last x position
GLfloat diffy = y-lasty; //check the difference between the current y and the last y position
lastx = x; //set lastx to the current x position
lasty = y; //set lasty to the current y position
}
}
void mouseButtons(int button, int state, int x, int y) {
if ((state == GLUT_DOWN) && (button == GLUT_LEFT_BUTTON))
{
leftMouseButton = true;
}
else if ((state == GLUT_DOWN) && (button == GLUT_RIGHT_BUTTON))
{
leftMouseButton = false;
}
}
void drawGrid(float size, float step)
{
// disable lighting
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(0.3f, 0.3f, 0.3f);
for(float i=step; i <= size; i+= step)
{
glVertex3f(-size, 0, i); // lines parallel to X-axis
glVertex3f( size, 0, i);
glVertex3f(-size, 0, -i); // lines parallel to X-axis
glVertex3f( size, 0, -i);
glVertex3f( i, 0, -size); // lines parallel to Z-axis
glVertex3f( i, 0, size);
glVertex3f(-i, 0, -size); // lines parallel to Z-axis
glVertex3f(-i, 0, size);
}
// x-axis
glColor3f(0.5f, 0, 0);
glVertex3f(-size, 0, 0);
glVertex3f( size, 0, 0);
// z-axis
glColor3f(0,0,0.5f);
glVertex3f(0, 0, -size);
glVertex3f(0, 0, size);
glEnd();
// enable lighting back
glEnable(GL_LIGHTING);
}
void keyboard (unsigned char key, int x, int y) {
float xrotrad, yrotrad;
switch(key) {
case 'a':
xrot += 1;
if(xrot > 360) xrot -= 360;
break;
case 'w':
xrot -= 1;
if(xrot < -360) xrot += 360;
break;
case 'z':
yrotrad = (yrot / 180 * PI);
xrotrad = (xrot / 180 * PI);
xpos += float(sin(yrotrad));
zpos -= float(cos(yrotrad));
ypos -= float(sin(xrotrad));
break;
case 's':
yrotrad = (yrot / 180 * PI);
xrotrad = (xrot / 180 * PI);
xpos -= float(sin(yrotrad));
zpos += float(cos(yrotrad));
ypos += float(sin(xrotrad));
break;
case 'd':
yrot += 1;
if (yrot >360) yrot -= 360;
break;
case 'q':
yrot -= 1;
if (yrot < -360)yrot += 360;
break;
case 27:
exit(0);
break;
}
}
void camera (void) {
glRotatef(xrot,1.0,0.0,0.0); //rotate our camera on teh x-axis (left and right)
glRotatef(yrot,0.0,1.0,0.0); //rotate our camera on the y-axis (up and down)
glTranslated(-xpos,-ypos,-zpos); //translate the screen to the position of our camera
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat lightKa[] = {.0f, .0f, .0f, 1.0f}; // ambient light
GLfloat lightKd[] = {.9f, .9f, .9f, 1.0f}; // diffuse light
GLfloat lightKs[] = {1, 1, 1, 1}; // specular light
glLightfv(GL_LIGHT0, GL_AMBIENT, lightKa);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightKd);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightKs);
// position the light
float lightPos[4] = {0, 10, 10, 0};
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
camera();
//call the skybox
// Store the current matrix
glPushMatrix();
// Reset and transform the matrix.
glLoadIdentity();
/* EDIT: I really dont know how to set gluLookAt, I guess it should be the camera positions??? */
gluLookAt(
0.0,0.0,0.0,
0.1, 0.0, 0.1,
0.0,1.0,0.0);
// Enable/Disable features
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
// Just in case we set all vertices to white.
glColor4f(1,1,1,1);
// Render the front quad
glBindTexture(GL_TEXTURE_2D, _skybox[0]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f( 0.5f, -0.5f, -0.5f );
glTexCoord2f(1, 0); glVertex3f( -0.5f, -0.5f, -0.5f );
glTexCoord2f(1, 1); glVertex3f( -0.5f, 0.5f, -0.5f );
glTexCoord2f(0, 1); glVertex3f( 0.5f, 0.5f, -0.5f );
glEnd();
// Render the left quad
glBindTexture(GL_TEXTURE_2D, _skybox[1]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f( 0.5f, -0.5f, 0.5f );
glTexCoord2f(1, 0); glVertex3f( 0.5f, -0.5f, -0.5f );
glTexCoord2f(1, 1); glVertex3f( 0.5f, 0.5f, -0.5f );
glTexCoord2f(0, 1); glVertex3f( 0.5f, 0.5f, 0.5f );
glEnd();
// Render the back quad
glBindTexture(GL_TEXTURE_2D, _skybox[2]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f( -0.5f, -0.5f, 0.5f );
glTexCoord2f(1, 0); glVertex3f( 0.5f, -0.5f, 0.5f );
glTexCoord2f(1, 1); glVertex3f( 0.5f, 0.5f, 0.5f );
glTexCoord2f(0, 1); glVertex3f( -0.5f, 0.5f, 0.5f );
glEnd();
// Render the right quad
glBindTexture(GL_TEXTURE_2D, _skybox[3]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f( -0.5f, -0.5f, -0.5f );
glTexCoord2f(1, 0); glVertex3f( -0.5f, -0.5f, 0.5f );
glTexCoord2f(1, 1); glVertex3f( -0.5f, 0.5f, 0.5f );
glTexCoord2f(0, 1); glVertex3f( -0.5f, 0.5f, -0.5f );
glEnd();
// Render the top quad
glBindTexture(GL_TEXTURE_2D, _skybox[4]);
glBegin(GL_QUADS);
glTexCoord2f(0, 1); glVertex3f( -0.5f, 0.5f, -0.5f );
glTexCoord2f(0, 0); glVertex3f( -0.5f, 0.5f, 0.5f );
glTexCoord2f(1, 0); glVertex3f( 0.5f, 0.5f, 0.5f );
glTexCoord2f(1, 1); glVertex3f( 0.5f, 0.5f, -0.5f );
glEnd();
// Render the bottom quad
glBindTexture(GL_TEXTURE_2D, _skybox[5]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f( -0.5f, -0.5f, -0.5f );
glTexCoord2f(0, 1); glVertex3f( -0.5f, -0.5f, 0.5f );
glTexCoord2f(1, 1); glVertex3f( 0.5f, -0.5f, 0.5f );
glTexCoord2f(1, 0); glVertex3f( 0.5f, -0.5f, -0.5f );
glEnd();
// Restore enable bits and matrix
glPopAttrib();
glPopMatrix();
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_BLEND);
glDepthMask(true);
glClear(GL_DEPTH_BUFFER_BIT);
drawGrid(20, 1);
glutSwapBuffers(); //swap the buffers
}
void update(int value) {
angle++; //increase the angle
glutPostRedisplay(); //Tell GLUT that the display has changed
//Tell GLUT to call update again in 25 milliseconds
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 800);
glutCreateWindow("Block Position");
initRendering();
glutDisplayFunc(drawScene);
glutKeyboardFunc(keyboard);
glutIdleFunc(drawScene);
glutReshapeFunc(handleResize);
glutPassiveMotionFunc(mouseMovement);
glutTimerFunc(25, update, 0); //Add a timer
glutMouseFunc(mouseButtons);
glutMainLoop();
return 0;
}
If nothing is appearing at all, it may be because the sky box isn't in the scene because it's being culled (or not rendered) onto the screen.
In your code you specify 100.0 for the zFar:
gluPerspective(45.0, (double)w / (double)h, 1.0, 100.0);
Change the zFar value to accommodate for the size of the sky box (say 500.0) and it should appear.
You should start with minimal rendering, like no lightning, no face culling, just triangles in white color. So if you see white then at least your camera position is probably OK. Then you can enable culling, if all disappears then this is your problem - normals are in wrong directions. Then if all is OK, enable lighting, then texturing - and always check what changes.
so dont look at it too hard, but eliminate complexity - even check if simple trianlge will show up in the expected position.
Related
im trying to use a framebuffer for offscreen-render a cube. Then i try to translate it to a texture using its texture. The problem i get is when i try to put that texture on a plane. The texture colour is full based on one primary colour: Reed, Green or Blue. I dont know where is the problem, maybe a cast problem from float to double? I really dont know what to think or where to explore.
Here is a gif of what i get. In this gif you can see the normal cube without offscreen render. The second GREEN cube is the framebuffer's texture printed on a plane:
here is the code I use. Its based on Qt but there is no difference from this to glut. I explain it to make easier to understand:
initializeGL: I declare the framebuffer and its attachments
PaintGL: draws the cube without using the FB if i dont "left click" to enable this (first part of the gif, it works perfect). If i left click, then the routine changes and paint the cube on the FrameBuffer, and then i paint its texture on a plane. (second part of the gif, it paints my texture GREEN)
setProyection: set the glOrtho for the normal cube draw.
#include "WidgetOpenGL.h"
WidgetOpenGL::WidgetOpenGL(QWidget *parent) : QOpenGLWidget(parent)
{
}
void WidgetOpenGL::initializeGL()
{
desplazamientoX = 1;
desplazamientoY = 0;
initializeOpenGLFunctions();
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
buttonpressed = false;
glGenFramebuffers(1, &buffer);
glBindFramebuffer(GL_FRAMEBUFFER, buffer);
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 768, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenRenderbuffers(1, &renderedDepth);
glBindRenderbuffer(GL_RENDERBUFFER, renderedDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1024, 768);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderedDepth);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderedTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
setProyection();
setModelView();
}
void WidgetOpenGL::paintGL()
{
if (buttonpressed)
{
glBindFramebuffer(GL_FRAMEBUFFER, buffer);
glViewport(0, 0, 1024, 768);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
setProyection();
setModelView();
glTranslatef(0.0, 0.0, -2.0);
setRotation();
glBegin(GL_QUADS);
// top
glColor3f(1.0f, 0.0f, 0.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glEnd();
glBegin(GL_QUADS);
// front
glColor3f(0.0f, 1.0f, 0.0f);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glEnd();
glBegin(GL_QUADS);
// right
glColor3f(0.0f, 0.0f, 1.0f);
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, 0.5f);
glEnd();
glBegin(GL_QUADS);
// left
glColor3f(0.0f, 0.0f, 0.5f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glEnd();
glBegin(GL_QUADS);
// bottom
glColor3f(0.5f, 0.0f, 0.0f);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glEnd();
glBegin(GL_QUADS);
// back
glColor3f(0.0f, 0.5f, 0.0f);
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glEnd();
glFlush();
if (buttonpressed)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// QImage img = frameBuffer->toImage();
// img.save("Hola.jpg");
//draw plane with texture
setViewport();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glBegin(GL_QUADS);
glTexCoord2d(0.0f, 0.0f);
glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2d(1.0f, 0.0f);
glVertex3f(1.0, -1.0, -1);
glTexCoord2d(1.0f, 1.0f);
glVertex3f(1.0, 1.0, -1.0);
glTexCoord2d(0.0f, 1.0f);
glVertex3f(-1.0, 1.0, -1.0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glFlush();
}
}
void WidgetOpenGL::resizeGL(int w, int h)
{
setViewport();
setProyection();
setModelView();
}
void WidgetOpenGL::setViewport()
{
int ancho = this->width();
int alto = this->height();
glViewport(0, 0, ancho, alto);
}
void WidgetOpenGL::setProyection()
{
int ancho = this->width();
int alto = this->height();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 10.0);
//gluPerspective(90.0f, ancho / (GLdouble)alto, 0.0f, 10.0f);
}
void WidgetOpenGL::setModelView()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void WidgetOpenGL::mouseMoveEvent(QMouseEvent *event)
{
desplazamientoY += ((event->x() - initX) * 360) / (GLdouble)width();
desplazamientoX += ((event->y() - initY) * 360) / (GLdouble)height();
initX = event->x();
initY = event->y();
if (((int)desplazamientoX % 360) == 0) desplazamientoX = 0;
if (((int)desplazamientoY % 360) == 0) desplazamientoY = 0;
repaint();
}
void WidgetOpenGL::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
initX = event->x();
initY = event->y();
}
else
{
buttonpressed = !buttonpressed;
repaint();
}
}
void WidgetOpenGL::setRotation()
{
glRotatef(desplazamientoX, 1.0, 0.0, 0.0);
glRotatef(desplazamientoY, 0.0, 1.0, 0.0);
}
and here is the header file if needed:
#ifndef WIDGETOPENGL_H
#define WIDGETOPENGL_H
#include <QtWidgets/QMainWindow>
#include <QtWidgets/qopenglwidget.h>
#include <QtOpenGL>
#include <GL/GLU.h>
class WidgetOpenGL : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
WidgetOpenGL(QWidget *parent);
signals:
void screenClicked();
protected:
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
void setViewport();
void setProyection();
void setModelView();
private:
int initX;
int initY;
QOpenGLFramebufferObject *frameBuffer;
GLuint buffer;
GLuint renderedTexture;
GLuint renderedDepth;
bool buttonpressed;
QImage image;
GLdouble desplazamientoX;
GLdouble desplazamientoY;
void setRotation();
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
};
#endif
Solved! the problem were that i was painting the texture on a green plane. Thats because the last glcolor3f is green (used when i paint the back plane of the real cube).
I only have to add glColor3f(1.0,1.0,1.0) before drawing the plane, to make a white plane.
I started learning OpenGL and I'm using it with SFML 2.1 to get window, load images, etc. But I've got a problem with simple prism. Faces are partly transparent and it looks terrible :/ I was looking at tutorials, but I don't know what is wrong with my code... Could you help me? I read that it's problem with Z-Buffering. How to fix it?
Here is my code:
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>
using namespace std;
void drawCube (float x, float y, float z, float width, float height, GLuint Texture);
int main()
{
// Window
sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL", sf::Style::Default, sf::ContextSettings(32));
// Camera
GLdouble eyex = 0;
GLdouble eyey = 0;
GLdouble eyez = 2575;
GLuint Texture = 0;
{
sf::Image Image;
if (!Image.loadFromFile("background.png"))
return EXIT_FAILURE;
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Image.getSize().x, Image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, Image.getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
// Main loop
while (window.isOpen())
{
// Checking events
sf::Event event;
while (window.pollEvent(event))
{
// Close the window
if (event.type == sf::Event::Closed)
window.close();
// Resize the window
if (event.type == sf::Event::Resized)
glViewport(0, 0, event.size.width, event.size.height);
}
// Close the window
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
window.close();
// Clear the window
window.clear(sf::Color::White);
// Viewport
glViewport( 0, 0, window.getSize().x, window.getSize().y );
// Matrix Mode
glMatrixMode( GL_PROJECTION );
// Matrix Load Identity
glLoadIdentity();
// Perspective
gluPerspective(window.getSize().y/45.0, 1.0f*window.getSize().x/window.getSize().y, 0.0f, 100.0f);
// Clear color buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set Matrix Mode
glMatrixMode( GL_MODELVIEW );
// Matrix Load Identity
glLoadIdentity();
// Change camera position
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
eyey -= 0.1f;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
eyey += 0.1f;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
eyex -= 0.1f;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
eyex += 0.1f;
printf("%f %f\n", eyex, eyey);
// Set the camera
gluLookAt( eyex, -eyey, eyez, eyex, -eyey, 0, 0, 1, 0 );
// RECTANGLE
/*
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Texture);
glColor4f( 0.0, 1.0, 0.0, 1.0f );
glScalef(1,-1,1);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(100, 200, 0.0f);
glTexCoord2f(3.333333f, 0.0f); glVertex3f(200, 200, 0.0f);
glTexCoord2f(3.333333f, 3.333333f); glVertex3f(200, 300, 0.0f);
glTexCoord2f(0.0f, 3.333333f); glVertex3f(100, 300, 0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
*/
// Set color drawing
glColor3f( 0.0, 0.0, 0.0 );
glScalef(1,-1,1);
// Draw cube
drawCube(0.0f, 0.0f, 1000.0f, 100.0f, 100.0f, Texture);
// Flush the scene
glFlush();
// Update the window
window.display();
}
return 0;
}
void drawCube (float x, float y, float z, float width, float height, GLuint Texture)
{
width /= 2;
height /= 2;
x += width;
y += height;
y = -y;
width = -width;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Texture);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
// Top face
glVertex3f( x + width, y + height, 0.0f);
glVertex3f( x - width, y + height, 0.0f);
glVertex3f( x - width, y + height, z);
glVertex3f( x + width, y + height, z);
glColor3f(1.0f, 1.0f, 0.0f);
// Left face
glVertex3f( x - width, y + height, z);
glVertex3f( x - width, y + height, 0.0f);
glVertex3f( x - width, y - height, 0.0f);
glVertex3f( x - width, y - height, z);
glColor3f(0.0f, 1.0f, 1.0f);
// Right face
glVertex3f( x + width, y + height, 0.0f);
glVertex3f( x + width, y + height, z);
glVertex3f( x + width, y - height, z);
glVertex3f( x + width, y - height, 0.0f);
glColor3f(0.0f, 0.0f, 0.0f);
// Bottom face
glVertex3f( x + width, y - height, 0.0f);
glVertex3f( x - width, y - height, 0.0f);
glVertex3f( x - width, y - height, z);
glVertex3f( x + width, y - height, z);
glColor3f(0.0f, 1.0f, 0.0f);
// Front face
glVertex3f( x + width, y + height, z);
glVertex3f( x - width, y + height, z);
glVertex3f( x - width, y - height, z);
glVertex3f( x + width, y - height, z);
glEnd();
glDisable(GL_TEXTURE_2D);
}
This is my result:
You are correct, this problem is related to Z-Buffering.
There are actually two issues I see in your code:
32-bit depth buffers are not supported by all hardware
24-bit Depth + 8-Bit Stencil is a much more compatible format, and more than adequate for your simple application. This can be requested using sf::ContextSettings (24, 8).
Depth testing is disabled by default in OpenGL
Even if your hardware supports a 32-bit depth buffer, allocating the depth buffer alone is insufficient. You must enable it yourself by adding a call to glEnable (GL_DEPTH_TEST) after you create your sf::RenderWindow.
UPDATE:
I totally missed this the first time I ran through your code:
// Perspective
gluPerspective(
window.getSize().y/45.0, 1.0f*window.getSize().x/window.getSize().y,
0.0f, 100.0f);
~~~~
You are using 0.0 for the near plane in your perspective projection matrix. This is a very bad thing to do, it will completely mess up your depth range and this likely accounts for both of the screenshots you included in your comments.
Both planes must be positive values. If gluPerspective (...) were actually a part of the OpenGL API, it would generate a GL_INVALID_VALUE error under these circumstances. Also be aware that the distance between your near and far plane will determine the overall precision of your depth buffer (this is discussed in the documentation for gluPerspective).
To correct this, use a value that is very close to, but not exactly 0.0 for the near plane (i.e. 0.1).
I'm making a particle fountain in openGL, I have the particles functioning properly. I decided to add a plane to make it look like they are bouncing off from it. What I'm trying to get is something like this
Unfortunately what I'm getting is this
the plain doesn't seem to be appearing at all. I tried messing with the co-ordinates and that doesn't seem to do anything. This is the image I'm using as the texture, it's a 256 X 256 24bit bmp.
I load the texture in the init function, then call it before I render the particles in the following function
void Load_Plane(){
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
glColor4f(0.0f, 0.2f, 0.2f, 0.5f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, txPlane);
glBegin(GL_QUADS);
glNormal3f(-10.0f, 0.0f, -10.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10.0f, 0.0f, 10.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 10.0f, 0.0f, 10.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 10.0f, 0.0f, -10.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-10.0f, 0.0f, -10.0f);
glEnd();
}
full code
// particle_fountain.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<stdlib.h>
#include <stdio.h>
#include<Windows.h>
#include <time.h>
#include <GL\glut.h>
#include<GL\GLU.h>
#define MAX_PARTICLES 200 //max number of particles
#define MAX_BOUNCE_COUNT 5 //number of times a particle should bounce
#define MAX_PARTICLE_AGE 95
//Colours
float R = 0.8f;
float G = 0.2f;
float B = 0.0f;
float cR = 0.001f;
float cG = 0.002f;
float cB = 0.003f;
float Size = 0.02f; //size for points
GLuint txParticle;
GLuint txPlane;
struct PARTICLE {
float X,Y,Z; // Current position
float sX,sY,sZ; // Current Speed/Movement
float tX,tY,tZ; // Target Speed/Movement
float R,B,G; // Particle Colour
bool Active; // Is particle Active
int Age; // Age of the particle
int MaxAge; // Maximum Age before particle dies
int BounceCount;
} Particles[MAX_PARTICLES];
void Init_Particles();
void Activate_Particles();
void Adjust_Particles();
void Render_Particles();
bool LoadBitmapTexture(char * FileName, GLuint &texid);
void timer(int extra);
void Load_Plane();
void DrawGLscene();
void Reshape(GLsizei w, GLsizei h);
int main(int argc, char** argv){
glutInit(&argc,argv);
glutInitDisplayMode( GLUT_RGBA| GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow("Particle fountain");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, -0.9, -3.0);
Init_Particles();
glutDisplayFunc(DrawGLscene);
glutTimerFunc(0, timer, 0);
glutMainLoop();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(20, timer, 0);
}
void Load_Plane(){
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
glColor4f(0.0f, 0.2f, 0.2f, 0.5f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, txPlane);
glBegin(GL_QUADS);
glNormal3f(-10.0f, 0.0f, -10.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10.0f, 0.0f, 10.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 10.0f, 0.0f, 10.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 10.0f, 0.0f, -10.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-10.0f, 0.0f, -10.0f);
glEnd();
}
void DrawGLscene(){
Load_Plane();
glPushMatrix();
glScalef(1.0f, -1.0f, 1.0f);
Render_Particles();
glPopMatrix();
Render_Particles();
}
void Init_Particles(){
LoadBitmapTexture("./Particle.bmp", txParticle); //load the particle texture
LoadBitmapTexture("./Plain.bmp",txPlane); //load the plain texture
int p;
srand((int)time(NULL));
for(p=0; p<MAX_PARTICLES; p++){
Particles[p].Active = FALSE;
Particles[p].tX = 0.0f;
Particles[p].tY = -0.1f;
Particles[p].tZ = 0.0f;
}
}
void Activate_Particles(){
int p;
for(p=0; p<MAX_PARTICLES; p++){
if(!Particles[p].Active){
// Start the particle at 0,0,0 origin
Particles[p].X = 0.0f;
Particles[p].Y = 0.0f;
Particles[p].Z = 0.0f;
// The following lines set a random speed value
Particles[p].sX = (((float)((rand() % 100) + 1)) /
1000.0f) - 0.05f;
Particles[p].sY = (((float)((rand() % 100) + 50)) /
500.0f);
Particles[p].sZ = (((float)((rand() % 100) + 1)) /
1000.0f) - 0.05f;
// We also activate the particle
Particles[p].Active = true;
// Set it's Age to zero
Particles[p].Age = 0;
// We also assign a max age to the particles
Particles[p].MaxAge = MAX_PARTICLE_AGE;
// We Also reset the bouncecount to zero
Particles[p].BounceCount = 0;
//Adding the colours
Particles[p].R = R;
Particles[p].G = G;
Particles[p].B = B;
R+=cR;
G+=cG;
B+=cB;
if(R>1.0f){R=1.0f; cR=-cR;}
if(R<0.0f){R=0.0f; cR=-cR;}
if(G>1.0f){G=1.0f; cG=-cG;}
if(G<0.0f){G=0.0f; cG=-cG;}
if(B>1.0f){B=1.0f; cB=-cB;}
if(B<0.0f){B=0.0f; cB=-cB;}
return;
}
}
}
void Adjust_Particles(){
int p;
for(p=0; p<MAX_PARTICLES; p++){
// We move the speed towards the target speed by 1/20 (5%)
Particles[p].sX+= (Particles[p].tX - Particles[p].sX) / 20.0f;
Particles[p].sY+= (Particles[p].tY - Particles[p].sY) / 20.0f;
Particles[p].sZ+= (Particles[p].tZ - Particles[p].sZ) / 20.0f;
// Then we adjust the position of
// the particle by the new speed
Particles[p].X+= Particles[p].sX;
Particles[p].Y+= Particles[p].sY;
Particles[p].Z+= Particles[p].sZ;
// Now for the bounce code.
if(Particles[p].Y < 0.0f){
Particles[p].Y = 0.0f;
Particles[p].sY = -Particles[p].sY;
Particles[p].BounceCount++;
if(Particles[p].BounceCount > MAX_BOUNCE_COUNT){
Particles[p].Active = FALSE;
}
}
// And finally the age check
Particles[p].Age++;
if(Particles[p].Age > Particles[p].MaxAge){
Particles[p].Active = FALSE;
}
}
}
void Render_Particles(){
Activate_Particles();
Adjust_Particles();
glClear( GL_COLOR_BUFFER_BIT );
int p;
// Enable textures and bind our particle texture
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, txParticle);
// Disable Depth testing.
glDisable(GL_DEPTH_TEST);
// Enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR,GL_ONE);
for(p=0; p<MAX_PARTICLES; p++){
if(Particles[p].Active){
glColor4f(Particles[p].R,
Particles[p].G,
Particles[p].B, 1.0f);
glPushMatrix();
glTranslatef(Particles[p].X,
Particles[p].Y,
Particles[p].Z);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-Size, -Size, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(Size, -Size, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(Size, Size, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-Size, Size, 0.0f);
glEnd();
glPopMatrix();
}
}
glEnable(GL_DEPTH_TEST);
glutSwapBuffers();
}
bool LoadBitmapTexture(char * FileName, GLuint &texid){
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure
glGenTextures(1, &texid); // Create The Texture
hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),
FileName,
IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION | LR_LOADFROMFILE
);
if (!hBMP) // Does The Bitmap Exist?
return FALSE; // If Not Return False
GetObject(hBMP, sizeof(BMP), &BMP); // Get The Object
// hBMP: Handle To Graphics Object
// sizeof(BMP): Size Of Buffer For Object Information
// &BMP: Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
// Pixel Storage Mode (Word Alignment / 4 Bytes)
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texid);// Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR); // Linear Min Filter
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR); // Linear Mag Filter
glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight,
0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); // Delete The Object
return TRUE; // Loading Was Successful
}
It could be that you're not clearing the depth buffer.
It doesn't affect any of the particles because you are disabling depth test when you render them, but when you render the plane, depth test is enabled, and since the depth buffer has not been cleared it has a spaz and doesn't render the plane.
Do
glClear(GL_DEPTH_BUFFER_BIT);
before you render the plane to clear the depth buffer.
EDIT:
This must be it-
You are calling
glClear(GL_COLOR_BUFFER_BIT);
after you render the plane. Look at your DrawGLScene function:
Load_Plane(); // you are drawing the plane here
glPushMatrix();
glScalef(1.0f, -1.0f, 1.0f);
Render_Particles(); // this function calls "glClear( GL_COLOR_BUFFER_BIT );"
// so anything that you rendered before is now removed.
glPopMatrix();
Render_Particles(); // same goes for here.
The solution would be to remove the call to glClear from your Render_Particles function,
and add it to the top of DrawGLScene:
(New DrawGLScene Code)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Load_Plane();
glPushMatrix();
glScalef(1.0f, -1.0f, 1.0f);
Render_Particles();
glPopMatrix();
Render_Particles();
EDIT #2:
You're calling glutSwapBuffers in the Render_Particles function.
Don't call it there. Call it at the end of DrawGLScene:
I'm writing a program that draws a rotating cube (with texture) in the middle of the screen followed by a small yellow sphere that orbits around the cube. The idea is to make the sphere as a spot light source that illuminates the cube.
Here is the problem: as you can see in the images below, I'm failing to achieve the spot light effect. It seems that the entire cube gets lighted:
I'm setting GL_SPOT_DIRECTION to be the cube position. I didn't set surface normals because I'm struggling to understand how to compute them for the cube, and I'm not sure a simple graphic application like this really requires it.
I'm sharing the code below:
main.cpp:
#include <QApplication>
#include "glwidget.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
GLWidget gl_widget;
gl_widget.show();
return app.exec();
}
GLWidget.h:
#pragma once
#include <QGLWidget>
#include <QImage>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget* parent = 0);
virtual ~GLWidget();
void _draw_texture_cube(int w, int h);
void _draw_light();
/* OpenGL initialization, viewport resizing, and painting */
void initializeGL();
void paintGL();
void resizeGL( int width, int height);
/* enable the user to interact directly with the scene using the keyboard */
void keyPressEvent(QKeyEvent *e);
private:
int _width;
int _height;
QImage* _img;
GLuint _texture;
float xrot;
float yrot;
float zrot;
bool _light_on;
bool _must_rotate;
bool _pause_light;
GLfloat _light_pos[3];
GLfloat _cube_pos[3];
GLUquadricObj* _quadratic;
protected slots:
void _tick();
};
GLWidget.cpp:
#include "GLWidget.h"
#include <iostream>
#include <QKeyEvent>
#include <QTimer>
#include <cmath>
#define LIGHT_MOVEMENT_SPEED 20.0f // Degrees per second
#define pi 3.141592654f
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent), _img(NULL), _light_on(true), _must_rotate(true),
_pause_light(false), _quadratic(NULL)
{
_width = 0;
_height = 0;
_texture = 0;
xrot = 0.f;
yrot = 0.f;
zrot = 0.f;
// Set central cube position
_cube_pos[0] = 0.0f;
_cube_pos[1] = 0.0f;
_cube_pos[2] = -7.0f;
// Set light position
_light_pos[0] = 0.5f;
_light_pos[1] = 0.5f;
_light_pos[2] = -7.0f;
}
GLWidget::~GLWidget()
{
if (_img)
delete _img;
glDeleteTextures(1, &_texture);
}
void GLWidget::_tick()
{
update(); // triggers paintGL()
QTimer::singleShot(33, this, SLOT(_tick()));
}
void GLWidget::initializeGL()
{
std::cout << "GLWidget::initializeGL" << std::endl;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Background
glEnable(GL_CULL_FACE);
/* Load bitmap */
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
if (!_img)
{
std::cout << "GLWidget::paintGL: loading image" << std::endl;
QImage tmp(":/crate.jpg");
if (tmp.isNull())
{
std::cout << "GLWidget::paintGL: !!! Failed QImage #1" << std::endl;
return;
}
_img = new QImage(QGLWidget::convertToGLFormat(tmp));
}
/* Convert bitmap into texture */
// Create The Texture
glGenTextures(1, &_texture);
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture);
// Generate The Texture
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
GL_RGBA, _img->width(), _img->height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, _img->bits());
if (glGetError() != GL_NO_ERROR)
{
std::cout << "GLWidget::paintGL: !!! Failed glTexImage2D" << std::endl;
return;
}
/* Setup lighting */
glShadeModel(GL_SMOOTH); //Smooth color shading
// Light properties
GLfloat AmbientLight[4] = {0.2, 0.2, 0.2, 1.0};
GLfloat DiffuseLight[4] = {0.8, 0.8, 0.8, 1.0}; // color
GLfloat SpecularLight[4] = {1.0, 1.0, 1.0, 1.0}; // bright
GLfloat SpecRef[] = {0.7f, 0.7f, 0.7f, 1.0f};
GLubyte Shine = 60.0;
//glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, AmbientLight);
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight);
glLightfv(GL_LIGHT0, GL_POSITION, _light_pos);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_SPECULAR, SpecRef); // refletância do material
glMaterialf(GL_FRONT, GL_SHININESS, Shine); // concentração do brilho
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
//glColorMaterial(GL_FRONT,GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
// Sphere
_quadratic = gluNewQuadric(); // Create A Pointer To The Quadric Object
gluQuadricNormals(_quadratic, GLU_SMOOTH); // Create Smooth Normals
gluQuadricTexture(_quadratic, GL_TRUE); // Create Texture Coords
/* Start the timer */
_tick();
}
/* Draw the central cube with texture
*/
void GLWidget::_draw_texture_cube(int w, int h)
{
glPushMatrix();
glTranslatef(_cube_pos[0], _cube_pos[1], _cube_pos[2]);
glRotatef ( xrot, 1.0, 0.0, 0.0 );
glRotatef ( yrot, 0.0, 1.0, 0.0 );
glRotatef ( zrot, 0.0, 0.0, 1.0 );
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS); // Draw A Cube
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(w, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(w, h); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, h); glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f(w, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(w, h); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, h); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f(0.0f, h); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(w, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(w, h); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f(w, h); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, h); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(w, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f(w, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(w, h); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, _img->height()); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(w, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(w, h); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, h); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glPopMatrix();
if (_must_rotate)
{
xrot += 0.6f;
yrot += 0.4f;
zrot += 0.8f;
}
}
/* Draw light source and light model (sphere)
*/
void GLWidget::_draw_light()
{
if (_light_on)
{
glEnable(GL_LIGHT0); // enable lights that we use
}
else
{
glDisable(GL_LIGHT0);
}
static float light_angle = 25.0f;
if (!_pause_light) // stop moving the light source
{
light_angle += LIGHT_MOVEMENT_SPEED * 0.1;
if (light_angle > 360.0f)
light_angle -= 360.0f;
}
/* Set light source position */
_light_pos[0] = 4.0f * (float) cos(light_angle * pi / 180.0f);
_light_pos[1] = 4.0f * (float) sin(light_angle * pi / 180.0f);
_light_pos[2] = -7;
glLightfv(GL_LIGHT0, GL_POSITION, _light_pos);
GLfloat SpotDir[] = {_cube_pos[0], _cube_pos[1], _cube_pos[2], 0.0 };
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, SpotDir);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 150.0);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 15.0);
/* Set the light model position to be the same as the light source */
glPushMatrix();
glTranslatef(_light_pos[0], _light_pos[1], _light_pos[2]);
glColor3ub(255, 255, 0); // yellow
gluSphere(_quadratic, 0.2f, 32, 32); // draw sphere
glPopMatrix();
}
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix
glLoadIdentity(); // Reset The Current Modelview Matrix
/* Draw central cube */
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture); // Select Our Texture
_draw_texture_cube(_img->width(), _img->height());
glDisable(GL_TEXTURE_RECTANGLE_ARB);
/* Draw light source and light model*/
_draw_light();
}
void GLWidget::resizeGL( int w, int h)
{
_width = w;
_height = h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
if (h == 0) // Calculate The Aspect Ratio Of The Window
gluPerspective ( 60, ( float ) w, 0.4, 500.0 );
else
gluPerspective ( 60, ( float ) w / ( float ) h, 0.4, 500.0 );
glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix
glLoadIdentity ( ); // Reset The Model View Matrix
gluLookAt(0.0, 0.0, 2.0, // eye
0.0, 0.0, 0.0, // center
0.0, 1.0, 0.0); // up
}
void GLWidget::keyPressEvent(QKeyEvent *e)
{
switch (e->key())
{
case Qt::Key_L:
if (_light_on)
_light_on = false;
else
_light_on = true;
break;
case Qt::Key_P:
if (_pause_light)
_pause_light = false;
else
_pause_light = true;
break;
case Qt::Key_R:
if (_must_rotate)
_must_rotate = false;
else
_must_rotate = true;
break;
default:
break;
}
}
Lighting.pro:
QT += core gui opengl
SOURCES += \
GLWidget.cpp \
main.cpp
HEADERS += \
GLWidget.h
RESOURCES += \
resource.qrc
What needs to be changed in this application in order to achieve the desired effect?
You do not specify any normals for your cube faces. As OpenGL is a state machine, it will use the default surface normal for all vertices, hence all of your faces. As the normal vector is crucial for the lighting, all of your faces will be lit almost identical (vertex postions still are different, but the effect is weak).
You should also be aware that the fixed function lighting of OpenGL is done per vertex. If you really want to see a good spotlight on the cuve, you would either need to tessalate it so more vertices are used where the lighting equation is actually evaluated, or use shaders for per-fragment lighting.
I'm trying to map the input from my webcam to a plane in OpenGL. I'm using OpenCV to get the images from the webcam.
The problem I have is that the texture is vertically inverted, if my texture is "v", the current result is "^".
I want to fit the image taken from the webcam to my plane (2x2). Its lower left corner is -1, -1 and the upper right corner is 1,1.
The code is:
const int VIEWPORT_WIDTH = 640;
const int VIEWPORT_HEIGHT = 480;
const int KEY_ESCAPE = 27;
CvCapture* g_Capture;
IplImage* image;
GLint g_hWindow;
GLvoid InitGL();
GLvoid OnDisplay();
GLvoid OnReshape(GLint w, GLint h);
GLvoid OnKeyPress (unsigned char key, GLint x, GLint y);
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
g_hWindow = glutCreateWindow("Image");
image = cvLoadImage("average.jpg", 1);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height, GL_RGB, GL_UNSIGNED_BYTE, image->imageData);
InitGL();
glutMainLoop();
return 0;
}
GLvoid InitGL()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glutDisplayFunc(OnDisplay);
glutReshapeFunc(OnReshape);
glutKeyboardFunc(OnKeyPress);
}
GLvoid OnDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(0.0f, 0.0f, -2.5f);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
GLvoid OnReshape(GLint width, GLint height)
{
if (height==0)
height=1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, 1.0f, 10.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( 0.0, 0.0, 0.0, 0.0, 0.0, -6.0, 0.0f, 1.0f, 0.0f);
}
GLvoid OnKeyPress(unsigned char key, int x, int y)
{
switch (key) {
case KEY_ESCAPE:
cvReleaseImage(&image);
glutDestroyWindow(g_hWindow);
exit(0);
break;
}
glutPostRedisplay();
}
BTW. In this code I'm loading an image instead of getting from the webcam.
Any suggestion?
Flip the texture coordinates on the quad you're rendering. OpenGL does store texture "upside-down" from how most people assume they'd be, so the simplest way to handle it is just work with OGL.
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
should do it, I think.