I fixed this, the solution was to add "ilDisable(IL_BLIT_BLEND)". Apparently the ilBlit function would combine alpha channels by default, instead of overwriting them.
Any other advice for cleaning up my code is welcome, though
=========
I haven't used OpenGL before this week, I'm probably making an obvious mistake.
I'm using DevIL to load a PNG file with alpha channel, blit a piece of the file to another texture, and use that texture to draw 6 faces of a cube.
It starts off black (I think transparent), but as I blit other textures a lot by holding down the arrow key, I'll see the textures with random transparent parts. The scary thing is, if I free the DevIL image after loading to openGL with glTexImage2D, it will stay transparent. I think it's only corrupted memory that is letting me see anything!
Here's the complete code...
//SFML test app
//SFML
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
//DevIL
#include <IL/il.h>
#include <IL/ilu.h>
//STL
#include <iostream>
#include <string>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
const string imageFilename("terrain.png");
//openGL image
GLuint image;
size_t texmap_X = 1;
size_t texmap_Y = 3;
const size_t texmap_SIZE = 16;
//Start
//draw cube faces
void drawCubes() {
//Draw cube
glBegin(GL_QUADS);
//x: A = -50, B = 50
//y: C = -50, D = 50
//z: E = -50, F = 50
//A
glTexCoord2i(0,0); glVertex3i( -16, -16, -16); //Lower left
glTexCoord2i(1,0); glVertex3i( -16, -16, 16); //Lower right
glTexCoord2i(1,1); glVertex3i( -16, 16, 16); //Top right
glTexCoord2i(0,1); glVertex3i( -16, 16, -16); //Top left
//B
glTexCoord2i(0,0); glVertex3i( 16, -16, 16); //Lower left: BCF
glTexCoord2i(1,0); glVertex3i( 16, -16, -16); //Lower right: BCE
glTexCoord2i(1,1); glVertex3i( 16, 16, -16); //Top right: BDE
glTexCoord2i(0,1); glVertex3i( 16, 16, 16); //Top left: BDF
//C
glTexCoord2i(0,0); glVertex3i( -16, -16, -16); //Lower left: ACE
glTexCoord2i(1,0); glVertex3i( 16, -16, -16); //Lower right: BCE
glTexCoord2i(1,1); glVertex3i( 16, -16, 16); //Top right: BCF
glTexCoord2i(0,1); glVertex3i( -16, -16, 16); //Top left: ACF
//D
glTexCoord2i(0,0); glVertex3i( -16, 16, 16); //Lower left: ADF
glTexCoord2i(1,0); glVertex3i( 16, 16, 16); //Lower right: BDF
glTexCoord2i(1,1); glVertex3i( 16, 16, -16); //Top right: BDE
glTexCoord2i(0,1); glVertex3i( -16, 16, -16); //Top left: ADE
//E
glTexCoord2i(0,0); glVertex3i( 16, -16, -16); //Lower left: BCE
glTexCoord2i(1,0); glVertex3i( -16, -16, -16); //Lower right: ACE
glTexCoord2i(1,1); glVertex3i( -16, 16, -16); //Top right: ADE
glTexCoord2i(0,1); glVertex3i( 16, 16, -16); //Top left: BDE
//F
glTexCoord2i(0,0); glVertex3i( -16, -16, 16); //Lower left: ACF
glTexCoord2i(1,0); glVertex3i( 16, -16, 16); //Lower right: BCF
glTexCoord2i(1,1); glVertex3i( 16, 16, 16); //Top right: BDF
glTexCoord2i(0,1); glVertex3i( -16, 16, 16); //Top left: ADF
glEnd();
}
//Blit from texture map to current OpenGL texture
ILuint blitTexture( ILuint texmap, ILuint SrcX, ILuint SrcY, ILuint Width, ILuint Height) {
//Take out a specific block from the texture grid (Blit)
ILuint il_blocktex;
ilGenImages(1, &il_blocktex);
ilBindImage(il_blocktex);
ilTexImage( Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
//Blit the rectangle from texmap to il_blocktex
ilBlit( texmap, 0, 0, 0, SrcX, SrcY, 0, Width, Height, 1);
glBindTexture(GL_TEXTURE_2D, image);
//Set zoom filters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //GL_LINEAR?
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//Copy current DevIL image to OpenGL image
glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP),
ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0,
ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());
//ilDeleteImages(1, &il_blocktex); //free memory used by DevIL
return il_blocktex;
}
//Set up buffer, perspective, blah blah blah
void startOpenGL() {
//OPENGL setup in SFML
//Set color and depth clear value
glClearDepth(1.0f);
glClearColor(0.f, 0.f, 0.f, 1.f);
// Enable Z-buffer read and write
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
//Enable texture mapping
glViewport(0, 0, 800, 600);
glEnable(GL_TEXTURE_2D);
//Transparency in textures
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
// Setup perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.f, 1.f, 1.f, 500.f);
//Move camera
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
//Create OpenGL texture
glGenTextures(1, &image);
}
//Load the image file
ILuint loadImageFile() {
ILuint il_texmap;
ilGenImages(1, &il_texmap);
ilBindImage(il_texmap);
if (ilLoad(IL_PNG, imageFilename.c_str())) {
//Convert image to RGBA
if (!ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE)) {
cerr << "Error converting " << imageFilename << endl;
ILenum ilErrorCode = 0;
while ( (ilErrorCode = ilGetError()) != IL_NO_ERROR) {
cerr << "Error code " << ilErrorCode << endl;
}
return 0;
}
} else {
cerr << "Error loading " << imageFilename << endl;
ILenum ilErrorCode = 0;
while ( (ilErrorCode = ilGetError()) != IL_NO_ERROR) {
cerr << "Error code " << ilErrorCode << endl;
}
return 0;
}
return il_texmap;
}
int main()
{
//Compare devIL DLL version to header version
if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) {
cerr << "devIL wrong DLL version" << endl;
return 1;
}
//SFML variables
sf::Clock Clock;
sf::WindowSettings Settings;
Settings.DepthBits = 24;
Settings.StencilBits = 8;
Settings.AntialiasingLevel = 2;
//Create the program window, with settings
sf::Window App(sf::VideoMode(800, 600, 32),
"SFML OpenGL", sf::Style::Close, Settings);
//Initialize OpenGL
startOpenGL();
//Start DevIL
ilInit();
//Load terrain image map
ILuint il_texmap = loadImageFile();
if (il_texmap == 0) {
return 0; //error, exit program
}
//Pick a texture
blitTexture( il_texmap, texmap_X * texmap_SIZE, texmap_Y * texmap_SIZE,
texmap_SIZE, texmap_SIZE);
//Event loop
sf::Event Event;
bool Running = true;
while (Running && App.IsOpened()) {
//Set window
App.SetActive();
//Clear window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Move camera
glTranslatef(0, -30, -100);
//Rotate camera
glRotatef(Clock.GetElapsedTime() * 2, 1, 0, 0); //yaw
glRotatef(Clock.GetElapsedTime() * 30, 0, 1, 0); //Rotate about Y axis
//glRotatef(Clock.GetElapsedTime() * 90, 0, 0, 1); //roll
drawCubes();
//Display the rendered frame
App.Display();
//Check events
while (App.GetEvent(Event))
{
switch( Event.Type) {
case sf::Event::Resized:
glViewport(0,0, Event.Size.Width, Event.Size.Height);
break;
case sf::Event::KeyPressed:
switch ( Event.Key.Code) {
case sf::Key::Escape:
Running = false;
break;
case sf::Key::Up:
texmap_Y = (texmap_Y - 1) % 16;
blitTexture( il_texmap, texmap_X * texmap_SIZE,
texmap_Y * texmap_SIZE, texmap_SIZE, texmap_SIZE);
break;
case sf::Key::Down:
texmap_Y = (texmap_Y + 1) % 16;
blitTexture( il_texmap, texmap_X * texmap_SIZE,
texmap_Y * texmap_SIZE, texmap_SIZE, texmap_SIZE);
break;
case sf::Key::Left:
texmap_X = (texmap_X - 1) % 16;
blitTexture( il_texmap, texmap_X * texmap_SIZE,
texmap_Y * texmap_SIZE, texmap_SIZE, texmap_SIZE);
break;
case sf::Key::Right:
texmap_X = (texmap_X + 1) % 16;
blitTexture( il_texmap, texmap_X * texmap_SIZE,
texmap_Y * texmap_SIZE, texmap_SIZE, texmap_SIZE);
break;
default:
break;
}
break;
default:
break;
}
}
}
return 0;
}
How I compile:
g++ -Wall -O3 -I/c/dev/axus/include -o build/main.o -c src/main.cpp
g++ build/main.o -Wall -O3 -Wl,--enable-auto-import -L/c/dev/axus/lib -lopengl32 -lglu32 -lDevIL -lILU -lsfml-system -lsfml-window -lwsock32 -o testsfml.exe