I'm trying to make a game engine, but I'm stuck at the triangle step. Since my current code has multiple classes, I tried to simplify it into one 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;
}
}
This is triangle.vert.glsl:
#version 400 core
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
This is triangle.frag.glsl:
#version 400 core
out vec4 color;
void main() {
color = vec4(0.0, 0.0, 1.0, 1.0);
}
When I run the program, there are no OpenGL or GLSL errors. I tried using glGetError()
but everything is 0.
I'm expecting to see a blue triangle with a red background, but I have just a red window. I am fairly certain that the problem is not with the GLFW code (the window does show up), or the shader code (the shader does compile and when I make an error in the shader code, the program lists it as such). But the triangle code seems to be okay too.
Is there anything I'm missing or have gotten wrong?
Note: I have tested this on just one computer, so it's possible it's a computer-specific error.
The order of operations per frame in your loop is wrong.
If we look at what happens during a frame (from swapbuffers to swapbuffers interval), then essentially, you first do the draw call which would render your triangle, then you clear the color buffers again (which will overwrite your triangle with the clear color) and then you swap buffers.
So, right now, the order of operations per frame is always:
In order to fix this, you should put the swap buffers call glfwSwapBuffers(window)
at the end of the loop, which would change the order of operations per frame to:
Then you will see the blue triangle.