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).
Related
I have a simple skybox.
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vector>
#include <iostream>
#include "texture.h"
#include "deviLoader.h"
using namespace std;
static std::vector<GLuint> textures;
class Skybox
{
private:
float x, y, z;
float width, height, length;
bool isBottomRequired;
void rearrange();
void loadTextures();
public:
Skybox() {};
Skybox(float x,
float y,
float z,
float width,
float height,
float length);
void renderSkybox();
void setBottom(bool required);
~Skybox() {};
};
I load textures using devIL lib in method loadTextures.
void Skybox::loadTextures()
{
cout<<"SKYBOX: texture loading...";
Texture t;
LoadTexture(IL_BMP, "Back.bmp", &t);
textures.push_back(t.texID);
LoadTexture(IL_BMP, "Front.bmp", &t);
textures.push_back(t.texID);
LoadTexture(IL_BMP, "Bottom.bmp", &t);
textures.push_back(t.texID);
LoadTexture(IL_BMP, "Top.bmp", &t);
textures.push_back(t.texID);
LoadTexture(IL_BMP, "Left.bmp", &t);
textures.push_back(t.texID);
LoadTexture(IL_BMP, "Right.bmp", &t);
textures.push_back(t.texID);
/*
LoadTexture(IL_BMP, "Back.bmp", &t);
textures[0] = t.texID;
*/
cout<<"SUCCESS"<<endl;
}
where function loadTexture
void LoadTexture(ILenum FileType, char *filename, Texture *texture)
{
ilInit();
iluInit();
ilLoad(FileType, filename);
int err = ilGetError();
if (err != IL_NO_ERROR)
{
const char* strError = iluErrorString(err);
cout<<strError<<" - error during loading!"<<endl;
return;
}
texture->width = ilGetInteger(IL_IMAGE_WIDTH);
texture->height = ilGetInteger(IL_IMAGE_HEIGHT);
texture->bpp = ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL);
texture->imageData = ilGetData();
ilEnable(IL_CONV_PAL);
unsigned int type = ilGetInteger(IL_IMAGE_FORMAT);
glGenTextures(1, &texture->texID);
glBindTexture(GL_TEXTURE_2D, texture->texID);
gluBuild2DMipmaps(GL_TEXTURE_2D, texture->bpp, texture->width, texture->height,
type, GL_UNSIGNED_BYTE, texture->imageData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
In my main.cpp I declare skybox object as a global variable and render it in method draw
Skybox skyBox;
.....
//part of method draw
if (selected[7] == 1) {
glDisable(GL_FOG);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(-0.2, 4, 2.3);
glScalef(0.15, 0.2, 0.19);
skyBox.renderSkybox();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
if (selected[6] == 1)
glEnable(GL_FOG);
}
renderSkybox method
void Skybox::renderSkybox()
{
glBindTexture(GL_TEXTURE_2D, textures[0]);
glBegin(GL_QUADS);
glTexCoord2f(1.0, 0.0); glVertex3f(x + width, y, z);
glTexCoord2f(1.0, 1.0); glVertex3f(x + width, y + height, z);
glTexCoord2f(0.0, 1.0); glVertex3f(x, y + height, z);
glTexCoord2f(0.0, 0.0); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, textures[1]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,z + length);
glEnd();
if (isBottomRequired)
{
glBindTexture(GL_TEXTURE_2D, textures[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y,z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y,z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,z);
glEnd();
}
glBindTexture(GL_TEXTURE_2D, textures[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y + height,z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height,z);
glEnd();
glBindTexture(GL_TEXTURE_2D, textures[4]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height,z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height,z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y,z + length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,z);
glEnd();
glBindTexture(GL_TEXTURE_2D, textures[5]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height,z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height,z);
glEnd();
};
When I draw other objects - It is seen that skybox appears to be black
What is the problem? Why it is black?
edit I've added project in case if somebody decides to look into problem with more details. There project and glm, assimp, devil, freeglut libs. Project is not finished but it should work.
http://www.filedropper.com/task
There are two strategies on drawing a skybox:
use the skybox for "clearing": You draw the skybox as the first thing in your scene. Before drawing the skybox call glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE);, then draw the skybox and reenable depth testing (glEnable(GL_DEPTH_TEST)) and depth writes (glDepthMask(GL_FALSE)) as needed
draw the skybox after the last opaque, but before blended geometry (requires support for depth clamping). Clear the scene with the depth buffer cleared to (pow(2, b)-1.)/pow(2, b) where b is the bit depth of the depth buffer. Draw the opaque scene as usual. Enable depth clamping and depth test set the depth test function to greater or equal (glDepthFunc(GL_GEQUAL)) and setup a projection, or scale up the skybox, so that the skybox quads will always stay behind the far clipping plane. Due to depth clamping the generated fragment depths with all be 1.0 passing the depth test rendering the skybox only at those areas of the screen, not covered by other geometry.
I tried to load the six pictures as texture and draw a skybox, but the result is weird, each picture is mapped three times on its corresponding rectangle in grey. What is the problem?
#include <stdlib.h>
#include <stdio.h>
#include <glut.h>
#include <gl.h>
#include <glu.h>
#include <math.h>
#include <windows.h>
GLuint texture [6]; //the array for our texture
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glShadeModel (GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
}
GLuint LoadTexture( const char * filename, int width, int height) {
GLuint texture;
unsigned char * data;
FILE* file;
file = fopen( filename, "r" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
void FreeTexture( GLuint texture )
{
glDeleteTextures( 1, &texture );
}
void skybox (void) {
float x = 0;
float y = 0;
float z = 0;
float width = 100;
float height = 100;
float length = 100;
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
// Bind the BACK texture of the sky map to the BACK side of the cube
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Center the skybox
x = x - width / 2;
y = y - height / 2;
z = z - length / 2;
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z + length);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[5]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
glEnd();
//glBindTexture( GL_TEXTURE_CUBE_MAP, texture[0] ); //bind the texture
//glRotatef( angle, 1.0f, 1.0f, 1.0f );
//glutSolidSphere(2, 40, 40);
}
void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat light_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0.0, 0.0, 30.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLoadIdentity();
glPushMatrix();
gluLookAt (20.0, 20.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
texture[1] = LoadTexture( "front.bmp", 256, 256 ); //load the texture
texture[2] = LoadTexture( "left.bmp", 256, 256 ); //load the texture
texture[3] = LoadTexture( "right.bmp", 256, 256 ); //load the texture
texture[4] = LoadTexture( "bottom.bmp", 256, 256 ); //load the texture
texture[5] = LoadTexture( "top.bmp", 256, 256 ); //load the texture
glPopMatrix();
glPopMatrix();
//glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
//glEnable(GL_TEXTURE_GEN_T);
skybox();
for (int i = 0; i < 6; i++) {
FreeTexture( texture[i] );
}
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0,-100.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main (int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("A basic OpenGL Window");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
So, you're trying to load DIB/BMP image files:
> texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
> ^^^^
>
Reading the contents of the file
> GLuint LoadTexture( const char * filename, int width, int height) {
> GLuint texture; unsigned char * data; FILE* file;
>
> file = fopen( filename, "r" );
> if ( file == NULL ) return 0;
> data = (unsigned char *)malloc( width * height * 3 );
> fread( data, width * height * 3, 1, file );
This is too short for a BMP, BTW.
> fclose( file );
So where's your DIB parser code?
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
You just pass the unparsed DIB/BMP file contents to OpenGL. What do you expect OpenGL to do with this? OpenGL has no idea about file format, less how process a DIB file. You need a DIB parser there.
Since you're loading RGB data make sure GL_UNPACK_ALIGNMENT is set to 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1).
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
I use the ImageMagick open library to easily load any image for use with OpenGL.
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 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.
To make my maze type game faster I decided to put my drawed ball inside a texture, because i have to draw it otherwise once for every room and I'm drawing it like a concave polygon using the stencil buffer, it takes more time than using a texture. The problem is, that I'm getting it inside a texture correctly from the back buffer when I'm rendering the third frame since the start of the game and my question is, why is it like so?
When I'm using a texture from the thirst frame, I'm having texture with solid white color, so it has nothing inside. When I'm using textures from the second frame, then I have only the black background of the desired texture and when I take the texture from the third frame, then I have desired texture. For frame count I use the static variable "done" inside the "drawTexture" function.
Copying from the first frame:
Copying from the second frame:
Copying from the third frame (desired outcome):
void DrawBall::drawTexture(float imageD) {
static int done = 0;
if (done < 3) {
drawToTexture(imageD);
done++;
}
glEnable(GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, texture);
glColor3f(1, 1, 1);
glBegin (GL_QUADS);
glTexCoord2f (0.0, 0.0); glVertex3f (0.0, 0.0, -imageD);
glTexCoord2f (1.0, 0.0); glVertex3f (5.0, 0.0, -imageD);
glTexCoord2f (1.0, 1.0); glVertex3f (5.0, 5.0, -imageD);
glTexCoord2f (0.0, 1.0); glVertex3f (0.0, 5.0, -imageD);
glEnd ();
glDisable(GL_TEXTURE_2D);
}
void DrawBall::drawToTexture(float imageD) {
int viewport[4];
glGetIntegerv(GL_VIEWPORT, (int*) viewport);
int textureWidth = 64;
int textureHeight = 64;
texture = genEmptyTexture(textureWidth, textureHeight);
glViewport(0, 0, textureWidth, textureHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/*
This function calculates the vertexes for the ball
inside a vector<vector<float>> variable "test"
*/
_calculateCircleVertexes(0.0f, 0.0f, -2.0f, 0.249f, &test, 20);
_displayBall(&test, 0.0f, 0.0f, 0.5f, -2.0f, &*smallBallColor);
glBindTexture(GL_TEXTURE_2D, texture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, textureWidth, textureHeight, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)viewport[2] / (GLfloat)viewport[3], 1.0f, imageD + 10.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
GLuint DrawBall::genEmptyTexture(unsigned int width, unsigned int height) {
GLuint txtIndex;
glGenTextures(1, &txtIndex);
glBindTexture(GL_TEXTURE_2D, txtIndex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
return txtIndex;
}
void DrawBall::_displayBall(vector<vector<GLfloat>> *vertexes, GLfloat x, GLfloat y
, GLfloat imageW, GLfloat imageD, color *color) {
glTranslatef(x, y, imageD);
glClearStencil(0);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NEVER, 0, 1);
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
glBegin(GL_POLYGON);
vector<vector<GLfloat>>::iterator it = vertexes->begin();
for (; it != vertexes->end(); it++) {
glVertex3f((*it)[0], (*it)[1], 0.0f);
}
glEnd();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glColor3f(color->r, color->g, color->b);
glBegin(GL_QUADS);
glVertex3f(-(imageW / 2.0f), -(imageW / 2.0f), 0.0f);
glVertex3f( (imageW / 2.0f), -(imageW / 2.0f), 0.0f);
glVertex3f( (imageW / 2.0f), (imageW / 2.0f), 0.0f);
glVertex3f(-(imageW / 2.0f), (imageW / 2.0f), 0.0f);
glEnd();
glDisable(GL_STENCIL_TEST);
glTranslatef(x, y, -imageD);
}
You should not use the window framebuffer (which includes both back- and frontbuffer) for render to texture operations. It just breaks to easily (you've experienced it). Instead use a so called Framebuffer Object, with the texture as rendering target.
Well, Datenwolf, thank you for your suggestion, you are probably right but I just want to use the advanced stuff as less as possible and I found my mistakes. I didn't get the desired outcome before the second frame because I didn't have yet enabled stencil test. Before the first frame I didn't get the desired outcome because in the window creation Windows sends WM_SIZE message and I had the draw message inside it but at that time the OpenGL isn't set up properly yet.