Loading and reading a floating point texture

Hi all.

I am currently using a lookup table to make some integral go faster in my application. To do this I load up a .csv file containing floating point values and then attempt to create a floating point texture using that like so.


int numCSVs = 0;
float* texData = harvesterPtr->loadCSV("tableF.csv", numCSVs);
int texDim = sqrt(float(numCSVs));

glGenTextures(1, &textureF);
glBindTexture(GL_TEXTURE_2D, textureF);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, texDim, texDim, 0, GL_RED, GL_FLOAT, texData);

The CSV contains a block of 512 * 512 values and on inspection “texData” contains the right values in a single array sized 262144. Moreover, texDim evaluates to 512 as expected.

In my shader this texture is declared as:

uniform sampler2D textureF;

and to set it in my application I use


glUseProgram(direct);
glUniform1i(glGetUniformLocation(direct, "textureF"), 4);

during the draw loop I have


glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, textureF);

When I simply output texture vals using


radiance.rgb = vec3(texture(textureF, texCoords).s, texture(textureF, texCoords).s, texture(textureF, texCoords).s);

While drawing a full screen quad, it seems to just read 0 values. Other textures are displayed just fine.

Am I forgetting something glaringly obvious? The csv table values aren’t clamped to 0 to 1, would this have something to do with it?

Help would be greatly appreciated

Try this add this


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

after you bind your texture but befre u call glTexImage2D
and output in shader like this


float red = texture(textureF,texCoords).r;
radiance.rgb = vec3(red);

Thank you!

It was the filter!

Why does a filter need to be set? I had always assumed the default filter was GL_NEAREST and that not setting a filter assumed that.

I have set up textures in the past (the ones attached to my FBO) with no filter without any trouble. The only difference between those and the one mentioned here is the pointer to the data in the FBO textures is always NULL.

Why does openGL mandate setting a filter when the data pointer is not NULL?

Once again thank you for your help mobeen.

Well the filtering is implementation dependent read this . You cannot be sure whether the default texture filter will be linear or nearest. Therefore, it’s always better to explicitly give it.

radiance.rgb = vec3(texture(textureF, texCoords).s, texture(textureF, texCoords).s, texture(textureF, texCoords).s);

Don’t do this. Every time you call “texture(textureF, texCoords),” you’re accessing the texture. There’s no need to do it 3 times just to get one value.

All you need to do is this:

radiance.rgb = texture(textureF, texCoords).rrr

You really should read the GLSL specification to see how the language works. It has many vector features which are not commonly available in C/C++, but are crucial for good performance in GLSL.

Why does openGL mandate setting a filter when the data pointer is not NULL?

It doesn’t. You need to set the filtering parameters in order to get the filtering that you want rather than the default.

Well the filtering is implementation dependent read this .

No it’s not. That spec is for an extension, one that isn’t widely implemented. Except for the specific nature of how anisotropic filtering is done, the procedure for filtering is very clearly spelled out by the specification.

You cannot be sure whether the default texture filter will be linear or nearest.

Um, yes you can. The spec is quite clear on this. The default mag filtering is GL_LINEAR, and the default min filtering is (for some reason) GL_NEAREST_MIPMAP_LINEAR (except for textures that can’t have mipmaps, in which case it is GL_LINEAR).

Thanks for the correction Alfonse but if the default min filter is linear, why it doesnt work if he does not specify?

The default min filter is GL_NEAREST_MIPMAP_LINEAR, so by default you have to provide texture mipmaps, otherwise, texture is invalid.

COOL. Thanks ZBUFFER.

Don’t do this. Every time you call “texture(textureF, texCoords),” you’re accessing the texture. There’s no need to do it 3 times just to get one value.

All you need to do is this:

Thanks for the .rrr tip and also the initializer tip from mobeen. I know that texture reads are slow. See I usually store texture lookups in a temp variable, but this was just debugging “lets output this as a color to see whats going on” code. That texture is a lookup texture for the airlight model so obviously I’d never attempt to display it otherwise.

The default mag filtering is GL_LINEAR, and the default min filtering is (for some reason) GL_NEAREST_MIPMAP_LINEAR (except for textures that can’t have mipmaps, in which case it is GL_LINEAR).

The default min filter is GL_NEAREST_MIPMAP_LINEAR, so by default you have to provide texture mipmaps, otherwise, texture is invalid.

Thats weird. I set up my frame buffer attachment textures like so:

glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, wWidth, wHeight, 0, GL_RGB, GL_FLOAT, NULL);

glBindTexture(GL_TEXTURE_2D, gAlbedo);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wWidth, wHeight, 0, GL_RGBA, GL_FLOAT, NULL);

glBindTexture(GL_TEXTURE_2D, gMaterial);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wWidth, wHeight, 0, GL_RGBA, GL_FLOAT, NULL);

With no calls to change the tex paramaters away from the default and no call to genMipmaps, an they work fine. Yet any texture that does not take a null data pointer requires me to do either of the two.

hello
can you please share your scv file
thanks