I'm very confused with VAO and VBO stuff And i need explanation

Started by Kudze, February 15, 2016, 18:18:51

Previous topic - Next topic

Kudze

Hello guys, so I'm working on my game engine. And I came onto these. I'm really confused now how these works.

I want to draw mesh by vertices and faces (Some people call it indices) here's my vertex code (it has texture coords which later i'm going to build shader, because on my new engine i don't have shaders yet, for now i want them to be stored but won't used):

I want to mesh have theirs vao, and for vertex i want give one vbo and for faces (indices) i want give another vbo ;d

package Kudze.Engine.Render.OpenGL.Objects3D;

import Kudze.Engine.Math.Vector2;
import Kudze.Engine.Math.Vector3;

public class Vertex {
	
	public static final int SIZE = 5;
	
	private Vector3 VertexPosition;
	private Vector2 TexturePosition;
	
	public Vertex(Vector3 VertexPosition, Vector2 TexturePosition) {
		this.VertexPosition = VertexPosition;
		this.TexturePosition = TexturePosition;
	}
	
	public void setVertexPosition(Vector3 Position) {
		VertexPosition = Position;
	}
	
	public void setTexturePosition(Vector2 Position) {
		TexturePosition = Position;
	}
	
	public Vector3 getVertexPosition() { return VertexPosition; }
	public Vector2 getTexturePosition() { return TexturePosition; }

}


Ok so there's my mesh code.

package Kudze.Engine.Render.OpenGL.Objects3D;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;

import Kudze.Engine.Render.OpenGL.Util.DataUtil;

public class Mesh {
	
	private int vao; //Pointeris (nevisai) Ã,,¯ vao kuriam yra visi bufferiai.
	private int vbo; //Vertices buffer
	private int fbo; //Faces buffer
	private int size;
	
	public Mesh(Vertex[] vertex, int[] faces) {
		vao = glGenVertexArrays();
		glBindVertexArray(vao);
		
		vbo = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, DataUtil.createFlippedBuffer(vertex), GL_STATIC_DRAW);
		
		fbo = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, fbo);
		glBufferData(GL_ARRAY_BUFFER, DataUtil.createFlippedBuffer(faces), GL_STATIC_DRAW);
		
		glBindVertexArray(0);
		
		size = faces.length;
	}
	
	public void draw() {
		
		System.out.println("Draw");
		
		glBindVertexArray(vao);
		glEnableVertexAttribArray(vao);
		
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glVertexAttribPointer(vao, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
		glVertexAttribPointer(vao, 3, GL_FLOAT, false, Vertex.SIZE * 4, 12);
		
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fbo);
		glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
		
		glDisableVertexAttribArray(vao);
		glBindVertexArray(0);
	}
	
	public void dispose() {
		glDeleteVertexArrays(vao);
		glDeleteBuffers(vbo);
		glDeleteBuffers(fbo);
	}

}


and here's how i test my engine I have glclear screen before drawing in other class and swapbuffers after draw in other class too :)

package Kudze.Amandas.Game;

import Kudze.Engine.Core.Engine;
import Kudze.Engine.Core.Game;
import Kudze.Engine.Math.Vector2;
import Kudze.Engine.Math.Vector3;
import Kudze.Engine.Render.OpenGL.Objects3D.Mesh;
import Kudze.Engine.Render.OpenGL.Objects3D.Vertex;

public class SandBox implements Game {
	
	public static Engine engine;

	@Override
	public void create(Engine engine) {
		SandBox.engine = engine;
		
	}
	
	private Mesh mesh;
	
	@Override
	public void start() {
		
		Vertex[] vertices = { 	new Vertex(new Vector3(-0.5f, -0.5f, 0), new Vector2(0, 0)),
								new Vertex(new Vector3(0, 0.5f, 0), new Vector2(0, 0)),
								new Vertex(new Vector3(0.5f, -0.5f, 0), new Vector2(0, 0))};
		
		int[] indices = {1, 2, 3};
		
		mesh = new Mesh(vertices, indices);
		
		
	}

	@Override
	public void update(double deltaTime) {
		
	}

	@Override
	public void draw() {
		mesh.draw();
	}

	@Override
	public void dispose() {
		mesh.dispose();
	}
}

Kai

Ermm... glVertexAttribPointer's first parameter is NOT the vao handle, but the generic vertex attribute index.
Same for gl[Enable/Disable]VertexAttribArray.
Read the docs about the OpenGL functions you are using.
Also peculiar is why your Vertex has a size of 5 whereas you are using a size of 3 for both vertex attributes. That will crash for granted.

One tip: Just forget about VAOs for the moment and just generate and bind one at the beginning of your program if you must (using OpenGL >= 3.2 core profile), until you learnt what state they exactly capture (read the OpenGL spec about that).
For example: They capture all the vertex specification states and vertex attribute enable states, meaning that your calls to glVertexAttribPointer in 'draw' are redundant as well as your calls to gl[Enable/Disable]VertexAttribArray.

Kudze

Meh, Its so difficult to create simple stuff xd But if i do this without vao. What will happen if i render two meshes?

Kai

What kind of question is that... your computer will explode, of course. :)
Nah, what exactly do you mean? You can bind different VBOs in succession after making a drawcall (glDrawArrays/glDrawElements/glDraw...) each.

Kudze

Oh ok ;d But then if I have unlimited vbo's whats the point of vao?

Kai

The point of a VAO is to reduce the amount of OpenGL calls the client has to make when switching between "models."

Without a VAO you would have to do (for each vertex attribute you have):
- gl[Enable/Disable]VertexAttribArray() (or glEnableClientState(GL_VERTEX_ARRAY/GL_NORMAL_ARRAY/...)... if you used that)
- glBindBuffer(GL_ARRAY_BUFFER)
- glVertexAttribPointer (or glVertexPointer/glNormalPointer/... if you used that)
- glVertexAttribDivisor (if you used instancing)
- ... for a complete list of state stored in a VAO please see the OpenGL spec

and also:
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) (if you used element/index array)

whereas with a VAO you only do the things above once and then only do:
- glBindVertexArray

Cornix

Quote from: Kudze on February 15, 2016, 20:26:26
Oh ok ;d But then if I have unlimited vbo's whats the point of vao?
Think about it like this:
A VAO and a VBO are both used to store information, but both are used to store different kinds of information. You use the VBO to store model data and you use the VAO to store management overhead.
You can do without a VAO and you can do without both VAOs and VBOs (using legacy OpenGL) but you can not render with only a VAO.

Kudze

Ok so for now i'll use vbo's only ok so i have the following: But i still can't see my triangle

package Kudze.Amandas.Game;

import Kudze.Engine.Core.Engine;
import Kudze.Engine.Core.Game;
import Kudze.Engine.Math.Vector2;
import Kudze.Engine.Math.Vector3;
import Kudze.Engine.Render.OpenGL.Objects3D.Mesh;
import Kudze.Engine.Render.OpenGL.Objects3D.Vertex;

public class SandBox implements Game {
	
	public static Engine engine;

	@Override
	public void create(Engine engine) {
		SandBox.engine = engine;
		
	}
	
	private Mesh mesh;
	
	@Override
	public void start() {
		
		Vertex[] vertices = { 	new Vertex(new Vector3(-0.5f, -0.5f, 0), new Vector2(0, 0)),
								new Vertex(new Vector3(0, 0.5f, 0), new Vector2(0, 0)),
								new Vertex(new Vector3(0.5f, -0.5f, 0), new Vector2(0, 0))};
		
		int[] indices = {0, 1, 2};
		
		mesh = new Mesh(vertices, indices);
		
		
	}

	@Override
	public void update(double deltaTime) {
		
	}

	@Override
	public void draw() { //It clears screen and displays in other class no worries here
		mesh.draw();
	}

	@Override
	public void dispose() {
		mesh.dispose();
	}
}


package Kudze.Engine.Render.OpenGL.Objects3D;

import Kudze.Engine.Math.Vector2;
import Kudze.Engine.Math.Vector3;

public class Vertex {
	
	public static final int SIZE = 5;
	
	private Vector3 VertexPosition;
	private Vector2 TexturePosition;
	
	public Vertex(Vector3 VertexPosition, Vector2 TexturePosition) {
		this.VertexPosition = VertexPosition;
		this.TexturePosition = TexturePosition;
	}
	
	public void setVertexPosition(Vector3 Position) {
		VertexPosition = Position;
	}
	
	public void setTexturePosition(Vector2 Position) {
		TexturePosition = Position;
	}
	
	public Vector3 getVertexPosition() { return VertexPosition; }
	public Vector2 getTexturePosition() { return TexturePosition; }

}


package Kudze.Engine.Render.OpenGL.Objects3D;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;

import Kudze.Engine.Render.OpenGL.Util.DataUtil;

public class Mesh {
	
	private int vbo; //Vertices buffer
	private int fbo; //Faces buffer
	private int size;
	
	public Mesh(Vertex[] vertex, int[] faces) {
		vbo = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, DataUtil.createFlippedBuffer(vertex), GL_STATIC_DRAW);
		
		fbo = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, fbo);
		glBufferData(GL_ARRAY_BUFFER, DataUtil.createFlippedBuffer(faces), GL_STATIC_DRAW);
		size = faces.length;
	}
	
	public void draw() {
		glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
		
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
		glVertexAttribPointer(1, 3, GL_FLOAT, false, Vertex.SIZE * 4, 12);
		
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fbo);
		glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
		
		glDisableVertexAttribArray(0);
		glDisableVertexAttribArray(1);
		
	}
	
	public void dispose() {
		glDeleteBuffers(vbo);
		glDeleteBuffers(fbo);
	}

}

Kudze

And i found this video https://www.youtube.com/watch?v=WMiggUPst-Q Mby i should redo my mesh and vertex system like he did in this video?

Kai

To be honest: You are not going to learn this overnight.
What you should do is take your time, do some good old Google research on "OpenGL VBO" and then read the first ten hits found, which are all excellent articles. And then do alot of trying out things yourself paired with more research/reading/studying.
Granted, this will take time, but OpenGL is a very complex and complicated API with alot of things that can be done in a hundred different ways affecting different other things and alot of implicit state to keep in mind.
You will not learn much from a single YouTube video.
Happy learning! :)

Kudze

Allright, but could you please fix my error that i don't see triangle i want just to test it :D