lwjgl纹理呈现黑色

时间:2020-06-06 08:46:55

标签: java opengl lwjgl opengl-3

尝试使用https://learnopengl.com/Getting-started/Textures课程学习OpenGL 3时,在未应用纹理(或未以我期望的方式应用纹理)时遇到了一个问题。

import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;

import java.nio.ByteBuffer;
import java.util.Random;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL33.*;
import static org.lwjgl.system.MemoryUtil.NULL;

public class Learn33 {

    static long window;

    static float triangles[] = {
            // 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
    };
    static int triangleVertexArray;
    static int indices[] = {
            0, 1, 3,
            1, 2, 3
    };

    static Shader shader;
    static int texture;

    public static void main(String[] args) {
        try {
            init();
            shader = Shader.load("texture"); // shader loading, compiling, linking
            loadModel();
            loop();
        } finally {
            glfwTerminate();
        }
    }

    private static void loadModel() {
        triangleVertexArray = glGenVertexArrays();
        int triangleDataBuffer = glGenBuffers();
        int triangleIndexBuffer = glGenBuffers();

        glBindVertexArray(triangleVertexArray);

        glBindBuffer(GL_ARRAY_BUFFER, triangleDataBuffer);
        glBufferData(GL_ARRAY_BUFFER, triangles, GL_STATIC_DRAW);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 32, 0);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, triangleDataBuffer);
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 32, 12);
        glEnableVertexAttribArray(1);

        glVertexAttribPointer(2, 2, GL_FLOAT, false, 32, 24);
        glEnableVertexAttribArray(2);

        //texture
        texture = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        int width = 512;
        int height = 512;
        byte[] pixels = new byte[width * height * 3];
        new Random().nextBytes(pixels);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, ByteBuffer.wrap(pixels));
        glGenerateMipmap(GL_TEXTURE_2D);

        shader.use(); // same as glUseProgram(id);
        shader.setInt("texture1", 0); // same as glUniform1i(glGetUniformLocation(id, "texture1"), 0)
    }

    private static void loop() {
        GL.createCapabilities();

        while (!glfwWindowShouldClose(window)) {
            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);

            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, texture);

            shader.use();
            glBindVertexArray(triangleVertexArray);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

            glfwSwapBuffers(window);
            glfwPollEvents();
        }
    }

    private static void init() {
        GLFWErrorCallback.createPrint(System.err).set();

        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

        window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        glfwMakeContextCurrent(window);

        GL.createCapabilities();
        glViewport(0, 0, 800, 600);

        glfwSetFramebufferSizeCallback(window, (wnd, width, height) -> glViewport(0, 0, width, height));
    }
}

顶点着色器:

#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 vertexColor;
out vec2 textureCoordinates;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    vertexColor = aColor;
    textureCoordinates = aTexCoord;
}

片段着色器:

#version 330 core

in vec3 vertexColor;
in vec2 textureCoordinates;

out vec4 FragColor;

uniform sampler2D texture1;

void main()
{
    FragColor = texture(texture1, textureCoordinates);
}

由于我用随机值填充纹理数据,所以我希望有嘈杂的图案。实际上,结果是黑色矩形:

enter image description here

当我将片段着色器更改为:

FragColor = vec4(textureCoordinates, 0.0, 1.0);

证明纹理坐标正确传递: enter image description here

因此问题一定在于如何填充纹理像素或将其传递给Open GL。可能是什么?会感谢您提供任何帮助,包括调试建议。

更新。有用的代码来检查错误。如果将其放入纹理加载代码或渲染循环中,则什么也不打印。

private static void checkErrors() {
    int i = glGetError();
    if (i != GL_NO_ERROR) {
        System.err.println("Error code: " + i);
    }
}

解决方案 如评论中所建议,此处Empty texture when using glTexImage2D with ByteBuffer in LWJGL

报告了类似的问题

更改为

        byte[] pixels = new byte[width * height * 3];
        new Random().nextBytes(pixels);
        ByteBuffer buffer = BufferUtils.createByteBuffer(pixels.length);
        buffer.put(pixels);
        buffer.flip();

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);

它开始工作: enter image description here

0 个答案:

没有答案