3D Texture producing stripes

Hi,
I am using the programming language C and the openGL-library freeglut under Windows 8.1.
I am trying to apply a 3D Texture to a 3D model which I draw by loading it from an obj-file. To do so I use the following code:

glEnable(GL_TEXTURE_3D);

unsigned int texname;
glGenTextures(1, &texname);
glBindTexture (GL_TEXTURE_3D, texname);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB32F, WIDTH, HEIGHT, DEPTH, 0, GL_RGB, GL_FLOAT, solidTexture);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
glVertexPointer(3, GL_FLOAT, 0, faces);
glColorPointer(3, GL_FLOAT, 0, solidTexture);
glTexCoordPointer(3, GL_FLOAT, 0, solidTexture);
glDrawArrays(GL_QUADS, 0, TotalConnectedComponents);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
glDisable(GL_TEXTURE_3D);

Drawing the quad which I loaded from an obj-file works fine, but applying the 3D-texture creates these crazy stripes on the quad:
[ATTACH=CONFIG]959[/ATTACH]

The texture is actually some kind of white noise which I created by using the rand()-function to fill a 3-dimensional array including 3 values per colour (RGB):

GLfloat *solidTexture= (GLfloat*) malloc(sizeof(GLfloat) * WIDTH * HEIGHT * DEPTH * 3);

Can someone please help me getting rid of those stripes? I can also post my whole code if necessary.

Thank you!
Fatman_Stoned

Passing the same array for both colour and texture coordinates doesn’t seem to make much sense.

The effect is what you would expect if two of the components were either constant or determined solely by the other component.

What values does the [var]solidTexture[/var] array contain?

Hi GClements,

Passing the same array for both colour and texture coordinates doesn’t seem to make much sense.

You are right, that was the problem producing the stripes. Thank you!
I now read the whole obj-file (including the “vt” data), ordered it concerning to the “f” data and used it as parameter for the glTexCoordPointer-function. This seems to work…almost.
What I now get is this (I use a a little bit more complex model now):
[ATTACH=CONFIG]961[/ATTACH]
At this model I have several cubic faces at each side which is unfortunately very good visible in the picture because you see the lines splitting the faces. Another problem is that some faces (or at least half of a face = a triangle) are coloured as a whole in black/white which is very disturbing.
Do you have an idea what is going wrong? Is it a problem with the shader?

Thank you!
Fatman_Stoned

My first guess would be that there’s something wrong with the normals. Are those being read from the OBJ file, or are they generated?

The normals are being read from the OBJ-file (“vn” data) and as well as the texture coordintes I order them depending the indexes from the “f” data (v/vt/vn). After ordering I use the them as parameter for the glNormalPointer-function. The normals-data itself is always 1.0, 0.0 or -1.0; Unfortunatley there is no change, the problem still appears.
My main code block now looks like this:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
glVertexPointer(3, GL_FLOAT, 0, faces);
glNormalPointer(GL_FLOAT, 0, normals);
glColorPointer(3, GL_FLOAT, 0, solidTexture);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
glDrawArrays(GL_QUADS, 0, TotalConnectedComponents);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT);

Thank you for your help!
Fatman_Stoned

Okay it seems that I solved the problem. The line ‘glEnable( GL_COLOR_MATERIAL )’ was causing the problem, the normals were okay. Thanks anyway!

The last thing I’d like to eradicate is the problem having these stripes on 4 special faces on the side of the extrusion:
[ATTACH=CONFIG]962[/ATTACH]
Is there a possibility that the CAD program exported some information into the OBJ-file telling opengl that the face was extruded? (some kind of wrong normals/texture coordinates?)
Or do you have another idea why this is happening?

Thanks for your help!
Fatman_Stoned

[QUOTE=Fatman_Stoned;1265198]The last thing I’d like to eradicate is the problem having these stripes on 4 special faces on the side of the extrusion:

Is there a possibility that the CAD program exported some information into the OBJ-file telling opengl that the face was extruded? (some kind of wrong normals/texture coordinates?)
Or do you have another idea why this is happening?
[/QUOTE]

The appearance is what you’d expect if both ends of the extruded section had the same texture coordinates.

Hi,
I am facing another problem now. I’m trying to apply a 3D texture to a cuboid which should look like a piece of wood. To do so I created an array containing a 3D texture with dark- and light brown colour points. The dark points should be the annual rings of the tree.
When I apply the texture to the model I get this result with a 128x128x128 texture:
[ATTACH=CONFIG]972[/ATTACH]
and this result with a 256x256x256 texture:
[ATTACH=CONFIG]973[/ATTACH]

It looks to me that the texture gets kind of wrapped around… which I definitively don’t want for 3D textures! Also on the top face (where the rings should be visible) you can see only a quater of the texture having its center point on one corner.
Does anyone have an idea what I am doing wrong?

Thanks!
Fatman_Stoned

Your texture coordinates are wrong.

The fact that there’s a discontinuity at each edge indicates that there isn’t a 1:1 correspondence between vertices and texture coordinates. Instead, the texture coordinates for a vertex are different for each face.

Also, the fact that you get radically different results for 128^3 and 256^3 textures indicates that either the texture coordinates are different in each case or the textures themselves are different (i.e. the 128^3 texture isn’t just a lower-resolution version of the 256^3 texture).

The OBJ file should have 8 vertex coordinates (“v”) and 8 texture coordinates (“vt”). In the face definitions, there should be a 1:1 correspondence between vertex coordinate indices and texture coordinate indices, i.e. a given vertex coordinate index should always be paired with the same texture coordinate index.

Can you post the OBJ file? Or if you’re now generating the vertex data in the program, can you post the relevant code?

That’s the OBJ I am using, created with Autodesk Maya:

# This file uses centimeters as units for non-parametric coordinates.

v -12.055533 -20.648668 11.898676
v 12.055533 -20.648668 11.898676
v -12.055533 20.648668 11.898676
v 12.055533 20.648668 11.898676
v -12.055533 20.648668 -11.898676
v 12.055533 20.648668 -11.898676
v -12.055533 -20.648668 -11.898676
v 12.055533 -20.648668 -11.898676
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.875000 0.000000
vt 0.875000 0.250000
vt 0.125000 0.000000
vt 0.125000 0.250000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
f 1/1/1 2/2/2 4/4/3 3/3/4
f 3/3/5 4/4/6 6/6/7 5/5/8
f 5/5/9 6/6/10 8/8/11 7/7/12
f 7/7/13 8/8/14 2/10/15 1/9/16
f 2/2/17 8/11/18 6/12/19 4/4/20
f 7/13/21 1/1/22 3/3/23 5/14/24

Unfortunately I don’t know enough to say whether there is an error or not.

Thanks,
Fatman_Stoned

The texture coordinates are 2D. For what you’re trying to do, you need 3D texture coordinates (the OBJ format supports this, but I don’t know about Maya or its OBJ export feature).

Okay I managed to create an OBJ file from 3DS MAX which has 3D texture coordinates:

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware

v  -14.5704 -17.9663 20.3455
v  -14.5704 -17.9663 -17.8120
v  20.3459 -17.9663 -17.8120
v  20.3459 -17.9663 20.3455
v  -14.5704 23.6314 20.3455
v  20.3459 23.6314 20.3455
v  20.3459 23.6314 -17.8120
v  -14.5704 23.6314 -17.8120
# 8 vertices

vn 0.0000 -1.0000 -0.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 -0.0000
# 6 vertex normals

vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords

f 1/1/1 2/2/1 3/3/1 4/4/1 
f 5/4/2 6/1/2 7/2/2 8/3/2 
f 1/4/3 4/1/3 6/2/3 5/3/3 
f 4/4/4 3/1/4 7/2/4 6/3/4 
f 3/4/5 2/1/5 8/2/5 7/3/5 
f 2/4/6 1/1/6 5/2/6 8/3/6 
# 6 polygons

This is the result I get now:
[ATTACH=CONFIG]976[/ATTACH]

This is the code I use to create the 3D texture data structure:

GLfloat* createWood()
{
	GLfloat *wood = (GLfloat*) malloc(sizeof(GLfloat) * WIDTH * HEIGHT * DEPTH * 3);
	GLfloat R, G, B;
	double r, alpha, c;
	
	int i, j, k;
	GLfloat *ptr = wood;
    for (i = 1; i < WIDTH+1; i++)
    {
        for (j = 1; j < HEIGHT+1; j++)
        {
			for (k = 1; k < DEPTH+1; k++)
			{
				r = sqrt(i*i + j*j);
				alpha = atan(i / j);
				r += 2 * sin(20*alpha + j/150);
				c = (GLfloat)(((int)(r))%60);
				
				if(c > 40) {			//dark brown: rgb(139,69,19)
					R = 0.54296875f;
					G = 0.26953125f;
					B = 0.07421875f;
				}
				else {					//light brown: rgb(245,222,179)
					R = 0.95703125f;
					G = 0.8671875f;
					B = 0.69921875f;
				}
				
				*ptr = R;		//R
				ptr++;
				*ptr = G;		//G
				ptr++;
				*ptr = B;		//B
				ptr++;
			}
        }
    }
	return wood;
}

Thanks,
Fatman_Stoned

Okay I managed to create an OBJ file from 3DS MAX which has 3D texture coordinates:

Do not mistake a value having three dimensions for being three dimensional. Your “3D” texture coordinates all use zero for the third dimension.

Generally speaking, in order to get true 3D texture coordinates out of a modeling package, you have to apply some kind of 3D texture to it in the tool. I seem to recall that Max had quite a few 3D texture generators, and they might be able to produce real 3D coordinates.

However, if you’re just trying to make something work, I would say to ignore the texture coordinates altogether. Instead, generate your own 3D texture coordinates from the 3D positions of the object. You seem to be using compatibility OpenGL, so this would involve some use of a texture coordinate generation matrix (glTexGen).

The idea is to normalize your positions by computing the minimum and maximum extent of the model in model space. Then build a matrix that transforms model space positions into the [0, 1] range for texture coordinates. And that’s the matrix you pass for the texture coordinate generation process.

I’ve never used glTexGen, but that’s the general idea as far as I understand. Someone else might be able to walk you through the details.

[QUOTE=Alfonse Reinheart;1265437]However, if you’re just trying to make something work, I would say to ignore the texture coordinates altogether. Instead, generate your own 3D texture coordinates from the 3D positions of the object. You seem to be using compatibility OpenGL, so this would involve some use of a texture coordinate generation matrix (glTexGen).

The idea is to normalize your positions by computing the minimum and maximum extent of the model in model space. Then build a matrix that transforms model space positions into the [0, 1] range for texture coordinates. And that’s the matrix you pass for the texture coordinate generation process.

I’ve never used glTexGen, but that’s the general idea as far as I understand. Someone else might be able to walk you through the details.[/QUOTE]

The way that glTexGen() works is that for each component (s,t,r,q) which you wish to generate, you provide 4 coefficients which specify a linear equation in (x,y,z,w), e.g. s=ax+by+cz+dw. In effect, you’re providing one row of a transformation matrix.

Personally, whenever I used glTexGen(), I just mapped vertex coordinates directly to texture coordinates (i.e. the plane coefficients passed to glTexGen() are all unit vectors) and used the texture matrix (glMatrixMode(GL_TEXTURE)) to control the transformation.

But in this case, it might be easier to just generate the texture coordinate array from the vertex coordinate array in software. That makes it easier to switch to using the texture coordinates from the OBJ file if you manage to figure out how to get the correct values from Maya.

Thanks for your answers guys!
I tried to use glTexGen() to make openGL create the texture coordinates on its own.
I now get this:
[ATTACH=CONFIG]981[/ATTACH]
On one face it looks very close to what I would expect… only a little bit twisted.

This is the code I used:

unsigned int texname;
	GLfloat sPlane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
	GLfloat tPlane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
	GLfloat rPlane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
	GLfloat qPlane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
	
	glGenTextures(1, &texname);
	glTexGenfv(GL_S, GL_OBJECT_PLANE, qPlane);
	glTexGenfv(GL_T, GL_OBJECT_PLANE, rPlane);
	glTexGenfv(GL_R, GL_OBJECT_PLANE, tPlane);
	glTexGenfv(GL_Q, GL_OBJECT_PLANE, sPlane);
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glEnable(GL_TEXTURE_GEN_R);
	glEnable(GL_TEXTURE_GEN_Q);
	glBindTexture (GL_TEXTURE_3D, texname);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB32F, WIDTH, HEIGHT, DEPTH, 0, GL_RGB,
				 GL_FLOAT, solidTexture);

To be honest I don’t really understand what I am doing here. Playing around with the planes doesn’t help. The annual rings of the tree should be on the top- and bottom faces.
Could you please tell me how the code has to look like to achieve the tree texture?

Thank you!
Fatman_Stoned

I am starting to believe that the problem is the algorithm:

	GLfloat *wood = (GLfloat*) malloc(sizeof(GLfloat) * WIDTH * HEIGHT * DEPTH * 3);
	GLfloat *ptr = wood;
	GLfloat R, G, B;
	double r, alpha, c;
	
	int i, j, k;
    for (i = 1; i < WIDTH+1; i++)
    {
        for (j = 1; j < HEIGHT+1; j++)
        {
			for (k = 1; k < DEPTH+1; k++)
			{
				r = sqrt(i*i + j*j);
				alpha = atan(i / j);
				r += 2 * sin(20*alpha + j/150);
				c = (GLfloat)(((int)(r))%20);
				
				if(c > 15) {			//dark brown: rgb(139,69,19)
					R = 0.54296875f;
					G = 0.26953125f;
					B = 0.07421875f;
				}
				else {					//light brown: rgb(245,222,179)
					R = 0.95703125f;
					G = 0.8671875f;
					B = 0.69921875f;
				}
				
				*ptr = R;		//R
				ptr++;
				*ptr = G;		//G
				ptr++;
				*ptr = B;		//B
				ptr++;
			}
        }
    }
	return wood;

It seems that it’s only working for one quadrant:
[ATTACH=CONFIG]987[/ATTACH]

Any idea what I am doing wrong?
Thanks!

Fatman_Stoned

[QUOTE=Fatman_Stoned;1265511]I am starting to believe that the problem is the algorithm:
It seems that it’s only working for one quadrant:
[/QUOTE]
The texture generation algorithm is fine (the fact that the atan(i/j) calculation will use integer division means that alpha isn’t quite what you want, but that isn’t the issue here).

The problem is that texture coordinates range from 0…1, but your object coordinates range from -1…1, and you’re using the object coordinates directly without any scale or translation. So the corner of the texture is at the centre of the face.

I suspect that you need


	GLfloat sPlane[] = { 0.5f, 0.0f, 0.0f, 0.5f };
	GLfloat tPlane[] = { 0.0f, 0.5f, 0.0f, 0.5f };
	GLfloat rPlane[] = { 0.0f, 0.0f, 0.5f, 0.5f };

With your code it looks like this:
[ATTACH=CONFIG]988[/ATTACH]

To get this picture:
[ATTACH=CONFIG]145[/ATTACH]
…I used this code:

GLfloat sPlane[4] = { 0.5f, 0.0f, 0.0f, 0.5f };
	GLfloat tPlane[4] = { 0.0f, 0.5f, 0.0f, 0.5f };
	GLfloat rPlane[4] = { 0.0f, 0.0f, 0.5f, 0.5f };

[QUOTE=Fatman_Stoned;1265513]With your code it looks like this:

To get this picture:
…I used this code:
[/QUOTE]
There’s no difference between the two, other than the explicit array size (which doesn’t affect anything). Both scale by 0.5 and translate by 0.5.

Also: ensure that you’re passing the correct planes (an earlier version had them mixed up).

It might help to post the current state of the (relevant) code.

Ooops sorry I postet the wrong code!

So this is the code I am using at the moment:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(	-1, 50, -100,
			0, -20,  90,
			0.0f, 1.0f,  0.0f);
	
	glEnable(GL_TEXTURE_3D);
	PFNGLTEXIMAGE3DPROC glTexImage3D;
	glTexImage3D = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");	
	
	unsigned int texname;
	GLfloat sPlane[4] = { 0.02f, 0.0f, 0.0f, -1.0f };
	GLfloat tPlane[4] = { 0.0f, 0.02f, 0.0f, -1.0f };
	GLfloat rPlane[4] = { 0.0f, 0.0f, 0.02f, -1.0f };
	
	glGenTextures(1, &texname);
	glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane);
	glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane);
	glTexGenfv(GL_R, GL_OBJECT_PLANE, rPlane);
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glEnable(GL_TEXTURE_GEN_R);
	glBindTexture (GL_TEXTURE_3D, texname);
	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);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB32F, WIDTH, HEIGHT, DEPTH, 0, GL_RGB,
				 GL_FLOAT, solidTexture);
	
	glTranslatef(-10.0f,10.0f,-10.0f);
	glRotatef((rotateModel+1)*10,0.0f,1.0f,0.0f);
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	//glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
	glVertexPointer(3, GL_FLOAT, 0, faces);
	glNormalPointer(GL_FLOAT, 0, normals);
	glColorPointer(3, GL_FLOAT, 0, solidTexture);
	//glTexCoordPointer(3, GL_FLOAT, 0, textureCoord);
	glDrawArrays(GL_QUADS, 0, TotalConnectedComponents);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
	//glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
	
	glDisable(GL_TEXTURE_3D);
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	glutSwapBuffers();

and it produces this picture:
[ATTACH=CONFIG]146[/ATTACH]

Switching around the coordinates -1.0f or 1.0f doesnt change a lot… only flips everything to the other side. Sorry I am really dumb about this.
Fatman_Stoned