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.
Related
I have created a rotating wired sphere. I have done textures to a cube but sphere seems to be a problem.
I want to add world map as a texture to this sphere. Any suggestions?
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <thread>
#include <chrono>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
using namespace std;
GLuint texture;
int start = 1;
GLfloat xRotated, yRotated, zRotated;
GLdouble radius = 1;
void init() {
glOrtho(-1000 / 2, 1000 / 2, -1000 / 2, 1000 / 2, -500, 500);
}
GLuint glInitTexture(char* filename)
{
GLuint t = 0;
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
unsigned char* data = stbi_load(filename, &width, &height, &nrChannels, 0);
glGenTextures(1, &t);
glBindTexture(GL_TEXTURE_2D, t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//unsigned char data[] = { 255, 0, 0, 255 };
if (data)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
else
std::cout << "fail";
return t;
}
void drawImage(GLuint file, float x, float y, float w, float h)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glPushMatrix();
//glTranslatef(x, y, 0.0);
//glRotatef(angle, 0.0, 0.0, 1.0);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, file);
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.5);
glRotatef(yRotated, 0.0, 1.0, 0.0);
glEnable(GL_TEXTURE_2D);
GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);
glDisable(GL_TEXTURE_2D);
glFlush();
yRotated += 0.01;
//glBindTexture(GL_TEXTURE_2D, 0);
glFlush();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
//Plots points of both graphs together
//Displays map on screen
void drawMap() {
std::cout << "\nDraw map\n";
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const double w = glutGet(GLUT_WINDOW_WIDTH);
const double h = glutGet(GLUT_WINDOW_HEIGHT);
gluPerspective(90.0, w / h, 0.1, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -15);
for (int i = 0; i < 10000; i++) {
glClear(GL_DEPTH_BUFFER_BIT);
drawImage(texture, 0, 0, 100, 200);
//std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
glutSwapBuffers();
glEnd();
glFlush();
}
void render()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//glFlush();
glPointSize(5);
glColor3f(1, 1, 1);
glBegin(GL_LINES);
glVertex3f(-450, -450, 10);
glVertex3f(-450, -250, 10);
glEnd();
glBegin(GL_LINES);
glVertex3f(-450, -450, 10);
glVertex3f(-250, -450, 10);
glEnd();
drawMap();
//plotPoints();
glFlush();
}
void Kbevent(unsigned char key, int x, int y) {
if (key == 's') {
start = start % 2;
glutPostRedisplay();
}
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1560, 810);
glutCreateWindow("Applying Textures");
init();
xRotated = yRotated = zRotated = 30.0;
xRotated = 33;
yRotated = 40;
char fn[] = "map.jpg";
texture = glInitTexture(fn);
glutDisplayFunc(render);
//glutReshapeFunc(reshapeFunc);
//glutIdleFunc(idleFunc);
glutKeyboardFunc(Kbevent);
glutMainLoop();
return 0;
}
The problem with applying a 2D texture is that when you wrap a 2D texture onto a sphere, the top and bottom area of the sphere, the texture looks squeezed.
I suggest to use gluSphere and gluQuadricTexture rather than glutSolidSphere. e.g:
glEnable(GL_TEXTURE_2D);
GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);
glDisable(GL_TEXTURE_2D);
For an continuously rotation, you have increment the rotation angle and to continuously update the window (glutPostRedisplay). e.g.:
void redisplayFunc(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.5);
glRotatef(yRotated, 0.0, 1.0, 0.0);
glEnable(GL_TEXTURE_2D);
GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);
glDisable(GL_TEXTURE_2D);
glFlush();
yRotated += 1;
glutPostRedisplay();
}
I am trying the texture mapping feature of OpenGL and the texture is displayed on the screen but not on the area that I set.
The area is a quad with 100.0 length and the texture is displayed only on the bottom.
When using GL_RGB in glTexImage2D, only one third of the quad is filled and when I change it to GL_RGBA, it becomes one quarter of the quad.
Main parameters declaration:
BYTE* m_pBMPBuffer;
int m_iWidth;
int m_iHeight;
GLuint m_uiTexture;
Code for setting up the texture mapping:
void CTextureMappingView::InitializeTexture()
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &m_uiTexture);
glBindTexture(GL_TEXTURE_2D, m_uiTexture);
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_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_iWidth, m_iHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, m_pBMPBuffer);
}
Buffer Initialization:
m_iWidth = 64;
m_iHeight = 64;
m_pBMPBuffer = new BYTE[m_iWidth * m_iHeight * 3];
for (int i = 0 ; i < m_iWidth * m_iHeight ; i += 3)
{
m_pBMPBuffer[i] = 255;
m_pBMPBuffer[i + 1] = 0;
m_pBMPBuffer[i + 2] = 0;
}
Rendering:
void CTextureMappingView::RenderScene()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(XAngle, 1.0f, 0.0f, 0.0f);
glRotatef(YAngle, 0.0f, 1.0f, 0.0f);
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, m_uiTexture);
glBegin(GL_POLYGON);
glTexCoord2d(0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3d(0.0, 100.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3d(100.0, 100.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3d(100.0, 0.0, 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
Current result:
You only initialize a third of your texture:
for (int i = 0 ; i < m_iWidth * m_iHeight ; i += 3)
You should go up to m_iWidth * m_iHeight * 3 since that's what you allocated.
I started with opengl texturing and everything was working well. Now I am trying to load a bmp and make white part transparent using glEnable(GL_BLEND); and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
This is my source code:
float kSpeedForw=0.0f;
GLuint texture[1];
CCamera g_Camera;
GLfloat xrot = 0;
GLfloat yrot = 0;
GLfloat zrot = 0;
bool g_bFullScreen = true;
HWND g_hWnd;
RECT g_rRect;
HDC g_hDC;
HGLRC g_hRC;
HINSTANCE g_hInstance;
float jump = -0.1;
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };
void Init(HWND hWnd)
{
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Position The Light
glEnable(GL_LIGHT1); // Enable Light One
glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
g_hWnd = hWnd;
GetClientRect(g_hWnd, &g_rRect);
InitializeOpenGL(g_rRect.right, g_rRect.bottom);
g_Camera.PositionCamera(0, 1.5f, 6, 0, 1.5f, 5, 0, 1, 0);
ShowCursor(false);
}
GLuint LoadTexture(const char * filename)
{
glEnable(GL_TEXTURE_2D);
GLuint texture;
int width, height;
unsigned char * data;
FILE * file;
file = fopen(filename, "rb");
if (file == NULL) return 0;
if (filename=="Data/weed.bmp"){
width = 200;
height = 200;
}
if (filename == "Data/gun.bmp"){
width = 300;
height = 300;
}
data = (unsigned char *)malloc(width * height * 3);
fread(data, width * height * 3, 1, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
if (filename == "Data/weed.bmp"){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
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);
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);
}
if (filename == "Data/gun.bmp"){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3,width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
return texture;
}
WPARAM MainLoop() // main function
{
MSG msg;
Init(g_hWnd);
glClearColor(0, 0, 255, 0);
while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if (LockFrameRate(60))
{
g_Camera.SetViewByMouse();
kSpeedForw = 0;
if (jump > -0.1)jump-=0.01;
CheckForMovement();
g_Camera.MoveCamera(kSpeedForw, jump);
RenderScene();
}
}
DeInit();
return(msg.wParam);
}
void RenderScene()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,
g_Camera.m_vView.x, g_Camera.m_vView.y, g_Camera.m_vView.z,
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y, g_Camera.m_vUpVector.z);
GLuint texture;
texture = LoadTexture("Data/weed.bmp");
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
float i = 0;
glColor3f(1,1,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, 10 - i / 5);
glTexCoord2f(50.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, -10 + i / 5);
glTexCoord2f(50.0f, 50.0f);
glVertex3f(10 - i / 5, 0, -10 + i / 5);
glTexCoord2f(0.0f, 50.0f);
glVertex3f(10 - i / 5, 0, 10 - i / 5);
glEnd();
////////////////////////////////////////////////////////////HUD
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SMOOTH);
glEnable(GL_BLEND); // Turn Blending On
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
GLuint ruka;
ruka = LoadTexture("Data/gun.bmp");
glBindTexture(GL_TEXTURE_2D, ruka);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(450,0);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(450,450);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0,450);
glEnd();
SwapBuffers(g_hDC);
}
The code works well for loading and rendering the platform(weed.bmp) and it also loads and renders gun fine. But big part of gun.bmp is white. I was hoping to get that part transparent. I was also hoping to add more HUD features, which would also need to be partly transparent.
My gun.bmp file: https://drive.google.com/file/d/0BxxlNcAI0eh9cHZGd1ZfMTFwYmM/view?usp=sharing
If you know a solution of this problem please post it. Thanks
You load image as GL_RGB, you want GL_RGBA to have an alpha channel.
Also, you need a 32 bits Bitmap (8 bits/channel × 4 channels = 32 bits).
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 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).