所以,我正在努力理解一维纹理。我尝试将三个浮点值作为 uniform
传递到片段着色器中。它们代表了光的颜色,旨在通过在纹理中存储所有信息(颜色和位置)来重用相同的着色器以处理 n
个灯光。目前,我正在尝试仅传递单个光源的颜色以测试事物。因此,在片段着色器中,我有以下内容:
uniform sampler1D lightColor;
...
vec3 lc = vec3(texelFetch(lightColor, 0, 0)); // all zeroes
vec3 lc = vec3(texture(lightColor, 0, 0)); // same
我曾尝试在着色器中使用texelFetch
和texture
调用(二者之一或两者皆有),但无济于事。请注意,如果我像这样在着色器中硬编码值:
vec3 lc = vec3(0.0f, 0.0f, 0.8f);
然后我得到了期望的结果(即 lc
中的非零值),因此我确信,至少在着色器中,问题可能出现在 texelFetch
或 texture
调用中。
回到 C++ 领域,代码(在我的 lightManager
初始化时执行一次)如下:
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);
这里没有什么非常花哨的东西(虽然肯定是错误的)。在阅读OpenGL文档的6.2表后,对于
glTexStorage1D
,我选择了1作为levels
(没有MipMaps),并选择了GL_RGB32F
作为internalFormat
(因为我正在尝试传递3个浮点数)。由于只有一个值,所以width
为1。这应该处理好了分配。现在,填充缓冲区需要使用
glTexSubImage1D
,我选择level
0(同样没有MipMaps),0作为xoffset
,宽度为GLfloat
大小的三倍,GL_RGB
作为格式,GLfloat
作为type
。最后,是实际数据。关于c++代码的一些事情:我正确地将过滤器设置为
GL_NEAREST
(所以不是它的问题),我会说uniform位置/连接到sader是正确的(通过glUniform1i
和glGetUniformLocation
)。现在来谈我的问题:
- 首先,显而易见,通过纹理传递灯光信息是否合理?着色器明显无法执行像
lights[n]
这样的操作,因为需要在编译时知道n
,所以纹理自然而然地成为一种欺骗的方式。 - 其次,我的假设是否正确,数据大小可能是罪魁祸首?我读到过关于纹理完整性的内容,但说实话,它非常简略。一个像素的大小肯定有问题。
- 第三,您是否发现其他任何问题?特别是与
internalFormat
、format
和type
有关的问题? - 第四,有什么想法可以解释为什么
lc
不断被填充为零吗?
编辑:我不想使用多次传递或定义传递到着色器的灯光数量的硬限制(使
n
恒定)。我读到了一些关于OpenGL 4.2中的某些功能的内容,但我对此不感兴趣。我只是想用手头的工具学习(但可以保证,在弄清楚这个问题后,将来我会回来问这些主题的问题(: )
glGetInteger(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
查询的数字),并且可以调用glActiveTexture(GL_TEXTURE_0 + i)
,其中i在范围0到N内。您使用glGenTextures
生成并使用glBindTexture
绑定的是所谓的纹理名称,在1到2^32-1的范围内可以使用任何名称作为纹理名称。 - datenwolfglActiveTexture(GL_TEXTURE_0 + 喷漆枪编号)
选择喷漆枪,glBindTexture(…, 染料名称)
连接喷嘴,glUniform(sampler_location, 喷漆枪编号)
分配喷漆枪到着色器。 - datenwolfM
支喷漆枪,对于我的照明计算来说需要加1。这个值m
会因为不同的表面而改变,并且最大值应该是N-1
,对吗?换句话说,对于绘制完整的模型(由许多表面组成),可用纹理数量的限制是分别应用于每个表面,而不是整个模型。更进一步地说,渲染我的场景可能需要超过N
支喷漆枪,只要每个单独的表面所需的喷漆枪数不超过N
即可。我说的有什么不对吗?还是我理解得没问题? - Carlos RomeroglDraw…
的函数来识别一个连贯的绘图批次。在这些调用之间,你可以为每个纹理单元更改纹理绑定。- 还有一个扩展(这还不是标准功能,所以不要依赖它),允许在绘图批次中使用任意数量的纹理,而无需绑定它们;该扩展称为“bindless textures”。我只是想引起你的兴趣... - datenwolf