如何将多个立方体纹理传递到一个统一的采样器数组中?

Posted

技术标签:

【中文标题】如何将多个立方体纹理传递到一个统一的采样器数组中?【英文标题】:How to pass multiple cube textures into a uniform array of samplers? 【发布时间】:2018-02-18 02:42:36 【问题描述】:

假设我在着色器中有一个制服,声明为:

uniform samplerCube depth_maps[];

我在 cpp 端有一个纹理 ID 数组,声明为:

vector<GLuint> depth_maps;

这是通过绘制到一个帧缓冲区附加纹理创建的。

对于单个纹理,将信息传递到数组中的代码或多或少类似于:

    glUseProgram(program);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

    GLint loc = glGetUniformLocation(program, "depth_maps");
    if(loc == GL_INVALID_VALUE || loc==GL_INVALID_OPERATION)
    
        cerr << "Error returned when trying to find depth_map uniform."
            << "\nuniform: text"
            << "Error num: " << loc
            << endl;
        return;
    

    glUniform1i(loc,1);

这里GL_TEXTURE1表示这个纹理将被附加到纹理单元1(假设已经有一个纹理附加到GL_TEXTURE0)。

问题 n1 只有 2 个有保证的纹理单元,之后的任何一个都取决于实现。

问题 n2,即使我有很多,我也只知道如何单独和独立地传递它们(即对我想要传递的每个纹理重复上述代码并为每个纹理定义一个新的制服)

如何将 thsi 数据作为连续的统一数组传递?

【问题讨论】:

"问题 n1 只有 2 个保证的纹理单元,之后的任何一个都取决于实现。" 不正确。 FS 的纹理图像单元的数量,即使在 GL 3.3 中,也至少是 16 个。您正在查看兼容性的东西。 【参考方案1】:

假设我在着色器中有一件制服,声明为:

uniform samplerCube depth_maps[];

那将是一个编译错误。除了一个例外,GLSL 中的数组必须(最终)声明为具有编译时确定的大小。

但是假设您已经给这个数组一个大小(并且您确保使包含纹理图像单元的vector 大小相同)。在统一数组上设置纹理图像单元的工作方式与在统一数组上设置 any 值的方式完全相同。

您可以单独执行此操作,对每个数组元素使用不同的 glUniform1i 命令。

for(std::size_t i = 0; i < depth_maps.size(); ++i)

  std::ostringstream os;
  os << "depth_maps[" << i << "]";
  std::string name = std::move(os).str();
  GLint loc = glGetUniformLocation(program, name.c_str());
  glUniform1i(loc, depth_maps[i]);

或者你可以一次设置它们。

GLint loc = glGetUniformLocation(program, "depth_maps");
glUniform1iv(loc, depth_maps.size(), depth_maps.data());

【讨论】:

以上是关于如何将多个立方体纹理传递到一个统一的采样器数组中?的主要内容,如果未能解决你的问题,请参考以下文章

尝试对立方体贴图纹理进行采样时出现 GL_INVALID_OPERATION

在OpenGL中使用统一参数(使用glm)

OpenGL/C++:将多个纹理传递给一个着色器的问题

OpenGL+OpenCV实现立方体贴图

使用单个 FBO 将单个场景从多个视点绘制到多个纹理中(每个视点 1 个)仅产生一个有效纹理

使用纹理数组时,为啥我不必将采样器绑定到着色器?