You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LWJGL3+OpenGL 3.2三角形Demo窗口空白无报错求助

问题:LWJGL3 + OpenGL 3.2+ 三角形Demo空白无渲染(无OpenGL错误)

我正在学习LWJGL3与OpenGL 3.2+,编写了一个三角形Demo程序。程序运行正常且未出现任何OpenGL错误,但窗口始终显示空白,三角形无法渲染出来。

已排查常见问题:VAO已创建绑定并配置顶点属性,三角形坐标有效,着色器编译链接均正常,仍找不到原因。

完整代码

package net.part1kl;

import com.hackoeur.jglm.Mat4;
import com.hackoeur.jglm.Matrices;
import org.lwjgl.Version;
import org.lwjgl.glfw.*;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.opengl.GL;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL30C.*;
import static org.lwjgl.system.MemoryUtil.*;


public class Demo {

    public static void main(String[] args) {
        init();
        loop();
        dispose();
    }

    private static long window;

    private static void init(){
        /* Initialize GLFW */
        System.out.println(Version.getVersion());
        glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err));
        if (!glfwInit()) throw new IllegalStateException("GLFW Init Failed");

        /* Set window hints and create window */
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        window = glfwCreateWindow(600, 600, "Demo", NULL, NULL);
        if ( window == NULL) { glfwTerminate(); throw new RuntimeException("Window Creation Failed"); }

        /* Other window setup */
        glfwSetWindowPos(window, 200, 200);
        glfwMakeContextCurrent(window);
        GL.createCapabilities();
        glfwSwapInterval(1);
        glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, true);
        });
        glfwShowWindow(window);

        /* Create and bind VAO */
        vao = glGenVertexArrays();
        glBindVertexArray(vao);

        /* Create, bind, and populate VBO */
        vbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        FloatBuffer verts = memAllocFloat(vertices.length);
        for (float val : vertices) verts.put(val);
        verts.flip();
        glBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
        memFree(verts);

        /* Create Vertex Shader */
        vShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vShader, vertexSource);
        glCompileShader(vShader);
        if (glGetShaderi(vShader, GL_COMPILE_STATUS) != GL_TRUE) throw new RuntimeException(glGetShaderInfoLog(vShader));

        /* Create Fragment Shader */
        fShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fShader, fragmentSource);
        glCompileShader(fShader);
        if (glGetShaderi(fShader, GL_COMPILE_STATUS) != GL_TRUE) throw new RuntimeException(glGetShaderInfoLog(fShader));

        /* Create Shader Program */
        program = glCreateProgram();
        glAttachShader(program, vShader);
        glAttachShader(program, fShader);
        glBindFragDataLocation(program, 0, "fragColor");
        glLinkProgram(program);
        if (glGetProgrami(program, GL_LINK_STATUS) != GL_TRUE) throw new RuntimeException(glGetProgramInfoLog(program));
        glUseProgram(program);

        /* Set pointer for vertex position information */
        int pAttr = glGetAttribLocation(program, "position");
        glEnableVertexAttribArray(pAttr);
        glVertexAttribPointer(pAttr, 3, GL_FLOAT, false, 6 * Float.BYTES, 0);

        /* Set pointer for vertex color information */
        int cAttr = glGetAttribLocation(program, "color");
        glEnableVertexAttribArray(cAttr);
        glVertexAttribPointer(cAttr, 3, GL_FLOAT, false, 6 * Float.BYTES, 3 * Float.BYTES);

        /* Create and set model uniform. Using com.hackoeur.jglm v1.0.0 for matrices. */
        Mat4 model = new Mat4();
        int uModel = glGetUniformLocation(program, "model");
        glUniformMatrix4fv(uModel, false, (FloatBuffer)model.getBuffer().flip());

        /* Create and set view uniform */
        Mat4 view = new Mat4();
        int uView = glGetUniformLocation(program, "view");
        glUniformMatrix4fv(uView, false, (FloatBuffer)view.getBuffer().flip());

        /* Get window size ratio for projection */
        IntBuffer width = memAllocInt(1);
        IntBuffer height = memAllocInt(1);
        GLFW.glfwGetFramebufferSize(window, width, height);
        float ratio = width.get() / (float) height.get();
        memFree(width); memFree(height);

        /* Create and set projection uniform */
        Mat4 projection = Matrices.ortho(-ratio, ratio, -1f, 1f, -1f, 1f);
        int uProjection = glGetUniformLocation(program, "projection");
        glUniformMatrix4fv(uProjection, false, (FloatBuffer)projection.getBuffer().flip());
    }

    private static void loop(){
        double lastTime = glfwGetTime();
        double time = lastTime;
        while(!glfwWindowShouldClose(window)){
            double delta = (float) (time - lastTime);

            glClear(GL_COLOR_BUFFER_BIT);

            glBindVertexArray(vao);
            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glUseProgram(program);


            glDrawArrays(GL_TRIANGLES, 0, 3);

            glfwSwapBuffers(window);
            glfwPollEvents();

            glCheck();

            lastTime = time;
            time = glfwGetTime();
        }
    }

    private static void dispose(){
        glDeleteVertexArrays(vao);
        glDeleteBuffers(vbo);
        glDeleteShader(vShader);
        glDeleteShader(fShader);
        glDeleteProgram(program);

        glfwDestroyWindow(window);
    }

    private static void print(String message) { System.out.println(message); }

    private static void err(String message) { System.err.println(message); }

    private static int glCheckCounter = 0;

    private static void glCheck() {
        int val = glGetError();
        if (val==0) print("GL Error Check "+glCheckCounter+" no error.");
        else err("GL Error Check "+glCheckCounter+" returned error "+val);
        glCheckCounter++;
    }


    private static int vao, vbo, vShader, fShader, program;
    private static final float[] vertices = {
            -0.6f,   -0.4f,   0f,   1f,   0f,   0f,
             0.6f,   -0.4f,   0f,   0f,   1f,   0f,
               0f,    0.6f,   0f,   0f,   0f,   1f
    };
    private static final CharSequence vertexSource
            = "#version 150 core\n"
            + "\n"
            + "in vec3 position;\n"
            + "in vec3 color;\n"
            + "\n"
            + "out vec3 vertexColor;\n"
            + "\n"
            + "uniform mat4 model;\n"
            + "uniform mat4 view;\n"
            + "uniform mat4 projection;\n"
            + "\n"
            + "void main() {\n"
            + "    vertexColor = color;\n"
            + "    mat4 mvp = projection * view * model;\n"
            + "    gl_Position = mvp * vec4(position, 1.0);\n"
            + "}";
    private static final CharSequence fragmentSource
            = "#version 150 core\n"
            + "\n"
            + "in vec3 vertexColor;\n"
            + "\n"
            + "out vec4 fragColor;\n"
            + "\n"
            + "void main() {\n"
            + "    fragColor = vec4(vertexColor, 1.0);\n"
            + "}";
}

程序运行输出

3.3.1 build 7
GL Error Check 0 no error.
GL Error Check 1 no error.
GL Error Check 2 no error.
GL Error Check 3 no error.
GL Error Check 4 no error.
GL Error Check 5 no error.
GL Error Check 6 no error.
GL Error Check 7 no error.

问题原因与解决方法

问题出在未设置OpenGL视口。

OpenGL默认视口尺寸为(0, 0, 1, 1),仅占窗口的1x1像素,导致渲染的三角形无法在窗口中显示。需要在初始化OpenGL上下文后,添加视口设置代码,将视口尺寸与窗口帧缓冲尺寸匹配。

修改步骤:

在init()函数中,GL.createCapabilities();之后,添加以下代码:

// 获取窗口帧缓冲尺寸
IntBuffer width = memAllocInt(1);
IntBuffer height = memAllocInt(1);
glfwGetFramebufferSize(window, width, height);
// 设置视口
glViewport(0, 0, width.get(), height.get());
memFree(width);
memFree(height);

另外,建议添加清屏颜色设置,让三角形与背景更易区分,可在视口设置后添加:

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

修改后重新运行程序,即可看到彩色三角形正常渲染。

内容的提问来源于stack exchange,提问作者part1kl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 20:17:13