Why it doesn't draw a rectangle ?

Started by t0m, August 15, 2017, 14:00:39

Previous topic - Next topic

t0m

Hi everyone, newbie here :)
I have followed some tutorials to simply draw triangles with OpenGL using LWJGL.
Here is my code :
/**** Game.java ****/
public class Game {
	private Screen screen;
	private String title;
	private int width, height;
	private long windowID;
	public Game(String title, int width, int height) {
		this.init();
	}

	private void init() {
		GLFWErrorCallback.createPrint(System.err).set();
		if ( !glfwInit() )
			throw new IllegalStateException("Unable to initialize GLFW");
		System.out.println("GLFW initalized !");	
	}
	public void create(Screen screen) {	
		glfwDefaultWindowHints();
                // Asking for OpenGL 3.X, cause OS X use 2.X by default
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
		glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
		glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
		windowID = glfwCreateWindow(this.width, this.height, this.title, NULL, NULL);
		if ( windowID == 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(windowID, pWidth, pHeight);
			GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
			glfwSetWindowPos(
				windowID,
				(vidmode.width() - pWidth.get(0)) / 2,
				(vidmode.height() - pHeight.get(0)) / 2
			);
		}
		glfwMakeContextCurrent(windowID);
		glfwSwapInterval(1);
		glfwShowWindow(windowID);
		GL.createCapabilities();

                // Here is called the Screen.init() method
		setScreen(screen);
		
		loop();
	}
	
	private void loop() {
		if (screen != null) {
			glClearColor(screen.getClearColor().x, screen.getClearColor().y, screen.getClearColor().z, screen.getClearColor().w);
		} else {
			glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
		}
		while ( !glfwWindowShouldClose(windowID) ) {
			render();
		}
		destroy();
	}
	
	private void render() {
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glfwSwapBuffers(windowID);
		glfwPollEvents();
		if (screen != null) {
			this.screen.update();
			this.screen.render();
		}
	}
	public void setScreen(Screen screen) {
		if (this.screen != null)
			this.screen.destroy();
		this.screen = screen;
		this.screen.init();
	}
    }

/**** TestScreen.java ****/
public class TestScreen extends Screen {
	float[] vertices = {
	        // Left bottom triangle
	        -0.5f, 0.5f, 0f,
	        -0.5f, -0.5f, 0f,
	        0.5f, -0.5f, 0f,
	        // Right top triangle
	        0.5f, -0.5f, 0f,
	        0.5f, 0.5f, 0f,
	        -0.5f, 0.5f, 0f
	};
	VAO vao;
	public void init() {
		//System.out.println("OpenGL v." + GL11.glGetString(GL11.GL_VERSION));
		setClearColor(new Vector4f(0.5f, 0.3f, 1f, 1f));
		vao = new VAO(vertices);
	}
	public void render() {
		// Bind to the VAO that has all the information about the quad vertices
		GL30.glBindVertexArray(vao.getVAO());
		GL20.glEnableVertexAttribArray(0);
		// Draw the vertices
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vao.getVerticesCount());
		// Put everything back to default (deselect)
		GL20.glDisableVertexAttribArray(0);
		GL30.glBindVertexArray(0);
	}
	public void update() {}
	public void destroy() {
		vao.destroy();
	}

/**** VAO.java ****/
public class VAO {
	private int vaoID;
	private int vboID;
	private int verticesCount;
	public VAO(float[] vertices) {
		// VAO creation
		vaoID = GL30.glGenVertexArrays();
		// Bind the VAO
		GL30.glBindVertexArray(vaoID);
		// VBO creation
		vboID = GL15.glGenBuffers();
		// Bind the VBO
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
		// Push the vertices array in the VBO
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, floatToFloatBuffer(vertices), GL15.GL_STATIC_DRAW);
		// Push the VBO in the VAO at index 0
		GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
		// Deselect all
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		GL30.glBindVertexArray(0);
		verticesCount = vertices.length / 3;
	}
	public FloatBuffer floatToFloatBuffer(float[] vertices) {
		FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
		verticesBuffer.put(vertices);
		verticesBuffer.flip();
		return verticesBuffer;
	}
	public void destroy() {
		// Delete the VBO
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		GL15.glDeleteBuffers(vboID);
		// Delete the VAO
		GL30.glBindVertexArray(0);
		GL30.glDeleteVertexArrays(vaoID);
	}

It does just draw an empty purple screen, but no white rectangle...
Thanks.

Kai

There is at least one issue that can be seen immediately in your code:
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glfwSwapBuffers(windowID);

You are clearing the backbuffer (and what was rendered to it previously), and then immediately swap it to front. That does not make any sense. The sequence is:
1. clear
2. render (draw calls)
3. swapbuffers

But your current sequence is:
1. clear
2. swapbuffers
3. render (draw calls)

or equivalently but more obvious:
1. render (draw calls)
2. clear    <-- clearing right after rendering? No.
3. swapbuffers

that means that whatever got rendered in 3 in iteration i-1 will immediately be cleared in iteration i.

If you suspect any more errors in your code, you can also run it with LWJGLX/debug and see what it outputs.

t0m

Thanks for reply, I changed the order of lines as you said, but still no rectangle (but thx for explanations).
I didn't know LWJGL Debug so I will test.

t0m

So I tried LWJGLX Debug and it gives me this error :
glDrawArrays produced error: 1282 (GL_INVALID_OPERATION)

Any idea ?

Kai