【问题标题】:Texture being rendered as black quad纹理被渲染为黑色四边形
【发布时间】:2017-09-26 14:19:31
【问题描述】:

我一直在尝试遵循this tutorial on OpenGL3+ textures 中指定的code,但结果是黑色而不是纹理。

我正在使用stbimage 将纹理使用的图像加载到直接的 ByteBuffer 中,并且可以保证缓冲区中的 RGB 数据至少是不统一的 - 所以不可能那样。

我通常不喜欢转储代码,但目前我看不出还有什么可以做的。这是我的 java 代码和着色器:

GL 是一个指向 LWJGL31 中所有 GL## 功能的接口。

ShaderProgram 将所有着色器特定的东西包装到一个漂亮的黑盒中,该黑盒在第一次调用use(GL) 时从附加的着色器生成着色器程序,然后重用该程序。这对于渲染彩色三角形非常有效,因此我排除了其中的任何错误。

Util.checkError(GL, boolean); 会检查自上次执行以来累积的任何 OpenGL 错误,如果未设置布尔值,则会引发运行时异常(如果设置,则静默写入日志)。

渲染代码,update(GL, long)每帧运行一次

private static final ResourceAPI res = API.get(ResourceAPI.class);

Image lwjgl32;

ShaderProgram prog = new ShaderProgram();
int vbo, vao, ebo;
int texture;

@Override
public void init(GL gl) {

    try {
        prog.attach(res.get("shaders/texDemo.vert", ShaderSource.class));
        prog.attach(res.get("shaders/texDemo.frag", ShaderSource.class));
        lwjgl32 = res.get("textures/lwjgl32.png", Image.class);
    } catch(ResourceException e) {
        throw new RuntimeException(e);
    }

    float[] vertices = {
        // positions          // colors           // texture coords
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left 
    };

    int[] indices = {
        0, 1, 3, // first triangle
        1, 2, 3  // second triangle
    };

    vao = gl.glGenVertexArrays();
    vbo = gl.glGenBuffers();
    ebo = gl.glGenBuffers();

    gl.glBindVertexArray(vao);

    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
    gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices, GL.GL_STATIC_DRAW);

    gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, ebo);
    gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices, GL.GL_STATIC_DRAW);

    gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 0);
    gl.glEnableVertexAttribArray(0);

    gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 3 * Float.BYTES);
    gl.glEnableVertexAttribArray(0);

    gl.glVertexAttribPointer(2, 2, GL.GL_FLOAT, false, 8 * Float.BYTES, 6 * Float.BYTES);
    gl.glEnableVertexAttribArray(0);

    texture = gl.glGenTextures();
    gl.glBindTexture(GL.GL_TEXTURE_2D, texture);

    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);

    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);

    gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8, lwjgl32.getWidth(), lwjgl32.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, lwjgl32.getImageData());
    gl.glGenerateMipmap(GL.GL_TEXTURE_2D);

    prog.use(gl);
    gl.glUniform1i(gl.glGetUniformLocation(prog.getId(gl), "texture"), 0);

    Util.checkError(gl, false);
}

@Override
protected void update(GL gl, long deltaFrame) {
    gl.glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    gl.glClear(GL.GL_COLOR_BUFFER_BIT);

    gl.glActiveTexture(GL.GL_TEXTURE0);
    gl.glBindTexture(GL.GL_TEXTURE_2D, texture);

    prog.use(gl);
    gl.glBindVertexArray(vao);
    gl.glDrawElements(GL.GL_TRIANGLES, 6, GL.GL_UNSIGNED_INT, 0);
}

@Override
public void clean(GL gl) {
    gl.glDeleteVertexArrays(vao);
    gl.glDeleteBuffers(vbo);
    gl.glDeleteBuffers(ebo);

    ShaderProgram.clearUse(gl);
    prog.dispose(gl);
}

顶点着色器

#version 330 core

layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_color;
layout (location = 2) in vec2 in_texCoord;

out vec3 color;
out vec2 texCoord;

void main() {
    gl_Position = vec4(in_position, 1.0);

    color = in_color;
    texCoord = vec2(in_texCoord.x, in_texCoord.y);
}

片段着色器

#version 330 core

out vec4 frag_colour;

in vec3 color;
in vec2 texCoord;

uniform sampler2D texture;

void main() {
    frag_colour = texture(texture, texCoord) * vec4(color, 1.0);
}

1我将 LWJGL3 的 GL## 静态类包装到单个接口和实现中,这样我就可以拥有一堆有状态的方法来执行诸如识别正在呈现的上下文之类的事情等。我也尽我所能从界面中删除非核心功能,所以我什至不想使用已弃用的东西

【问题讨论】:

    标签: java textures lwjgl opengl-3


    【解决方案1】:

    你只启用索引为 0 的顶点属性,但是这 3 次。

    像这样调整你的代码:

    gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 0);
    gl.glEnableVertexAttribArray(0);
    
    gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 8 * Float.BYTES, 3 * Float.BYTES);
    gl.glEnableVertexAttribArray(1); // <-------
    
    gl.glVertexAttribPointer(2, 2, GL.GL_FLOAT, false, 8 * Float.BYTES, 6 * Float.BYTES);
    gl.glEnableVertexAttribArray(2); // <------
    

    【讨论】:

      【解决方案2】:

      仅看代码很难判断,但黑色四边形表示片段着色器中的这一行:

      frag_colour = texture(texture, texCoord) * vec4(color, 1.0);
      

      评估为 0。这意味着纹理未正确读取/绑定,您的纹理坐标已关闭或颜色为零向量。确保您的纹理图像已正确加载(文件存在,具有宽度和高度等)并具有正确的格式。我通常调试着色器的做法是将每个参数设置为一种颜色,以便在其值正确时给出提示:

      frag_colour = vec4(color, 1.0); //Makes sure the color is right
      

      frag_colour = texture(texture, texCoord); //Makes sure the texture is loaded and bound
      

      如果这没有提供足够的信息,那就更详细了:

      frag_colour = vec4(color.x, color.x, color.x, 1.0);
      

      frag_colour = vec4(texCoord.x, texCoord.x, texCoord.x, 1.0);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-27
        • 1970-01-01
        相关资源
        最近更新 更多