在glTexImage3D和glTexStorage3D之间切换

时间:2017-01-31 13:40:40

标签: c++ opengl

我使用纹理数组来存储纹理图集。对于支持OpenGL 4.2的硬件,我使用glTexStorage3D方法,但我也想使用4.2之前的纹理数组。

我检查了其他一些问题,例如thisthis。我尝试按照那里提供的解决方案,但纹理数组似乎是空的,在渲染过程中没有纹理可见。

我的glTexStorage3D解决方案没有任何问题:

glTexStorage3D(GL_TEXTURE_2D_ARRAY,
                1,
                GL_R8,
                2048, 2048,
                100);

然而,glTexImage3D应该是等价的,但不会显示:

glTexImage3D(GL_TEXTURE_2D_ARRAY,
             0,
             GL_R8,
             2048, 2048, 100,
             0,
             GL_RED,
             GL_UNSIGNED_BYTE,
             0);

使用以下代码段将纹理数据上传到指定的索引(图集宽度和高度均为2048,深度为1):

glBindTexture(GL_TEXTURE_2D_ARRAY, m_arrayTexture);

glTexSubImage3D(GL_TEXTURE_2D_ARRAY,
                0,
                0, 0, m_nextTextureLevel,
                atlas->width, atlas->height, atlas->depth,
                GL_RED,
                GL_UNSIGNED_BYTE,
                atlas->data);

我在这里缺少什么?任何帮助都将受到高度赞赏。

修改
不能立即将纹理数据上传到数组,因为在执行期间可以将新纹理添加到数组中。

编辑v2,解决方案
通常问题是我忽略的一些微不足道的问题。我深入研究了Nazar554的解决方案并尝试将其与我的代码进行比较。问题是我不小心使用错误的常量设置了纹理参数,因此glTexParameteri调用是使用GL_TEXTURE_2D而不是GL_TEXTURE_2D_ARRAY进行的。在改变这些价值之后,一切都像魅力一样。

1 个答案:

答案 0 :(得分:0)

您可以查看我在项目中使用的Texture.cpp

但是我没有在后备情况下使用glTexSubImage()。相反,我立即上传了纹理数据(您传递的是0以预先分配缓冲区)

您可能感兴趣的功能:Texture::loadTexStorageInternal(const std::string& fileName)bool Texture::loadTexInternal(const std::string& fileName)

以下是其中之一,它在glTexStorage3D不可用时处理后备。它很长,因为它试图处理压缩格式/ mipmap。

bool Texture::loadTexInternal(const std::string& fileName)
{
      gli::texture Texture = gli::load(fileName);
      if(Texture.empty())
          return 0;

      const gli::gl GL(gli::gl::PROFILE_GL33);
      const gli::gl::format Format = GL.translate(Texture.format(), Texture.swizzles());
      GLenum Target = static_cast<GLenum>(GL.translate(Texture.target()));

      Binder texBinder(*this, Target);
      glTexParameteri(Target, GL_TEXTURE_BASE_LEVEL, 0);
      glTexParameteri(Target, GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(Texture.levels() - 1));
      glTexParameteri(Target, GL_TEXTURE_SWIZZLE_R, Format.Swizzles[0]);
      glTexParameteri(Target, GL_TEXTURE_SWIZZLE_G, Format.Swizzles[1]);
      glTexParameteri(Target, GL_TEXTURE_SWIZZLE_B, Format.Swizzles[2]);
      glTexParameteri(Target, GL_TEXTURE_SWIZZLE_A, Format.Swizzles[3]);
      if(Texture.levels() >= 1)
          glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
      else
          glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameteri(Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      glTexParameteri(Target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

      //glm::tvec3<GLsizei> const Extent(Texture.extent());

      for(std::size_t Layer = 0; Layer < Texture.layers(); ++Layer)
      for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
      for(std::size_t Face = 0; Face < Texture.faces(); ++Face)
      {
          GLsizei const LayerGL = static_cast<GLsizei>(Layer);
          glm::tvec3<GLsizei> loopExtent(Texture.extent(Level));
          Target = gli::is_target_cube(Texture.target())
              ? static_cast<GLenum>(static_cast<GLint>(GL_TEXTURE_CUBE_MAP_POSITIVE_X) + static_cast<GLint>(Face))
              : Target;

          switch(Texture.target())
          {
          case gli::TARGET_1D:
              if(gli::is_compressed(Texture.format()))
                  glCompressedTexImage1D(
                      Target,
                      static_cast<GLint>(Level),
                      static_cast<GLenum>(static_cast<GLenum>(Format.Internal)),
                      0, loopExtent.x,
                      static_cast<GLsizei>(Texture.size(Level)),
                      Texture.data(Layer, Face, Level));
              else
                  glTexImage1D(
                      Target, static_cast<GLint>(Level),
                      static_cast<GLenum>(Format.Internal),
                      loopExtent.x,
                      0,
                      static_cast<GLenum>(Format.External), static_cast<GLenum>(Format.Type),
                      Texture.data(Layer, Face, Level));
              break;
          case gli::TARGET_1D_ARRAY:
          case gli::TARGET_2D:
          case gli::TARGET_CUBE:
              if(gli::is_compressed(Texture.format()))
                  glCompressedTexImage2D(
                      Target, static_cast<GLint>(Level),
                      static_cast<GLenum>(Format.Internal),
                      loopExtent.x,
                      Texture.target() == gli::TARGET_1D_ARRAY ? LayerGL : loopExtent.y,
                      0,
                      static_cast<GLsizei>(Texture.size(Level)),
                      Texture.data(Layer, Face, Level));
              else
                  glTexImage2D(
                      Target, static_cast<GLint>(Level),
                      static_cast<GLenum>(Format.Internal),
                      loopExtent.x,
                      Texture.target() == gli::TARGET_1D_ARRAY ? LayerGL : loopExtent.y,
                      0,
                      static_cast<GLenum>(Format.External), static_cast<GLenum>(Format.Type),
                      Texture.data(Layer, Face, Level));
              break;
          case gli::TARGET_2D_ARRAY:
          case gli::TARGET_3D:
          case gli::TARGET_CUBE_ARRAY:
              if(gli::is_compressed(Texture.format()))
                  glCompressedTexImage3D(
                      Target, static_cast<GLint>(Level),
                      static_cast<GLenum>(Format.Internal),
                      loopExtent.x, loopExtent.y,
                      Texture.target() == gli::TARGET_3D ? loopExtent.z : LayerGL,
                      0,
                      static_cast<GLsizei>(Texture.size(Level)),
                      Texture.data(Layer, Face, Level));
              else
                  glTexImage3D(
                      Target, static_cast<GLint>(Level),
                      static_cast<GLenum>(Format.Internal),
                      loopExtent.x, loopExtent.y,
                      Texture.target() == gli::TARGET_3D ? loopExtent.z : LayerGL,
                      0,
                      static_cast<GLenum>(Format.External), static_cast<GLenum>(Format.Type),
                      Texture.data(Layer, Face, Level));
              break;
          default:
              return false;
          }
      }
      return true;
}