Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

opengl 1D texture: fill with arbitrary float values

So, I'm struggling with 1D textures. What I'm trying to achieve is passing 3 float values to a fragment shader as a uniform. They represent a light's color, in an attempt to reuse the same shader for n lights, with all their info -color and position- stored in the texture. For now, I'm trying to pass only the color for a single light to test things out. So in the fragment shader I have this:

uniform sampler1D lightColor;
...
vec3 lc = vec3(texelFetch(lightColor, 0, 0)); // all zeroes
vec3 lc = vec3(texture(lightColor, 0, 0));    // same

I've tried to achieve it both with texelFetch and texture calls within the shader (either one or the other), in both cases to no avail. Please note that if I hardcode the value in the shader like this:

vec3 lc = vec3(0.0f, 0.0f, 0.8f);

then I get the expected results (which are non-zero values in lc), so I'm positive that, at least in the shader, the problem may be in either the texelFetch or texture calls.

Back in C++ land, the code (executed once when my lightManager initializes) is as follows:

GLfloat lightValues[] = { 0.8f, 0.8f, 0.8f };
GLuint lightID; // member, not a local variable.
glGenTextures(1, &lightID);
glBindTexture(GL_TEXTURE_1D, lightID);
glActiveTexture(GL_TEXTURE0 + lightID);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexStorage1D(GL_TEXTURE_1D, 1, GL_RGB32F, 1);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 3 * sizeof(GLfloat), GL_RGB, GL_FLOAT, lightValues);
glUniform1i(glGetUniformLocation(shader->program, "light"), lightID);

Nothing extremely fancy going here (although definitely wrong). After going through table 6.2 of the OpenGL doc, for glTexStorage1D I chose 1 for levels (no MipMaps) and GL_RGB32F for internalFormat (since I'm trying to pass 3 floats). width is 1, since there is a single value. That should take care of the allocation.

Now, on to filling the buffers up with glTexSubImage1D, for which I choose level 0 (again, no MipMaps), 0 for xoffset, for width thrice the size of a GLfloat, GL_RGB as the format and GLfloat as the type. Finally, the actual data.

A few things about the c++ code: I correctly set the filters to GL_NEAREST (so that's not to blame) and I would say the uniform location/connection to the sader is correct (via glUniform1i and glGetUniformLocation).

So here come my questions:

  • First and obvious, does this make sense, passing lights info via a texture? Shaders are blatantly unable to do stuff like lights[n], since n needs to be known at compile time, so textures came naturally to mind as a way to trick this.
  • Second, is my assumption correct that the size of the data may be the culprit? I've read about completeness in textures, but to be honest, it was rather brief. A size of 1 texel smells definitely fishy, though.
  • Third, do you see anything else wrong? Particularly with the internalFormat, format and type?
  • Fourth, any ideas in general why lc keeps being populated with zeroes?

Thanks!!

EDIT: I do not want to use techniques like multiple passing, or defining a hard limit on the number of lights passed to the shader (making n constant). I read too about some feature in OpenGL 4.2, I believe, which does not interest me either. I'm just trying to learn with the tools at hand (but it's 100% guaranteed in the future I will come back with questions about those topics, once I figure this out (: )

like image 512
Carlos Romero Avatar asked May 27 '26 06:05

Carlos Romero


1 Answers

Okay, figured it out together with https://stackoverflow.com/users/1774414/raistmaj

Turns out width is both in glTexStorage and glTexSubImage the number of elements in the array, so 1, regardless of the number of components.

Also, glActiveTexture must be called before glBindTexture (duh!!)

like image 131
Carlos Romero Avatar answered Jun 01 '26 07:06

Carlos Romero