3D texture coordinate generation doesn't work as expected, need some help

Started by
7 comments, last by usbman3 13 years, 3 months ago
EDit: Problem has been solved. Don't bother reading this thread.

I need to render some textured axis aligned cubes. Currently I'm using a 2D texture.
I want to use a 3D texture and let OpenGL automatically generate texture coordinates, to simplify things a bit.

I have some code to generate a 2x2x2 checker pattern and then render cubes with it:
#include <stdlib.h>#include <stdint.h>#include <string.h>#include <GL/gl.h>#include "image.h"#include "checkers3d.h"GLuint make_3d_checkers( GLubyte color1[3], GLubyte color2[3] ){	GLuint tex;	uint8_t pixels[8*3];		/*	color1, color2,	color2, color1,	color2, color1,	color1, color2	*/		memcpy( pixels, color1, 3 );	memcpy( pixels+3, color2, 3 );	memcpy( pixels+6, color2, 3 );	memcpy( pixels+9, color1, 3 );	memcpy( pixels+12, color2, 3 );	memcpy( pixels+15, color1, 3 );	memcpy( pixels+18, color1, 3 );	memcpy( pixels+21, color2, 3 );		glGenTextures( 1, &tex );	glBindTexture( GL_TEXTURE_3D, tex );	glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT );	glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT );	glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT );	// Set the texture's stretching properties	glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );	glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );		// apply color and lighting effects to texture	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );		// upload texture	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );	glTexImage3D( GL_TEXTURE_3D, 0, 3, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );		return tex;}

static void draw_map_3d( void ){	glEnable( GL_TEXTURE_GEN_S );	glEnable( GL_TEXTURE_GEN_T );	glEnable( GL_TEXTURE_GEN_R );	GLenum mode = GL_OBJECT_LINEAR;	glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, mode );	glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, mode );	glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, mode );	glEnable( GL_TEXTURE_3D );		int n;	Box *b;	static GLuint tex = 0;		if ( tex == 0 )	{		GLubyte color1[3] = {DARK};		GLubyte colo2[3] = {BRIGHT};		tex = make_3d_checkers( color1, colo2 );	}		glBindTexture( GL_TEXTURE_3D, tex );	for( n=0; n<map.num_boxes; n++ )	{		b = &map.boxes[n];				glPushMatrix();			glTranslatef( b->centre[0], b->centre[1], b->centre[2] );			glScalef( b->size[0], b->size[1], b->size[2] );			glMatrixMode( GL_TEXTURE );				glLoadIdentity();				glTranslatef( b->centre[0], b->centre[1], b->centre[2] );				glScalef( b->size[0], b->size[1], b->size[2] );			glMatrixMode( GL_MODELVIEW );			glutSolidCube( 2.0f );		glPopMatrix();	}		glMatrixMode( GL_TEXTURE );	glLoadIdentity();	glMatrixMode( GL_MODELVIEW );		glDisable( GL_TEXTURE_3D );	glDisable( GL_TEXTURE_GEN_S );	glDisable( GL_TEXTURE_GEN_T );	glDisable( GL_TEXTURE_GEN_R );}


But texture coordinates aren't generated correctly for Z axis

<image removed>

What am I doing wrong?

[Edited by - usbman3 on December 30, 2010 9:44:30 AM]
Advertisement
I would imagine it is your 3d texture generation code.
Did you inspect it with a debugger? http://www.opengl.org/wiki/Debugging_Tools
Did you try GLIntercept. You can use it to capture the commands that are executed and it will show the textures as well.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Unfortunately none of those debugging tools are available in kubuntu repos (I could install them manually but I'm lazy and I do that only if I can't solve this without them).

If I don't initialize the texture pixels at all (they're random!), I still get incorrect texture coordinates, so the problem can not be in the texture generating function.
The only thing I can think of is the fact that you're using glutSolidCube(). Do you know if it sets the third texture coordinate?
You can write each layer to disk as a png file and inspect to make sure the 3d pattern is ok.

Or, write shaders. Do the texcoord generation yourself in the vertex shader. Here is the math. You need GL 2.0 for GLSL support.
http://www.opengl.org/wiki/Mathematics_of_glTexGen

Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Try setting the GL_OBJECT_PLANE for GL_R manually, as I believe the defaults are {0, 0, 0, 0} for GL_R.
GLfloat plane[4] = {0.0f, 0.0f, 1.0f, 0.0f};glTexGenfv(GL_R, GL_OBJECT_PLANE, plane);
I wrote my own functions for rendering cubes:
#include <GL/gl.h>#include "cube.h"static const GLshort the_coords[] = {	-1,-1,-1, // 0	-1,-1,1,  // 1	-1,1,-1,  // 2	-1,1,1,   // 3	1,-1,-1,  // 4	1,-1,1,   // 5	1,1,-1,   // 6	1,1,1,    // 7};static const GLubyte indexes[] = {	// x/y top	1,5,7,3,	// x/y bottom	0,2,6,4,	// z/x	3,7,6,2,	// -------	1,0,4,5,	// z/y	4,6,7,5,	// -------	0,1,3,2};void begin_cubes( void ){	glEnableClientState( GL_VERTEX_ARRAY );	glEnableClientState( GL_TEXTURE_COORD_ARRAY );		glVertexPointer( 3, GL_SHORT, 0, the_coords );	glTexCoordPointer( 3, GL_SHORT, 0, the_coords );}void draw_cube( void ){	glDrawElements( GL_QUADS, 24, GL_UNSIGNED_BYTE, indexes );}void end_cubes( void ){	glDisableClientState( GL_VERTEX_ARRAY );	glDisableClientState( GL_TEXTURE_COORD_ARRAY );	glDisableClientState( GL_NORMAL_ARRAY );}


It worked just like glutSolidCube.

Then I removed OpenGL texture coordinate generation stuff.

Now it works as it should:


But I still don't know what was wrong with GL_TEXTURE_GEN_R. I guess it's just the broken ATI drivers, whatever...
Quote:Original post by usbman3
But I still don't know what was wrong with GL_TEXTURE_GEN_R. I guess it's just the broken ATI drivers, whatever...


I'm pretty sure it's just the default values. It should work if you manually set the GL_R plane.
Quote:Original post by Erik Rufelt
Try setting the GL_OBJECT_PLANE for GL_R manually, as I believe the defaults are {0, 0, 0, 0} for GL_R.
GLfloat plane[4] = {0.0f, 0.0f, 1.0f, 0.0f};glTexGenfv(GL_R, GL_OBJECT_PLANE, plane);


Now texture coordinate generation and glutSolidCube work properly. Thanks.

But lighting doesn't work with either methods. Just with the 2D texture. (I have added a normal array to draw_cube()).

What might be the problem with lighting?
EDIT: Lighting didn't work because I didn't have the glMaterial(...) calls in the new functions which use 3D textures.

Just to make it clear, there are no problems anymore (so don't try to help). Thanks for your replies.


[Edited by - usbman3 on December 30, 2010 10:23:23 AM]

This topic is closed to new replies.

Advertisement