为什么此代码在 LWJGL 3 中不显示三角形?
Why doesn't this code show a triangle in LWJGL 3?
我正在尝试制作游戏引擎,但我卡在了三角形步骤上。由于我目前的代码有多个class,我试图将其简化为一个class。
public class MainGame {
public static void main(String[] args) {
GLFW.glfwInit();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
long window = GLFW.glfwCreateWindow(900, 900, "Test Window", NULL, NULL);
GLFWVidMode vid = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
GLFW.glfwSetWindowPos(window, (vid.width() - 900)/2,
(vid.height() - 900)/2);
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
GLFW.glfwSwapInterval(1);
GLFW.glfwShowWindow(window);
int programId = 0;
try {
programId = loadProgram("triangle.vert.glsl", "triangle.frag.glsl");
} catch (IOException e) {
e.printStackTrace();
}
int vaoId = loadTriangle();
while (!GLFW.glfwWindowShouldClose(window)) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glClearColor(1, 0, 0, 1);
GLFW.glfwSwapBuffers(window);
GLFW.glfwPollEvents();
GL30.glUseProgram(programId);
GL30.glBindVertexArray(vaoId);
GL20.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
GL30.glUseProgram(0);
}
GL30.glDeleteVertexArrays(vaoId);
GL30.glDeleteProgram(programId);
GLFW.glfwDestroyWindow(window);
GLFW.glfwTerminate();
}
private static int loadTriangle() {
float[] positions = new float[] {
+0f, +1f,
-1f, -1f,
+1f, -1f
};
FloatBuffer buffer = BufferUtils.createFloatBuffer(positions.length);
buffer.put(positions);
buffer.flip();
int vaoId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoId);
int bufferId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);
GL30.glBindVertexArray(0);
return vaoId;
}
private static int loadProgram(String vertex, String fragment) throws IOException {
int vertexShader = GL30.glCreateShader(GL30.GL_VERTEX_SHADER);
int fragmentShader = GL30.glCreateShader(GL30.GL_FRAGMENT_SHADER);
String vertexCode = Files.lines(Paths.get(vertex))
.collect(Collectors.joining("\n"));
String fragmentCode = Files.lines(Paths.get(fragment))
.collect(Collectors.joining("\n"));
GL30.glShaderSource(vertexShader, vertexCode);
GL30.glCompileShader(vertexShader);
String slog = GL30.glGetShaderInfoLog(vertexShader);
System.out.println(slog);
GL30.glShaderSource(fragmentShader, fragmentCode);
GL30.glCompileShader(fragmentShader);
slog = GL30.glGetShaderInfoLog(fragmentShader);
System.out.println(slog);
int program = GL30.glCreateProgram();
GL30.glAttachShader(program, vertexShader);
GL30.glAttachShader(program, fragmentShader);
GL30.glLinkProgram(program);
GL30.glDetachShader(program, vertexShader);
GL30.glDetachShader(program, fragmentShader);
GL30.glDeleteShader(vertexShader);
GL30.glDeleteShader(fragmentShader);
return program;
}
}
这是triangle.vert.glsl:
#version 400 core
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
这是triangle.frag.glsl:
#version 400 core
out vec4 color;
void main() {
color = vec4(0.0, 0.0, 1.0, 1.0);
}
当我运行程序时,没有OpenGL或GLSL错误。我尝试使用 glGetError()
但一切都是 0.
我希望看到一个红色背景的蓝色三角形,但我只有一个红色 window。我相当确定问题不在于 GLFW 代码( window 确实出现)或着色器代码(着色器确实编译并且当我在着色器代码中出错时,程序将其列为这样的)。不过三角码好像也还行
有什么我遗漏或弄错的吗?
注意:我只在一台计算机上测试过,所以这可能是计算机特定的错误。
循环中每帧的操作顺序错误。
如果我们查看一帧期间发生的情况(从交换缓冲区到交换缓冲区间隔),那么本质上,您首先执行渲染三角形的绘制调用,然后再次清除颜色缓冲区(这将覆盖您的三角形使用清晰的颜色)和然后你交换缓冲区。
所以,现在,每帧的操作顺序总是:
- 平局
- 清除缓冲区
- 交换缓冲区
为了解决这个问题,您应该将交换缓冲区调用 glfwSwapBuffers(window)
放在循环的末尾,这会将每帧的操作顺序更改为:
- 清除缓冲区
- 平局
- 交换缓冲区
然后你会看到蓝色三角形。
我正在尝试制作游戏引擎,但我卡在了三角形步骤上。由于我目前的代码有多个class,我试图将其简化为一个class。
public class MainGame {
public static void main(String[] args) {
GLFW.glfwInit();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
long window = GLFW.glfwCreateWindow(900, 900, "Test Window", NULL, NULL);
GLFWVidMode vid = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
GLFW.glfwSetWindowPos(window, (vid.width() - 900)/2,
(vid.height() - 900)/2);
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
GLFW.glfwSwapInterval(1);
GLFW.glfwShowWindow(window);
int programId = 0;
try {
programId = loadProgram("triangle.vert.glsl", "triangle.frag.glsl");
} catch (IOException e) {
e.printStackTrace();
}
int vaoId = loadTriangle();
while (!GLFW.glfwWindowShouldClose(window)) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glClearColor(1, 0, 0, 1);
GLFW.glfwSwapBuffers(window);
GLFW.glfwPollEvents();
GL30.glUseProgram(programId);
GL30.glBindVertexArray(vaoId);
GL20.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
GL30.glUseProgram(0);
}
GL30.glDeleteVertexArrays(vaoId);
GL30.glDeleteProgram(programId);
GLFW.glfwDestroyWindow(window);
GLFW.glfwTerminate();
}
private static int loadTriangle() {
float[] positions = new float[] {
+0f, +1f,
-1f, -1f,
+1f, -1f
};
FloatBuffer buffer = BufferUtils.createFloatBuffer(positions.length);
buffer.put(positions);
buffer.flip();
int vaoId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoId);
int bufferId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);
GL30.glBindVertexArray(0);
return vaoId;
}
private static int loadProgram(String vertex, String fragment) throws IOException {
int vertexShader = GL30.glCreateShader(GL30.GL_VERTEX_SHADER);
int fragmentShader = GL30.glCreateShader(GL30.GL_FRAGMENT_SHADER);
String vertexCode = Files.lines(Paths.get(vertex))
.collect(Collectors.joining("\n"));
String fragmentCode = Files.lines(Paths.get(fragment))
.collect(Collectors.joining("\n"));
GL30.glShaderSource(vertexShader, vertexCode);
GL30.glCompileShader(vertexShader);
String slog = GL30.glGetShaderInfoLog(vertexShader);
System.out.println(slog);
GL30.glShaderSource(fragmentShader, fragmentCode);
GL30.glCompileShader(fragmentShader);
slog = GL30.glGetShaderInfoLog(fragmentShader);
System.out.println(slog);
int program = GL30.glCreateProgram();
GL30.glAttachShader(program, vertexShader);
GL30.glAttachShader(program, fragmentShader);
GL30.glLinkProgram(program);
GL30.glDetachShader(program, vertexShader);
GL30.glDetachShader(program, fragmentShader);
GL30.glDeleteShader(vertexShader);
GL30.glDeleteShader(fragmentShader);
return program;
}
}
这是triangle.vert.glsl:
#version 400 core
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
这是triangle.frag.glsl:
#version 400 core
out vec4 color;
void main() {
color = vec4(0.0, 0.0, 1.0, 1.0);
}
当我运行程序时,没有OpenGL或GLSL错误。我尝试使用 glGetError()
但一切都是 0.
我希望看到一个红色背景的蓝色三角形,但我只有一个红色 window。我相当确定问题不在于 GLFW 代码( window 确实出现)或着色器代码(着色器确实编译并且当我在着色器代码中出错时,程序将其列为这样的)。不过三角码好像也还行
有什么我遗漏或弄错的吗?
注意:我只在一台计算机上测试过,所以这可能是计算机特定的错误。
循环中每帧的操作顺序错误。
如果我们查看一帧期间发生的情况(从交换缓冲区到交换缓冲区间隔),那么本质上,您首先执行渲染三角形的绘制调用,然后再次清除颜色缓冲区(这将覆盖您的三角形使用清晰的颜色)和然后你交换缓冲区。
所以,现在,每帧的操作顺序总是:
- 平局
- 清除缓冲区
- 交换缓冲区
为了解决这个问题,您应该将交换缓冲区调用 glfwSwapBuffers(window)
放在循环的末尾,这会将每帧的操作顺序更改为:
- 清除缓冲区
- 平局
- 交换缓冲区
然后你会看到蓝色三角形。