OpenGL数组纹理根本无法渲染

时间:2016-03-23 01:14:28

标签: opengl textures lwjgl

我目前正在努力将项目从使用纹理图集转换为数组纹理,但对于我的生活,我无法让它工作。

关于我的环境的一些注意事项:

  • 我正在使用OpenGL 3.3核心上下文与GLSL版本3.30
  • 纹理都是128x128,使用地图集时渲染得非常精细(除了让我切换的边缘工件)

我相信我已经排除了问题:

  • 分辨率问题 - 128x128,是2的幂,应该没问题
  • 纹理加载(它像以前一样完美地工作)
  • 不完整的纹理(mipmap问题) - 我已经解决了有关mipmap的常见问题,我不相信OpenGL应该期待它们

这是我创建数组纹理的代码:

public void createTextureArray() {
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    int handle = glGenTextures();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D_ARRAY, handle);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, Texture.SIZE);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, Texture.SIZE, Texture.SIZE, textures.size());

    try {
        int layer = 0;
        for (Texture tex : textures.values()) {
            // Next few lines are just for loading the texture. They've been ruled out as the issue.
            PNGDecoder decoder = new PNGDecoder(ImageHelper.asInputStream(tex.getImage()));
            ByteBuffer buffer = BufferUtils.createByteBuffer(decoder.getWidth() * decoder.getHeight() * 4);
            decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
            buffer.flip();

            glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, decoder.getWidth(), decoder.getHeight(), 1,
                    GL_RGBA, GL_UNSIGNED_BYTE, buffer);

            tex.setLayer(layer);

            layer++;
        }
    } catch (IOException ex) {
        ex.printStackTrace();
        System.err.println("Failed to create/load texture array");
        System.exit(-1);
    }
}

创建VAO / VBO的代码:

private static int prepareVbo(int handle, FloatBuffer vbo) {
    IntBuffer vaoHandle = BufferUtils.createIntBuffer(1);
    glGenVertexArrays(vaoHandle);
    glBindVertexArray(vaoHandle.get());
    glBindBuffer(GL_ARRAY_BUFFER, handle);

    glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D_ARRAY, GraphicsMain.TEXTURE_REGISTRY.atlasHandle);

    glEnableVertexAttribArray(positionAttrIndex);
    glEnableVertexAttribArray(texCoordAttrIndex);

    glVertexAttribPointer(positionAttrIndex, 3, GL_FLOAT, false, 24, 0);
    glVertexAttribPointer(texCoordAttrIndex, 3, GL_FLOAT, false, 24, 12);

    glBindVertexArray(0);

    vaoHandle.rewind();
    return vaoHandle.get();
}

片段着色器:

#version 330 core

uniform sampler2DArray texArray;

varying vec3 texCoord;

void main() {
    gl_FragColor = texture(texArray, texCoord);
}

texCoord工作正常;它正在从顶点着色器正确传递。)

我是出于想法,所以对现代OpenGL来说还是有点新鲜,我想知道我的代码是否有任何明显的错误。

1 个答案:

答案 0 :(得分:1)

一些注意事项:

  • 你不再需要两种纹理的力量
  • 确保每个图层的级别/ mipmaps数量与wiki says
  • 相同
  • 前四个glTexParameteri会影响当时GL_TEXTURE_2D_ARRAY 绑定的内容,因此您最好在glBindTexture
  • 之后移动它们
  • 如何使用glGenTextures()指定要创建的纹理数量?如果您有可能采用更具体的方法,请使用它
  • GL_UNPACK_ROW_LENGTH如果大于0,则定义一行中的像素数。我想那时Texture.SIZE不是真正的纹理大小,而是一侧的尺寸(在你的情况下为128)。无论如何你不需要设置它,你可以跳过它
  • 仅当您的行长度是其倍数时才将GL_UNPACK_ALIGNMENT设置为4。大多数时候人们在加载纹理之前将其设置为1以避免任何麻烦,然后在完成后将其设置为4
  • glTexStorage3D的最后一个参数预计是层数,我希望textures.size()更好地返回而不是大小(128x128)
  • glActiveTextureglBindTexture内的prepareVbo无用,它们不属于vao
  • 请勿在glsl中使用varying,不推荐使用,请切换为简单的in out
  • 您可能希望从this sample
  • 中获取灵感
  • 使用采样器,它们为您提供更大的灵活性
  • 如果可用则使用Debug Output,否则glGetError(),渲染输出可能无法明确看到某些无提示错误
  • 你称之为prepareVbo,但你确实在其中初始化了vao和vbo