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]
, sincen
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
andtype
? - 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 (: )