Using DevIL

Started by
7 comments, last by songho 16 years, 5 months ago
I'm tryng to use DevIL to load an image so I can use it as a texture in my openGL program. I've tried to implement the code from this wiki site into my C/openGL/GLUT code but I cant get it to work. I realise that the site uses SDL but I think I've stripped out the DevIL code I need. I've basically just plonked it all into a seperate function and then called that from my display function. When I run it the window appears but it's empty (not black background - I can see my desktop/windows etc inside the window). As you can probably tell I'm a bit of a newcomer to all this so any advice would be much appreciated, as would any pointers to some DevIL tutorial guides because this wiki is all I can find that covers the basic code - however it doesn't really explain any of the code which is probably why I'm struggling. Here's my code:

#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <gl/glaux.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <IL/il.h>
#include <IL/ilu.h>
#include <IL/ilut.h>
//#include <IL/ilu_region.h>
#include "IL/devil_internal_exports.h"



ILuint texid; //ILuint is a 32bit unsigned integer. Variable texid will be used to store image name. 
ILboolean success;
GLuint image;	
int finished;

float xpos = 0.0, ypos = 0.0, zpos = 5.0, xrot = 0, yrot = 0, zrot =0,  angle=0.0, ratio;


void loadImage(){

	glViewport(0, 0, 256, 256);
	glEnable(GL_TEXTURE_2D);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0, 256.0, 256.0, 0.0, 0.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(0.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	
	ilInit();
	ilGenImages(1, &texid); // Generation of one image name 
	ilBindImage(texid); // Binding of image name 
	
	success = ilLoadImage((const ILstring)"E:\image.jpg"); // Loading of image "image.jpg" 

	if (success){ // If no error occured: 
		success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Convert every colour component into unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA 
		if (!success){
			printf("error");
			exit(0);
		}
    
		glGenTextures(1, &image); // Texture name generation 
		glBindTexture(GL_TEXTURE_2D, image); // Binding of texture name 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // We will use linear interpolation for magnification filter 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // We will use linear interpolation for minifying filter 
    
		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()); // Texture specification 
		}
	else {
		printf("error2");
		exit(0);
	}
  
	ilDeleteImages(1, &texid); // Because we have already copied image data into texture data we can release memory used by image. 	

	glBegin(GL_QUADS);
    glTexCoord2i(0, 0); glVertex2i(0, 0);
    glTexCoord2i(0, 1); glVertex2i(0, 256);
    glTexCoord2i(1, 1); glVertex2i(256, 256);
    glTexCoord2i(1, 0); glVertex2i(256, 0);
    glEnd();
	
	glDeleteTextures(1, &image);
}



void init(){
	
	glEnable(GL_TEXTURE_2D);						// Enable Texture Mapping ( NEW )
	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
}


void reshape( int w, int h )
{
	if(h == 0) //
		h = 1;

	ratio = 1.0f * w / h;
	// Reset the coordinate system before modifying
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	
	// Set the viewport to be the entire window
    glViewport(0, 0, w, h);

	// Set the clipping volume
	gluPerspective(80,ratio,1,200);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0, 0, 30,
		      0,0,10,
			  0.0f,1.0f,0.0f);
}

void camera (void) {
	
	glRotatef(xrot,1.0,0.0,0.0); //rotate our camera on the x-axis (left and right)
	glRotatef(yrot,0.0,1.0,0.0); //rotate our camera on the y-axis (up and down)
	glRotatef(zrot,0.0,0.0,1.0); 
}


void display( void )
{
	camera();
	loadImage();
}



void keyboard (unsigned char key, int x, int y) {
	
	//Rotate about X axis
	if (key=='q') {
		xrot += 10;
		if (xrot >360) xrot -= 360; 
	}
	if (key=='z'){
		xrot -= 10;
		if (xrot < -360) xrot += 360;
	}
	
	//Rotate about Y axis
	if (key=='d'){
		yrot += 10;
		if (yrot >360) yrot -= 360;
	}
	if (key=='a'){
		yrot -= 10;
		if (yrot < -360)yrot += 360;
	}

	//Rotate about Z axis
	if (key=='e'){
		zrot += 10;
		if (zrot >360) zrot -= 360;
	}
	if (key=='c'){
		zrot -= 10;
		if (zrot < -360)zrot += 360;
	}

	if (key==27){
		exit(0);
	}
}


int main (int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |GLUT_DEPTH);
	glutInitWindowSize(550, 550);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Testing");
	init();
	glutDisplayFunc(display);
	glutIdleFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();

	return 0;
}


Thanks again.
Advertisement
First of all I must say that I haven't used DevIL so I can't really comment on that one.But what I have to say is that you are generating the image every frame in your display callback which is bad and slow.Also you are setting every frame your projection view which is not required either.You can put them in your init code and draw everyhing else in the draw call.Also you have to use glBindTexture before glBegin to set the current texture when you want to render it.These are just of the top of my head,someone else may show you other errors as well.
Does the image has power of 2 dimensions? if now, are you sure your card supports the NPOT extension?

The call to ilInit() should be in your main() function rather than loadImage() but I doubt that would cause it to fail.
you never call glutSwapBuffers.
[size="1"]
Thanks mrbastard, it was the glutSwapBuffers. So I've put those in and tried to alter the data a bit by putting more in init() and less in display(). It now displays the texture on screen but I cant use gluLookAt() or it disappears, and when I use any of my camera functions the image doesn't redraw, I can see the top of the texture flickering but the rest is black - it's almost as if it cant redraw it quick enough - but I dont think this is the probably because my computer's pretty fast (C2D @2.9GHz, 7800GTX). I think it's more to do with the fact I've got code in the wrong place, is there anywhere that explains where these functions should be placed in your call?

Here's my new code:

   #include <windows.h>#include <GL/gl.h>#include <GL/glu.h>#include <gl/glaux.h>#include <GL/glut.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include <vector>#include <IL/il.h>#include <IL/ilu.h>#include <IL/ilut.h>//#include <IL/ilu_region.h>#include "IL/devil_internal_exports.h"ILuint texid; //ILuint is a 32bit unsigned integer. Variable texid will be used to store image name. ILboolean success;GLuint image;	int finished;float xpos = 0.0, ypos = 0.0, zpos = 5.0, xrot = 0, yrot = 0, zrot =0,  angle=0.0, ratio;void loadImage(){	glViewport(0, 0, 256, 256);	glEnable(GL_TEXTURE_2D);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	glOrtho(0.0, 256.0, 256.0, 0.0, 0.0, 100.0);	glMatrixMode(GL_MODELVIEW);	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	glClearDepth(0.0f);	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	//gluLookAt(0, 0, 10, 0,0,1,0.0f,1.0f,0.0f);	glBegin(GL_QUADS);    glTexCoord2i(0, 0); glVertex2i(0, 0);    glTexCoord2i(0, 1); glVertex2i(0, 256);    glTexCoord2i(1, 1); glVertex2i(256, 256);    glTexCoord2i(1, 0); glVertex2i(256, 0);    glEnd();	glutSwapBuffers();	//glDeleteTextures(1, &image);	}void init(){		glEnable(GL_TEXTURE_2D);						// Enable Texture Mapping ( NEW )	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		ilInit();	ilGenImages(1, &texid); // Generation of one image name 	ilBindImage(texid); // Binding of image name 		success = ilLoadImage((const ILstring)"E:\image.jpg"); // Loading of image "image.jpg" 	if (success){ // If no error occured: 		success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Convert every colour component into unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA 		if (!success){			printf("error");			exit(0);		}    		glGenTextures(1, &image); // Texture name generation 		glBindTexture(GL_TEXTURE_2D, image); // Binding of texture name 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // We will use linear interpolation for magnification filter 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // We will use linear interpolation for minifying filter     		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()); // Texture specification 		}	else {		printf("error2");		exit(0);	}  	ilDeleteImages(1, &texid); // Because we have already copied image data into texture data we can release memory used by image. 	}void reshape( int w, int h ){	if(h == 0) //		h = 1;	ratio = 1.0f * w / h;	// Reset the coordinate system before modifying	glMatrixMode(GL_PROJECTION);	glLoadIdentity();		// Set the viewport to be the entire window    glViewport(0, 0, w, h);	// Set the clipping volume	gluPerspective(80,ratio,1,200);	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	//gluLookAt(0, 0, 10, 0,0,1, 0.0f,1.0f,0.0f);}void camera (void) {		glRotatef(xrot,1.0,0.0,0.0); //rotate our camera on the x-axis (left and right)	glRotatef(yrot,0.0,1.0,0.0); //rotate our camera on the y-axis (up and down)	glRotatef(zrot,0.0,0.0,1.0); }void display( void ){	camera();	loadImage();}void keyboard (unsigned char key, int x, int y) {		//Rotate about X axis	if (key=='q') {		xrot += 10;		printf("qq");		if (xrot >360) xrot -= 360; 	}	if (key=='z'){		xrot -= 10;		if (xrot < -360) xrot += 360;	}		//Rotate about Y axis	if (key=='d'){		yrot += 10;		if (yrot >360) yrot -= 360;	}	if (key=='a'){		yrot -= 10;		if (yrot < -360)yrot += 360;	}	//Rotate about Z axis	if (key=='e'){		zrot += 10;		if (zrot >360) zrot -= 360;	}	if (key=='c'){		zrot -= 10;		if (zrot < -360)zrot += 360;	}	if (key==27){		exit(0);	}}int main (int argc, char **argv){	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |GLUT_DEPTH);	glutInitWindowSize(550, 550);	glutInitWindowPosition(100, 100);	glutCreateWindow("Testing");	init();	glutDisplayFunc(display);	glutIdleFunc(display);	glutReshapeFunc(reshape);	glutKeyboardFunc(keyboard);	glutMainLoop();	return 0;}


Thanks again.
Why do you want to use gluLookAt with a orthographic projection ?Also move this code out of loadImage and at your init or in separate function called setOrtho

glViewport(0, 0, 256, 256);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 256.0, 256.0, 0.0, 0.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);

You only need to reset the view by calling glLoadIdentity() at the start of your display callback,but in this case you are not required to set the Projection matrix every frame(it's only required if you want to mix 2d and 3d in the scene)
Quote:Original post by mpledge52
Thanks mrbastard

No problem.
Quote:Original post by mpledge52
it's almost as if it cant redraw it quick enough - but I dont think this is the probably because my computer's pretty fast (C2D @2.9GHz, 7800GTX).

It's because you're loading the image every frame.

There's nothing that will tell you exactly where to call anything - after all nobody knows where to call it in your code except you. In general though, it sounds like you need to get used to following the flow of your program in your mind. Though some of your problems may be down to misunderstanding glut.

For example, the function pointer passed to glutDisplay will be called every frame. In your case this means every instruction in display() gets called every frame, which in turn means loadImage gets called every frame. This why it can't redraw quick enough - it doesn't matter how fast your cpu and gpu are if they have to wait for the image file to load from disk EVERY FRAME before they can do their work. Make sense?

So, I suggest seperating out your drawing and image loading / texture upload code.
[size="1"]
Thanks everyone its working perfectly now. [smile]

Is there any way I can copy the texture image into a 2D array so I can view/manipulate the data stored in it?
Quote:Original post by mpledge52
Is there any way I can copy the texture image into a 2D array so I can view/manipulate the data stored in it?

You can allocate an array in your application which has the same size of the original image, then copy the image data to your array using memcpy() of C/C++ or ilCopyPixels() of DevIL.
int dataSize = width * height * 3; // 3 bytes per pixel (RGB)unsigned char* buffer = new unsigned char[dataSize];memcpy(buffer, ilGetData(), dataSize);// or use DevIL functionilCopyPixels(0,0, width, height, 1, IL_RGB, IL_BYTE, (void*)buffer);...delete [] buffer;

This topic is closed to new replies.

Advertisement