为什么sampler2D数组采样时始终使用纹理单元0的纹理?
问题原因
- 非动态统一的sampler数组索引属于非法用法
你使用SSBO中每个对象独立的texture字段作为sampler数组的索引,该索引不属于动态统一表达式(即同一次计算调度中,不同着色器线程读取到的索引值可能不同),这种用法不符合OpenGL核心规范要求。只有当索引是编译期常量,或者同一次绘制/调度调用中所有线程的索引值完全一致时,sampler数组的动态索引才是合法的。绝大多数桌面GPU驱动遇到这类非法的非统一索引时,会默认固定返回索引0对应的sampler,这就是你始终获取到背景纹理的核心原因。 - sampler数组未完整初始化
你在着色器中定义的sampler数组长度为8,但仅显式给textures[0]和textures[1]设置了uniform值,剩余6个元素的uniform处于未初始化状态,驱动通常会将未初始化的sampler uniform默认赋值为0,进一步导致采样结果异常。 - 可选排查点:可调用
glGetUniformLocation(rt_shader->get_id(), "textures[1]")检查返回值是否为非-1的有效值,如果返回-1说明该uniform被驱动优化掉了,可先在着色器中写死采样textures[1]的代码验证纹理绑定逻辑本身是否正确,排除绑定侧的问题。
修复方案
- 你的场景适合直接改用
sampler2DArray:将所有纹理上传到同一个纹理数组的不同层,采样时直接用SSBO中的索引作为数组层索引即可,天然支持非统一的索引需求。 - 小bug修复:你当前纹理构造函数中
glTexImage2D的internalformat参数传的是GL_RGBA,但你调用stbi_load时强制读取3通道数据,format参数传的是GL_RGB,通道数不匹配可能导致纹理颜色异常,建议将internalformat改为GL_RGB8和输入数据对齐。
内容的提问来源于stack exchange,提问作者denormal
相关产品推荐
相关产品推荐

