LWJGL:无法使用 nvidia gpu 绘制纹理

LWJGL: Unable to draw textures using nvidia gpu

所以我们正在 Java 中使用 LWJGL 与 GLFW 和 OpenGL 3.3 开发一个简单的游戏。

在 AMD 和 Intel 上运行良好,但在 Nvidia 上运行不佳。屏幕只是黑色(来自 glClearColor 的值),既没有 Java-exceptions 也没有 OpenGL-Errors.

我们做错了什么?

Main.java:

public class Main {
    Shader defaultShader;
    boolean running = false;
    long window;
    int width = 1000;
    int height = 1000;
    String title = "pain";
    int vao;

    public static void main(String[] args){
        var pain = new Pain();
        pain.init();
        pain.run();
    }

    public void init() throws RuntimeException {
        GLFWErrorCallback.createPrint(System.err).set();
        if (!glfwInit()) throw new RuntimeException("glfw.init.failed");

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

        this.window = glfwCreateWindow(this.width, this.height, this.title, 0, 0);
        if (window == NULL) throw new RuntimeException("glfw.window.failed");

        glfwMakeContextCurrent(window);
        glfwSwapInterval(1);
        GL.createCapabilities();
        glEnable(GL_TEXTURE_2D);

        this.vao = glGenVertexArrays();
        glBindVertexArray(vao);

        this.defaultShader = new Shader("main");

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }

    public void run() {
        this.running = true;
        glfwShowWindow(window);

        IntBuffer width = BufferUtils.createIntBuffer(1);
        IntBuffer height = BufferUtils.createIntBuffer(1);
        IntBuffer comp = BufferUtils.createIntBuffer(1);

        ByteBuffer data = null;
        try {
            data = stbi_load_from_memory(BufferCreator.createByteBuffer(FileHandler.readFileAsBytes("fuckoff/" + "heal_powerup.png")), width, height, comp, 4);
        } catch (IOException ignored) {}
        if (data == null) throw new RuntimeException("texture.load.failed");

        int id = glGenTextures();
        int twidth = width.get();
        int theight = height.get();

        glBindTexture(GL_TEXTURE_2D, id);

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

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        stbi_image_free(data);

        int vid;
        int tid;
        int dc;
        int arg4;
        int[] indices = {0, 1, 2, 2, 3, 0};
        dc = indices.length;

        vid = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vid);
        glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
                0.0f, 0.0f,
                100.0f, 0.0f,
                100.0f, 100.0f,
                0.0f, 100.0f
        }), GL_DYNAMIC_DRAW);

        arg4 = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferCreator.createIntBuffer(indices), GL_STATIC_DRAW);

        tid = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, tid);
        glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
                0.0f, 0.0f,
                1.0f, 0.0f,
                1.0f, 1.0f,
                0.0f, 1.0f
        }), GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);



        while(this.running) {
            glfwPollEvents();
            glClear(GL_COLOR_BUFFER_BIT);

            defaultShader.bind();

            glBindTexture(GL_TEXTURE_2D, id);
            this.defaultShader.setUniform("sampler", 0);

            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);

            glBindBuffer(GL_ARRAY_BUFFER, vid);
            glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);

            glBindBuffer(GL_ARRAY_BUFFER, tid);
            glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
            glDrawElements(GL_TRIANGLES, dc, GL_UNSIGNED_INT, 0);


            //Unbind buffers
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
            //Disable
            glDisableVertexAttribArray(0);
            glDisableVertexAttribArray(1);

            glfwSwapBuffers(window);
            if (glfwWindowShouldClose(window)) shutdown();
            System.out.println(glGetError());
        }

        glfwFreeCallbacks(this.window);
        glfwDestroyWindow(this.window);
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    void shutdown(){
        this.running = false;
    }
}

Shader.java:

public class Shader {
    private int program, vs, fs;

    public Shader(String name) {
        try {
            this.program = glCreateProgram();

            this.vs = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(this.vs, FileHandler.readFile("shaders/" + name + ".vs"));
            glCompileShader(this.vs);
            if (glGetShaderi(this.vs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed\n" + glGetShaderInfoLog(vs));

            this.fs = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(this.fs, FileHandler.readFile("shaders/" + name + ".fs"));
            glCompileShader(this.fs);
            if (glGetShaderi(this.fs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed" + glGetShaderInfoLog(fs));

            glAttachShader(this.program, this.vs);
            glAttachShader(this.program, this.fs);

            glBindAttribLocation(this.program, 0, "vertices");
            glBindAttribLocation(this.program, 1, "textures");

            glLinkProgram(this.program);
            if (glGetProgrami(this.program, GL_LINK_STATUS) != 1) throw new RuntimeException("shader.link.failed");
            glValidateProgram(this.program);
            if (glGetProgrami(this.program, GL_VALIDATE_STATUS) != 1) throw new RuntimeException("shader.validation.failed");
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void updateShaderParameters() {
        this.setUniform("sampler", 0);
        int location = glGetUniformLocation(this.program, "windowSize");
        if (location != 1) {
            glUniform2f(location, 1000, 1000);
        }
    }

    public void setUniform(String name, int value) {
        int location = glGetUniformLocation(this.program, name);
        if (location != -1) {
            glUniform1i(location, value);
        }
    }

    public void bind() {
        glUseProgram(this.program);
        this.updateShaderParameters();
    }
}

顶点着色器:

#version 330 core

layout (location = 0) in vec2 vertices;
layout (location = 1) in vec2 textures;

uniform vec2 windowSize;

out vec2 tex_coords;

void main() {
    tex_coords = textures;
    gl_Position = vec4(2.0/windowSize.x * vertices.x - 1.0, (2.0/windowSize.y * vertices.y - 1.0) * -1.0, 1, 1);
}

片段着色器:

#version 330 core

uniform sampler2D sampler;

out vec4 FragColor;

in vec2 tex_coords;

void main() {
    if (texture(sampler, tex_coords).a != 1.0f) {
        discard;
    }

    FragColor = texture(sampler, tex_coords);
}

BufferCreator.java 和 FileHandler.java 是简单的实用程序-类 似乎工作得很好。

我假设,它与采样器有关,因为当我删除片段着色器中的 if...discard 语句并将 FragColor 设置为一些随机值时,它被绘制了。

在您的 updateShaderParameters() 方法中,您检查 !=1 它应该是 !=-1,因为 windowSize 位置将为 1。
如果您检查 1,它将永远不会被设置.
最后这可能是疏忽或错误输入。发生在我们最好的人身上。

public void updateShaderParameters() {
        this.setUniform("sampler", 0);
        int location = glGetUniformLocation(this.program, "windowSize");
        if (location != -1) {
            glUniform2f(location, 1000, 1000);
        }
    }