OpenGL 中的三角形无法渲染

问题描述 投票:0回答:1

我正在使用 LWJGL 3,我的三角形不渲染。这是我的代码:

package com.xicreations.infinimob;

import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryStack;

import java.nio.IntBuffer;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.NULL;

public class Infinimob 
{
    private final int WIDTH = 800, HEIGHT = 800;
    private final String TITLE = "Infinimob 0.0.1a";
    
    private static String vs = "#version 330 core\n" + 
    "layout (location = 0) in vec3 aPos;\n" + 
    "void main()\n" +
    "{\n" + 
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" + 
    "}\0";
    
    private static String fs = "#version 330 core\n" + 
            "out vec4 fragColor;\n" + 
            "void main()\n" +
            "{\n" + 
            "   fragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n" + 
            "}\0";
    
    private long window;
    private int vao, vbo;
    private int vertexCount = 3;
    
    private void init()
    {
        if (!glfwInit()) 
        {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

        window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
        if (window == NULL) 
        {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        try (MemoryStack stack = stackPush()) 
        {
            IntBuffer pWidth = stack.mallocInt(1);
            IntBuffer pHeight = stack.mallocInt(1);

            glfwGetWindowSize(window, pWidth, pHeight);

            GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            glfwSetWindowPos(
                    window,
                    (vidMode.width() - pWidth.get(0)) / 2,
                    (vidMode.height() - pHeight.get(0)) / 2
            );
        }

        glfwMakeContextCurrent(window);
        glfwSwapInterval(1);
        glfwShowWindow(window);
    }
    
    private int loadShader(String shaderSource, int shaderType) 
    {
        int shader = glCreateShader(shaderType);
        glShaderSource(shader, shaderSource);
        glCompileShader(shader);
        if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
            throw new RuntimeException("Failed to compile shader: " + glGetShaderInfoLog(shader));
        }
        return shader;
    }

    private void initShaders() 
    {
        int vertexShader = loadShader(vs, GL_VERTEX_SHADER);
        int fragmentShader = loadShader(fs, GL_FRAGMENT_SHADER);

        int shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, fragmentShader);
        glAttachShader(shaderProgram, vertexShader);
        glLinkProgram(shaderProgram);
        if (glGetProgrami(shaderProgram, GL_LINK_STATUS) == GL_FALSE) {
            throw new RuntimeException("Failed to link shader program: " + glGetProgramInfoLog(shaderProgram));
        }
        glUseProgram(shaderProgram);
    }
    
    private void loop() 
    {
        GL.createCapabilities();
        initShaders();

        float[] vertices = 
        {
                -0.5f, -0.5f, 0.0f,
                0.5f, -0.5f, 0.0f,
                0.0f, 0.5f, 0.0f
        };

        vao = glGenVertexArrays();
        vbo = glGenBuffers();

        glBindVertexArray(vao);

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

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

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        glViewport(0, 0, WIDTH, HEIGHT);
        
        while (!glfwWindowShouldClose(window)) 
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
            glUseProgram(0);
            glBindVertexArray(vao);
            glDrawArrays(GL_TRIANGLES, 0, vertexCount);
            glBindVertexArray(0);

            glfwSwapBuffers(window);

            glfwPollEvents();
        }
    }

    private void cleanup() 
    {
        glDeleteBuffers(vbo);
        glDeleteVertexArrays(vao);
        glfwTerminate();
    }
    
    public static void main(String[] args) 
    {
        Infinimob app = new Infinimob();
        app.init();
        app.loop();
        app.cleanup();
    }
}

我认为它应该有效,但事实并非如此。

更多信息:

我正在使用 OpenGL 3.3,更奇怪的是,如果我使顶点着色器和片段着色器完全相同,并删除对链接错误的检查,则三角形渲染为白色。如果没有效果,我可能会重写整个代码。

java opengl lwjgl
1个回答
0
投票

在此代码中-

while (!glfwWindowShouldClose(window)) 
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
    glUseProgram(0);
    glBindVertexArray(vao);

您不应该将“0”传递给 glUseProgram。它将取消绑定您在 initShaders 函数中创建并绑定的着色器程序。您应该传递 glCreateProgram 返回的着色器程序的句柄/id。

但是,在 initShaders 函数中,您没有将句柄/id 值存储在类的成员变量中。所以你能做的就是简单地删除“glUseProgram(0);”行,因为程序已经绑定并且应该可以工作,即使我还没有测试代码。

更理想的解决方案是将“int ShaderProgram”声明为成员变量而不是 local-

private void initShaders() 
{
    int vertexShader = loadShader(vs, GL_VERTEX_SHADER);
    int fragmentShader = loadShader(fs, GL_FRAGMENT_SHADER);

    shaderProgram = glCreateProgram();
...

然后在绘制三角形之前将其传递给 glUseProgram -

while (!glfwWindowShouldClose(window)) 
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
    glUseProgram(shaderProgram);
    glBindVertexArray(vao);
© www.soinside.com 2019 - 2024. All rights reserved.