Problem with rendering a quad using VBOs and VAOs

Started by Nitai99, August 15, 2020, 18:29:47

Previous topic - Next topic

Nitai99

So, I just started learning LWJGL 3 and I used a mixture of a couple of tutorials and example code to make something that should render a rectangle to a magenta screen using VAOs and VBOs. There are no errors but the rectangle doesn't appear on screen (all I can see is a magenta screen). I tried using the old LWJGL pipeline (glBegin() and glEnd()) and it does work so I tried changing random things in the rendering code and the loading to VAOs and VBOs. I also tried to bind the VBO too but it didn't change anything. I also tried debugging and it seems like there is a VAO and a VBO that is created.

Can someone take a look at my code and see if something looks wrong? Here it is (sorry if its a bit messy. Like I said, I don't think the problem is in the Main or Window class but I have no idea about LWJGL so I wanted to put it here anyways. If you have time, please also look at them. Otherwise I would really appreciate it if you could look at the Loader and Renderer classes):
The Raw Model class:
    package engine.io;

    public class RawModel {
	private int vaoID;
	private int vertexCount;
	
	
	public RawModel(int vaoID, int vertexCount) {
		this.vaoID = vaoID;
		this.vertexCount = vertexCount;
	}


	public int getVaoID() {
		return vaoID;
	}


	public int getVertexCount() {
		return vertexCount;
	}
}


The loader class:
    package engine.io;

    import java.nio.FloatBuffer;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.lwjgl.BufferUtils;
    import org.lwjgl.opengl.GL11;
    import org.lwjgl.opengl.GL15;
    import org.lwjgl.opengl.GL20;
    import org.lwjgl.opengl.GL30;
    import org.lwjgl.system.MemoryUtil;
    
    public class Loader {
    	
	private List<Integer> vaos = new ArrayList<Integer>();
	private List<Integer> vbos = new ArrayList<Integer>();
	
	
	
	public RawModel loadToVAO(float[] positions) {
		int vaoID = createVAO();
		storeDataInAttributeList(0, positions);
		unbindVAO();
		return new RawModel(vaoID, positions.length/3);
	}
	
	private int createVAO() {
		int vaoID = GL30.glGenVertexArrays();
		vaos.add(vaoID);
		GL30.glBindVertexArray(vaoID);
		return vaoID;
	}
	
	private void storeDataInAttributeList(int attributeNumber, float[] data) {
		int vboID = GL15.glGenBuffers();
		vbos.add(vboID);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
		FloatBuffer buffer = storeDataInFloatBuffer(data);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		}
	
	private void unbindVAO() {
		GL30.glBindVertexArray(0);
	}
	
	private FloatBuffer storeDataInFloatBuffer(float[] data) {
		FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
		buffer.put(data);
		buffer.flip();
		return buffer;
	}
	
	public void cleanUp() {
		for (int vao : vaos) {
			GL30.glDeleteVertexArrays(vao);
		}
		for (int vbo : vbos) {
			GL15.glDeleteBuffers(vbo);
		}
	}
}


The renderer class:
        package engine.io;
    
    import org.lwjgl.opengl.GL11;
    import org.lwjgl.opengl.GL15;
    import org.lwjgl.opengl.GL20;
    import org.lwjgl.opengl.GL30;
    
    public class Renderer {
    	

	
	public void prepare() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
		GL11.glClearColor(1f, 0f, 1f, 1f);
	}
	
	public void render(RawModel model) {
		GL30.glBindVertexArray(model.getVaoID());
		GL20.glEnableVertexAttribArray(0);
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
		GL20.glDisableVertexAttribArray(0);
		GL30.glBindVertexArray(0);
	}
}



Here is the Main class:

    import org.lwjgl.*;
    import org.lwjgl.glfw.*;
    import org.lwjgl.opengl.*;
    import org.lwjgl.system.*;

    import engine.io.Loader;
    import engine.io.RawModel;
    import engine.io.Renderer;
    import engine.io.Window;

    import java.nio.*;

    import static org.lwjgl.glfw.Callbacks.*;
    import static org.lwjgl.glfw.GLFW.*;
    import static org.lwjgl.opengl.GL11.*;
    import static org.lwjgl.system.MemoryStack.*;
    import static org.lwjgl.system.MemoryUtil.*;

    public class Main {

	private Window window;
	
	Loader loader = new Loader();
	Renderer renderer = new Renderer();
	
	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
    };
	
	RawModel model;
	

	public void run() {
		setup();
		loop();
		
		loader.cleanUp();

		glfwFreeCallbacks(window.getWindowNum());
		glfwDestroyWindow(window.getWindowNum());
		
		glfwTerminate();
		glfwSetErrorCallback(null).free();
	}

	private void loop() {
		while ( !glfwWindowShouldClose(window.getWindowNum()) ) {
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
			
			renderer.render(model);
			
			glfwSwapBuffers(window.getWindowNum()); // swap the color buffers
			
			glfwPollEvents();
		}
	}

	
	public void setup() {
		window = new Window(900, 300, "Flappy Bird");
		window.create();
		
		GL.createCapabilities();
		GLFW.glfwMakeContextCurrent(window.getWindowNum());

		model = loader.loadToVAO(vertices);
		renderer.prepare();
		
		GL11.glViewport(0, 0, 900, 300);
        
	}
	
	
	public static void main(String[] args) {
		new Main().run();
	}
}
[code]

Here is the window class:


[code]
    package engine.io;

    import static org.lwjgl.glfw.GLFW.*;
    import static org.lwjgl.opengl.GL11.*;
    import static org.lwjgl.system.MemoryStack.stackPush;
    import static org.lwjgl.system.MemoryUtil.*;
    
    import java.nio.IntBuffer;
    
    //import static org.lwjgl.glfw.GLFW.*;
    import org.lwjgl.glfw.GLFW;
    import org.lwjgl.glfw.GLFWErrorCallback;
    import org.lwjgl.glfw.GLFWVidMode;
    import org.lwjgl.system.MemoryStack;

    public class Window {
	private int width, height;
	private String title;
	private long window;

	public Window(int width, int height, String title) {
		this.width = width;
		this.height = height;
		this.title = title;
	}

	public void create() {
		GLFWErrorCallback.createPrint(System.err).set();

		if (!glfwInit())
			throw new IllegalStateException("Unable to initialize GLFW");

		// Configure GLFW
		glfwDefaultWindowHints(); // optional, the current window hints are already the default
		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
		glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

		// Create the window
		window = glfwCreateWindow(width, height, "Flappy Bird", NULL, NULL);
		if (window == NULL)
			throw new RuntimeException("Failed to create the GLFW window");

		// Get the thread stack and push a new frame
		try (MemoryStack stack = stackPush()) {
			IntBuffer pWidth = stack.mallocInt(1); // int*
			IntBuffer pHeight = stack.mallocInt(1); // int*

			// Get the window size passed to glfwCreateWindow
			glfwGetWindowSize(window, pWidth, pHeight);

			// Get the resolution of the primary monitor
			GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

			// Center the window
			glfwSetWindowPos(window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
		} // the stack frame is popped automatically
			// Setup a key callback. It will be called every time a key is pressed, repeated
			// or released.
		glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
			if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
				glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
		});

		// Make the OpenGL context current
		glfwMakeContextCurrent(window);
		// Enable v-sync
		glfwSwapInterval(1);

		// Make the window visible
		glfwShowWindow(window);

	}
	
	
	
	public long getWindowNum() {
		return window;
	}
}

scaventz

Hi,NITAI99

    I ran your code, and the rectangle appeared.