【问题标题】:OpenGL Texture Renders black eventhough its data is not null [duplicate]OpenGL纹理呈现黑色,即使它的数据不为空[重复]
【发布时间】:2020-09-12 21:30:17
【问题描述】:

我已经在 LWJGL OpenGL 中编写了一个可以使用颜色的 2D Batch Renderer。当我为其添加纹理支持时,Quad Rendered 始终为黑色。 STBImage 可以很好地读取数据。但它仍然呈现黑色。 这是着色器: 顶点: 片段:

#version 450 core

in vec4 v_Colour;
in vec2 v_TexCoord;
in float v_TexIndex;

uniform sampler2D u_TextureSlots[16];

void main() {
    int index = int(v_TexIndex);
    gl_FragColor = texture(u_TextureSlots[index], v_TexCoord) * v_Colour;
}

渲染器的提交方法

public static void Submit(Texture texture, Rect drawRect, Rect uvRect, Vector4f colour) {
    if (hasRoom) {
        texture.BindSlot(textureIndex + 1);
        int index = spriteCount++;
        int offset = index * 6 * VERTEX_COUNT;
        StoreData(offset, textureIndex++, drawRect, uvRect, colour);
        if (textureIndex >= 16) hasRoom = false;
        if (spriteCount >= maxBatchSize) hasRoom = false;
    }
}
private static void StoreData(int offset, int textureIndex, Rect drawRect, Rect uvRect, Vector4f colour) {
    float x1 = drawRect.x;
    float y1 = drawRect.y;
    float x2 = drawRect.x + drawRect.width;
    float y2 = drawRect.y + drawRect.height;
    float u1 = uvRect.x;
    float v1 = uvRect.y;
    float u2 = uvRect.x + uvRect.width;
    float v2 = uvRect.y + uvRect.height;
    for (int vertex = 0; vertex < 6; vertex++) {
        int currentIndex = offset + vertex * VERTEX_COUNT;
        float x = vertex == 0 || vertex == 3 || vertex == 5 ? x1 : x2;
        float y = vertex == 0 || vertex == 3 || vertex == 1 ? y1 : y2;
        float u = x == x1 ? u1 : u2;
        float v = y == y1 ? v1 : v2;
        vertices[currentIndex] = x;
        vertices[currentIndex + 1] = y;
        vertices[currentIndex + 2] = u;
        vertices[currentIndex + 3] = v;
        vertices[currentIndex + 4] = colour.x;
        vertices[currentIndex + 5] = colour.y;
        vertices[currentIndex + 6] = colour.z;
        vertices[currentIndex + 7] = colour.w;
        vertices[currentIndex + 8] = textureIndex;
    }
}

质地:

public Texture(String filepath) {
        IntBuffer width = BufferUtils.createIntBuffer(1);
        IntBuffer height = BufferUtils.createIntBuffer(1);
        IntBuffer channels = BufferUtils.createIntBuffer(1);

        ByteBuffer data = STBImage.stbi_load(filepath, width, height, channels, 0);
        m_Width = width.get();
        m_Height = height.get();
        m_Channels = channels.get();

        m_RendererID = glCreateTextures(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, m_RendererID);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        assert data != null : "Image " + filepath + " doesn't exist";
        STBImage.stbi_image_free(data);
    }

【问题讨论】:

  • 我编辑了问题以包含纹理
  • 请注意u_TextureSlots[index] 是未定义的行为。未定义的行为意味着它可能会起作用,但规范并不保证它会起作用。不同硬件上的行为会有所不同。

标签: java opengl textures lwjgl


【解决方案1】:

片段着色器的行为未定义,因为:

int index = int(v_TexIndex);
... u_TextureSlots[index]...;

u_TextureSlots 是一个采样器数组,v_TexIndex 是片段着色器输入,因此index 不是Dynamically uniform expression
请注意,未定义的行为意味着它可能会起作用,但规范并不保证它会起作用。不同硬件上的行为会有所不同。

请参阅 GLSL 版本 4.60(最新)(来自 OpenGL Shading Language 4.60 Specification - 4.1.7. Opaque Types):
(当然这条规则也适用于 GLSL 4.50 版)

当在着色器中聚合成数组时,这些类型只能使用动态统一的表达式进行索引,否则纹理查找将导致未定义的值。


我建议使用sampler2DArray(参见Sampler)而不是sampler2D 的数组。 当您使用sampler2DArray 时,您根本不需要任何索引,因为“索引”在纹理查找时被编码在纹理坐标的第三个分量中(请参阅Texture)。


此外,要么指定纹理目标并使用glTexParameter

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

或纹理对象并使用glTextureParameteri

glTextureParameteri(m_RendererID, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

【讨论】:

    猜你喜欢
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多