Problems Texture Mapping with Float Texture

I am trying to use a float texture as a 1D lookup table. I had originally put my data in a 2D texture, but I did not get the results I thought I should, so instead of trying to determine if my 1D-to-2D conversion was messed up or the texture data was messed up I decided to back off and do a simple test with a 1D texture. That gave me the same results. So now, I am just trying to texture map a floating point texture to a quad. I see the same thing as when trying to do a 1D LUT. Every texel I retrieve from the texture is rgb = (0.0,0.0,0.0). I am using imdebug to look at the texture data before I stuff into the texture object, and it looks fine, but it doesn’t look like the data is in the texture or something.

In my current test app, I modified a texture mapping sample I found online. I modified it to create two different textures at runtime, rather than loading an image file. The float texture is created like this:


int texTarget			= GL_TEXTURE_2D;
int texInternalFormat	= GL_FLOAT_RGBA32_NV;
int texFormat			= GL_RGBA;

glGenTextures( 1, &g_FloatTextureID );
glBindTexture( texTarget, g_FloatTextureID );

int textureWidth   = 256;
int textureHeight  = 256;
int textureSize    = textureWidth * textureHeight;
int textureMemSize = textureWidth * textureHeight * 4 * format2components(texInternalFormat);

GLfloat *rgbaTextureData = new GLfloat[textureMemSize];

int index = 0;
int nRow  = 0;
int nCol  = 0;

unsigned long int nIndex = 0;
unsigned long int nTexelIndex = 0;

for(int nRow = 0; nRow < textureHeight; nRow++) {
	for(int nCol = 0; nCol < textureWidth; nCol++) {

		nIndex = textureWidth * nRow + nCol;
		nTexelIndex = 4*nIndex;

		rgbaTextureData[nTexelIndex + 0] = 2550.0;	
		rgbaTextureData[nTexelIndex + 1] = 2550.0;	
		rgbaTextureData[nTexelIndex + 2] = 2550.0;	
		rgbaTextureData[nTexelIndex + 3] = 2550.0;	
	}
}

glTexImage2D(texTarget, 
	 0, 
	 texInternalFormat,
	 textureWidth, 
	 textureHeight,
	 0, 
	 texFormat, 
	 GL_FLOAT, 
	 rgbaTextureData);

glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);

delete [] rgbaTextureData;
rgbaTextureData = 0;


I set my texture locations like this:


glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, g_FloatTextureID );
if( g_FloatTexture_Location != -1 )
   glUniform1i(g_FloatTexture_Location, 1); 

And my frag shader looks like this:


uniform sampler2D floatTexture;

void main( void )
{   
   // When not comment out... this doesn't
   gl_FragColor = texture2D( floatTexture, gl_TexCoord[0].xy );
}

I don’t see what I am doing wrong… Any suggestions?

CB

You shouldn’t need glEnable(GL_TEXTURE_2D) if you do the texturing in a shader. More important for the problem you describe, make sure you use the same Texture Unit (w/ glActiveTexture) both when initializing the parameters (such as filters/wrap mode) and when binding the texture to the TU. As far as I can see from the code you post, you set several paramters on the default TU (GL_TEXTURE0). The default filter is to use mipmaps and since you’re not supplying it yourself, or requesting a mipmap chain to be computed, the texture is possibly not complete.

so when I create the float texture, I need to make a call to glActiveTexture before I bind the texture and set the texture parameters? For example…


int texTarget			= GL_TEXTURE_2D;
int texInternalFormat	= GL_FLOAT_RGBA32_NV;
int texFormat			= GL_RGBA;

glEnable(GL_TEXTURE_RECTANGLE_ARB);
glActiveTexture(GL_TEXTURE1);

glGenTextures( 1, &g_FloatTextureID );
glBindTexture( texTarget, g_FloatTextureID );

int textureWidth   = 256;
int textureHeight  = 256;
int textureSize    = textureWidth * textureHeight;
int textureMemSize = textureWidth * textureHeight * 4 * format2components(texInternalFormat);

GLfloat *rgbaTextureData = new GLfloat[textureMemSize];

int index = 0;
int nRow  = 0;
int nCol  = 0;

unsigned long int nIndex = 0;
unsigned long int nTexelIndex = 0;

for(int nRow = 0; nRow < textureHeight; nRow++) {
	for(int nCol = 0; nCol < textureWidth; nCol++) {

		nIndex = textureWidth * nRow + nCol;
		nTexelIndex = 4*nIndex;

		rgbaTextureData[nTexelIndex + 0] = 2550.0;	
		rgbaTextureData[nTexelIndex + 1] = 2550.0;	
		rgbaTextureData[nTexelIndex + 2] = 2550.0;	
		rgbaTextureData[nTexelIndex + 3] = 2550.0;	
	}
}

glTexImage2D(texTarget, 
	 0, 
	 texInternalFormat,
	 textureWidth, 
	 textureHeight,
	 0, 
	 texFormat, 
	 GL_FLOAT, 
	 rgbaTextureData);

glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);

delete [] rgbaTextureData;
rgbaTextureData = 0;

When I do this, my app crashes on the glActiveTexture call giving the following msg: :Unhandled exception at 0x00000000 in testapp.exe: 0xC0000005: Access violation reading location 0x00000000."

That function call should not under any circumstances crash your application. Your problem lies somewhere else. When do you initialize your texture? A constructor? Before the context is created perhaps?

I suggest you post more source code :slight_smile:

so when I create the float texture, I need to make a call to glActiveTexture before I bind the texture and set the texture parameters?

No, texture object creation does not depend on the selected texture unit. You 1st create and initialize your texture object, then choose which texture unit will be affected by next texture state changes calling glActiveTexture; finally you bind the texture object to the selected texture unit.

Is it normal that you bind a texture to texture unit 1 and read texture coordinates from texture unit 0 in fragment shader?

Crashes at glActiveTexture?
Smells like null pointer…Check if you initialize your glActiveTexture correctly.

That’s what it was… I am using glew and wasn’t calling glewintit until after I called glActiveTexture the first time… doh!

Ok… I still can’t see what is wrong here… would anyone be willing to run this code and see what might be wrong? I know that is a lot to ask, but I am out of ideas…
Thanks,
CB

I placed the code in zip file here:

http://www.celticblues.com/code/glslTextureMapping.zip

If it would work on Linux, yes.

I second that! :slight_smile:

Heard ya…

here it is modified to run on linux…

http://celticblues.com/code/glslTextureMapping.tar.gz

CB

I must admit, that I only gave it a quick look.
You are using rect textures and I cannot find a place where you adjust the texture coordinates accordingly. Remember, rect textures don’t work with normalized coordinates.
And I don’t see the reason why you use them, as your float texture is 256x256.
The code is a little bit confusing, perhaps you could get rid of the unnecessary parts (for example the other two textures, the commented parts etc.) and just give use the bare bones.
I know I am a lazy a**, but hey, I don’t have troubles with float textures. :wink:

I’ll clean it up… One reason I am using the rect textures is that I will have to in the future… but for now… maybe I should just go back to 2D…

Why?
On most modern cards NPOT textures are supported.

So rect texture is not required for npot textures?

CD

Here is a cleaned up, pared down version of the code… rather than putting all the code at the prior link again, I am just submitting the main file…

CD


//-----------------------------------------------------------------------------
//	This code is based on an example from http://www.codesampler.com
//  Original author information follows:
//
//           Name: ogl_glslang_simple_vs2ps.cpp
//         Author: Kevin Harris
//  Last Modified: 04/21/05
//
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
//#include <string.h>

#include <GL/glew.h>
#include <GL/glut.h>
#include "textfile.h"

GLuint g_VertexShader	= 0;
GLuint g_FragmentShader = 0;
GLuint g_ShaderProgram	= 0;

GLuint g_TextureID;
GLint  g_TextureWidth  = 256;
GLint  g_TextureHeight = 256;
GLint  g_TextureLocation = -1;

// GL_T2F_C3F_V3F
struct Vertex
{
	float tu, tv;
	float r, g, b;
	float x, y, z;
};

Vertex g_QuadVertices[] =
{
	// tu,  tv     r    g    b       x     y     z 
	{ 0.0f,0.0f,  1.0f,1.0f,0.0f, -1.0f,-1.0f, 0.0f },
	{ 1.0f,0.0f,  1.0f,0.0f,0.0f,  1.0f,-1.0f, 0.0f },
	{ 1.0f,1.0f,  0.0f,1.0f,0.0f,  1.0f, 1.0f, 0.0f },
	{ 0.0f,1.0f,  0.0f,0.0f,1.0f, -1.0f, 1.0f, 0.0f },
};

////////////////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////////////////
void changeSize(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;

	float 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);
}

////////////////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////////////////
void renderTexturedQuad(void) 
{
	// Clear the screen and the depth buffer
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	glTranslatef( 0.0f, 0.0f, -4.0f );

        glUseProgramObjectARB( g_ShaderProgram );

			// eventually I need to use multiple textures.... 

			glEnable(GL_TEXTURE_RECTANGLE_ARB);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_TextureID );

			if( g_TextureLocation != -1 ){
				glUniform1i(g_TextureLocation, 	
							0);
			}

			glInterleavedArrays( GL_T2F_C3F_V3F, 0, g_QuadVertices );
			glDrawArrays( GL_QUADS, 0, 4 );

		glUseProgramObjectARB( 0 );

	glutSwapBuffers();
}

////////////////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////////////////
void processNormalKeys(unsigned char key, int x, int y) 
{

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


////////////////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////////////////
void initializeShaders() 
{
	char *vertexShader		= NULL;
	char *fragmentShader1	= NULL;

	g_VertexShader		= glCreateShader(GL_VERTEX_SHADER);
	g_FragmentShader	= glCreateShader(GL_FRAGMENT_SHADER);

	vertexShader	= textFileRead("vertex_shader.vert");
	fragmentShader1 = textFileRead("fragment_shader.frag");

	const char * ff = fragmentShader1;
	const char * vv = vertexShader;

	glShaderSource(g_VertexShader,    1, &vv,  NULL);
	glShaderSource(g_FragmentShader, 1, &ff,  NULL);

	free(vertexShader);
	free(fragmentShader1);

	glCompileShader(g_VertexShader);
	glCompileShader(g_FragmentShader);

	g_ShaderProgram = glCreateProgram();
	glAttachShader(g_ShaderProgram, g_FragmentShader);
	glAttachShader(g_ShaderProgram, g_VertexShader);

	glLinkProgram(g_ShaderProgram);

	glUseProgram(g_ShaderProgram);

	g_TextureLocation	= glGetUniformLocationARB( g_ShaderProgram, "floatTexture" );
}

////////////////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////////////////
int initializeTextures()
{
	int ret = -1;

	// mem size = width * height * # components per texel
	int textureMemSize = g_TextureWidth * g_TextureHeight * 4;

	// Create Texture Data
	GLfloat *rgbaFloatTextureData = new GLfloat[textureMemSize];

	unsigned long int nIndex = 0;
	unsigned long int nTexelIndex = 0;
	
	for(int nRow = 0; nRow < g_TextureHeight; nRow++) {
		for(int nCol = 0; nCol < g_TextureWidth; nCol++) {

			nIndex = g_TextureWidth * nRow + nCol;
			nTexelIndex = 4*nIndex;

			GLdouble texVal = static_cast<GLfloat>(nRow/256.0); 
#if 1
			// ...this doesn't work
			rgbaFloatTextureData[nTexelIndex + 0] = texVal;
			rgbaFloatTextureData[nTexelIndex + 1] = texVal;
			rgbaFloatTextureData[nTexelIndex + 2] = texVal;
			rgbaFloatTextureData[nTexelIndex + 3] = 1.0;
#else
			// ...but this seems to work
			rgbaFloatTextureData[nTexelIndex + 0] = 0.3;
			rgbaFloatTextureData[nTexelIndex + 1] = 0.6;
			rgbaFloatTextureData[nTexelIndex + 2] = 0.9;
			rgbaFloatTextureData[nTexelIndex + 3] = 1.0;
#endif
		}
	}

	glEnable(GL_TEXTURE_RECTANGLE_ARB);

	glGenTextures(1, &g_TextureID);

	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g_TextureID);

	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 
				 0, 
				 GL_FLOAT_RGBA32_NV, 
				 g_TextureWidth,
				 g_TextureHeight,
				 0, 
				 GL_RGBA, 
				 GL_FLOAT, 
				 rgbaFloatTextureData);

	delete [] rgbaFloatTextureData;
	rgbaFloatTextureData = 0;

	return ret;
}

////////////////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) 
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(320,320);
	glutCreateWindow("GLSL Texture Mapping");

	glutDisplayFunc(renderTexturedQuad);
	glutIdleFunc(renderTexturedQuad);
	glutReshapeFunc(changeSize);

	glutKeyboardFunc(processNormalKeys);

	glDisable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
	glClearColor(0.0, 0.0, 0.0, 0.0);
	
	glewInit();
	if (glewIsSupported("GL_VERSION_2_0"))
		printf("
Ready for OpenGL 2.0
");
	else {
		printf("
OpenGL 2.0 not supported
");
		exit(1);
	}
	const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
	fprintf(stdout, "
GLSL Version: %s
", glslVersion);


	initializeTextures();

	initializeShaders();

	glutMainLoop();

	return 0;
}



No, see: http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_non_power_of_two.txt

Regarding your problem:
Do you wan’t to annoy me? Do you do it on purpose?
Reread post #251800 and your problem is solved. Just tested your ‘new’ code and it works as it should.

uh…you might want to make your code more consistent. Why do you use glUseProgramObjectARB and glUseProgram at the same time?

The story of NPOT and rect textures is here
http://www.opengl.org/wiki/NPOT_Textures

#251800 didn’t solve my problem. My code doesn’t work for me as it should or I wouldn’t have continued to ask questions… No I don’t wan’t [sic] to annoy you… at least I didn’t until now. People come here for help not to be spoken to in a condescending manner. If you don’t want to help, then don’t… but don’t be a jerk.

CD

No, see: http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_non_power_of_two.txt

Regarding your problem:
Do you wan’t to annoy me? Do you do it on purpose?
Reread post #251800 and your problem is solved. Just tested your ‘new’ code and it works as it should.
[/QUOTE]

FLAMEWAR!!!
No, just joking. :wink:

Your texture coordinates are wrong! Correct them!
V-mans link will tell you how.

You have much to learn, my young Padawan.