Only Last Texture Works

Hi,

I’m trying to develop a simple app. however I’m having a problem with textures.

The problem is that only the last texture I create is available. I’ve spent ages looking at the code however I can’t see where the problem is. The textures seem to be loading OK. The code I’m using is below.

Any help with this would be much appreciated.

Cheers,

Chris

 // Get rid of console window.
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

//***************************************************************************\\
// Includes.

#include <windows.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/openglut.h>
#include <GL/glaux.h>
#include "functions.h"
#include <stdio.h>

//***************************************************************************\\
// Definitions.

#define ESC					27
#define TRUE				1
#define FALSE				0
#define NUMBER_OF_TEXTURES	4

//***************************************************************************\\
// Globals.

static float angle = 0.0;
static float deltaAngle = 0.0;
static int	 deltaFwBw = 0;
static int	 deltaUpDn = 0;
static double ratio;

static double x = 0.0f;
static double y = 1.0f;
static double z = 10.0f;

static double lx = 0.0f;
static double ly = 0.0f;
static double lz = -1.0f;

GLuint	texture[NUMBER_OF_TEXTURES];
char	*textureNames[NUMBER_OF_TEXTURES] = {"crate.bmp", "grass.bmp", "speaker.bmp", "stone.bmp"};
GLfloat lightPosition[] = {10.0, 10.0, 10.0, 0.0};

//***************************************************************************
// Render the scene.

void renderScene(void) 
{
	// Check to see if we've moved.
	if(deltaFwBw)
		moveFWBW(deltaFwBw);
	if(deltaUpDn)
		moveUpDn(deltaUpDn);
	if(deltaAngle) 
	{
		angle += deltaAngle;
		rotateY(angle);
	}
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texture[3]);

	glBegin(GL_QUADS);
   // Front Face
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		// Back Face
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		// Top Face
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		// Bottom Face
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		// Right face
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		// Left Face
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
	glEnd();

	glDisable(GL_TEXTURE_2D);
	
	glutSwapBuffers();
}

//***************************************************************************\\
// Rotate the camera about the y-axis.

void rotateY(float ang)
{
	lx = sin(ang);
	lz = -cos(ang);
	glLoadIdentity();
	gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);				/// Don't move the light.
}

//***************************************************************************\\
// Move the camera forwards and backwards.

void moveFWBW(int direction) 
{
	x = x + direction * (lx) * 0.1;
	z = z + direction * (lz) * 0.1;
	glLoadIdentity();
	gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
}

//***************************************************************************\\
// Move the camera up and down (without rotation).

void moveUpDn(int direction)
{
	y = y + direction * 0.1;
	glLoadIdentity();
	gluLookAt(x, y, z, lx + x, ly + y, lz + z, 0.0f, 1.0f, 0.0f);
}

//***************************************************************************\\
// Handle special key press.

void pressSpecialKey(int key, int x, int y) 
{
	switch(key) 
	{
		case GLUT_KEY_LEFT: 
			deltaAngle = -0.01f;
			break;
		case GLUT_KEY_RIGHT: 
			deltaAngle = 0.01f;
			break;
		case GLUT_KEY_UP: 
			deltaFwBw = 1;
			break;
		case GLUT_KEY_DOWN: 
			deltaFwBw = -1;
			break;
	}
}

//***************************************************************************\\
// Handle special key release.

void releaseSpecialKey(int key, int x, int y) 
{
	switch (key) 
	{
		case GLUT_KEY_LEFT: 
		case GLUT_KEY_RIGHT: 
			deltaAngle = 0.0f;
			break;
		case GLUT_KEY_UP: 
		case GLUT_KEY_DOWN: 
			deltaFwBw = 0;
			break;
	}
}

//***************************************************************************\\
// Handl normal key press.

void pressNormalKey(unsigned char key, int x, int y) 
{
	switch(key)
	{
		case ESC:
			exit(0);
			break;
		case 'u':
			deltaUpDn = 1;
			break;
		case 'd':
			deltaUpDn = -1;
			break;
	}		
}

//***************************************************************************\\
// Handl normal key release.

void releaseNormalKey(unsigned char key, int x, int y) 
{
	switch(key)
	{
		case 'u':
			deltaUpDn = 0;
		case 'd':
			deltaUpDn = 0;
	}
}

//***************************************************************************\\
// Initialise the scene.

void initScene()
{
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glClearDepth(1.0f);												/// Depth buffer setup.
	glDepthFunc(GL_LEQUAL);											/// The type of depth testing to do.
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);				/// Use the best available perspective calculations.
	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);						/// Use the best available antialising.
	glClearColor(0.6f, 1.0f, 1.0f, 1.0f);							/// Blue sky background.
	init_Textures();												/// Initialise the textures.
	init_Lights();													/// Initialise the lights.
}

//***************************************************************************\\
/// Initialise the lighting.

void init_Lights()
{
	GLfloat lightPosition[] = {10.0, 10.0, 10.0, 0.0};
	GLfloat lightAmbient[] = {0.25, 0.25, 0.25, 1.0};
	
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightAmbient);
	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
}

//***************************************************************************\\
/// Initialise the textures.

void init_Textures()
{
	int succeeded, i;
	
	/// Load the textures.
	for(i = 0; i < NUMBER_OF_TEXTURES; i++)						
	{
		succeeded = load_Texture(textureNames[i]);
		if (!succeeded)											
			printf("Could not load texture %d
", i);			/// If texture didn't load return FALSE.
	}
	
	/// Set the general parameters of the textures.
	/// Note that texture binding is being done during the loading of the textures.
	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_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

//***************************************************************************\\
/// Load a texture.

int load_Texture(char* str)
{
	static int count = 0;
	int status = FALSE;									/// Status indicator.
	AUX_RGBImageRec *TextureImage[1];					/// Create storage space for the texture.
	memset(TextureImage, 0, sizeof(void *)*1);			/// Set the pointer to NULL.
	
	/// Load the bitmap.
	TextureImage[0] = loadBMP(str);
	if(TextureImage[0])
	{
		status = TRUE;									/// Set the status to TRUE.

		glGenTextures(1, &texture[count]);				/// Create the texture.

		/// Texture generation using data from the bitmap.
		glBindTexture(GL_TEXTURE_2D, texture[count]);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
	}

	if(TextureImage[0])									/// If texture exists
	{
		if (TextureImage[0]->data)						/// If texture image exists
			free(TextureImage[0]->data);				/// Free the texture image memory

		free(TextureImage[0]);							/// Free the image structure
	}

	count++;

	return status;										/// Return the status
}

//***************************************************************************\\
/// Load a bitmap.

AUX_RGBImageRec* loadBMP(char *filename)
{
	FILE *file = NULL;							/// Pointer to bitmap file.

	if(!filename)								/// Make sure a filename was given.
		return NULL;							/// If not return NULL.

	file = fopen(filename, "r");				/// Check to see if the file exists.
	
	if(file)									/// Does the file exist?
	{
		fclose(file);							/// Close the handle.
		return auxDIBImageLoad(filename);		/// Load the bitmap and return a pointer.
	}

	return NULL;								/// If load failed return NULL.
}

//***************************************************************************\\
// Handle resizing the window without distorting the model.

void changeWindowSize(int w, int h)
{
	// Prevent a divide by zero, when window is too short
	// (you cant make a window of zero width).
	if(h == 0)
		h = 1;

	ratio = 1.0 * 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 correct perspective.
	gluPerspective(45, ratio, 1, 1000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
}

//***************************************************************************\\
// Main function.

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(700, 500);
	glutCreateWindow("Texture_01");
	initScene();
	glutIgnoreKeyRepeat(1);
	glutSpecialFunc(pressSpecialKey);
	glutSpecialUpFunc(releaseSpecialKey);
	glutKeyboardFunc(pressNormalKey);
	glutKeyboardUpFunc(releaseNormalKey);
	glutDisplayFunc(renderScene);
	glutIdleFunc(renderScene);
	glutReshapeFunc(changeWindowSize);
	glutMainLoop();
	return(0);
} 

In your display function you have called the following function:

glBindTexture(GL_TEXTURE_2D, texture[3]);

take a look at texture[3]. try to change the value of the second argument of the function glBindTexture() to use from the other textures.
-Ehsan-

Thanks for your reply.

If I change the value of texture[3] to, say, texture 0, 1 or 2, nothing happens–no textures are drawn. The only one that works is texture[3].

That’s where the problem lies.

Any ideas.

Cheers,

Chris

Originally posted by cpsmusic:

	/// Set the general parameters of the textures.
	/// Note that texture binding is being done during the loading of the textures.
	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_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Simple.
Texture parameters are per texture object. These are stored with the last bound texture object and recalled on each further glBindTexture call (no need to set these parameters again).

Having this at the place in your code after the loading of textures means you set it only for the last texture.
Unfortunately the minification filter default in OpenGL is using mipmaps. Not downloading mipmaps then means your textures 0 to 2 are inconsistent and shut off the texture unit when bound.
TexEnv is per texture unit, that can be left where it is.

Put the above code inside your texture loading routine directly after the glBindTexture call.

Great work!

Thanks everyone for the quick responses. That fixed the problem.

Cheers,

Chris