glDrawElements

Started by awesomelemonade, April 06, 2015, 19:59:43

Previous topic - Next topic

awesomelemonade

I've been recently trying to experiment with OpenGL 3+ and came across the tutorials made by thinmatrix on youtube.

I'm currently experimenting with his code, but not entirely copying it. I ran into a problem:

package lemon.engine.dev;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import lemon.render.RawModel;

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.system.MemoryUtil;

public class Test {
	public static void main(String[] args){
		GLFW.glfwInit();
		GLFW.glfwDefaultWindowHints();
		GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL11.GL_FALSE);
		GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GL11.GL_FALSE);
		long window = GLFW.glfwCreateWindow(800, 600, "Test", MemoryUtil.NULL, MemoryUtil.NULL);
		GLFW.glfwMakeContextCurrent(window);
		GLFW.glfwShowWindow(window);
		GLContext.createFromCurrent();
		
		float[] vertices = {
				-0.5f, 0.5f, 0f,
				-0.5f, -0.5f, 0f,
				0.5f, -0.5f, 0f,
				0.5f, 0.5f, 0f
		};
		FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
		verticesBuffer.put(vertices);
		verticesBuffer.flip();
		int[] indices = {
				0, 1, 3,
				3, 1, 2
		};
		IntBuffer indicesBuffer = BufferUtils.createIntBuffer(indices.length);
		indicesBuffer.put(indices);
		indicesBuffer.flip();
		
		RawModel model = new RawModel(indices.length);
		model.loadVboIndices(indicesBuffer);
		model.loadVboVertices(0, verticesBuffer);
		
		while(GLFW.glfwWindowShouldClose(window)!=GL11.GL_TRUE){
			GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
			
			model.render();
			
			GLFW.glfwSwapBuffers(window);
			GLFW.glfwPollEvents();
		}
		model.cleanUp();
		GLFW.glfwDestroyWindow(window);
		GLFW.glfwTerminate();
	}
}


package lemon.render;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

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

public class RawModel {
	private int vaoId;
	private List<Integer> vboIds;
	private int vertexCount;
	
	public RawModel(int vertexCount){
		vboIds = new ArrayList<Integer>();
		vaoId = GL30.glGenVertexArrays();
		this.vertexCount = vertexCount;
	}
	public void loadVboVertices(int attributeNumber, FloatBuffer data){
		GL30.glBindVertexArray(vaoId);
		int vboId = GL15.glGenBuffers();
		vboIds.add(vboId);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		GL30.glBindVertexArray(0);
	}
	public void loadVboIndices(IntBuffer data){
		GL30.glBindVertexArray(vaoId);
		int vboId = GL15.glGenBuffers();
		vboIds.add(vboId);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboId);
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
		GL30.glBindVertexArray(0);
	}
	public void render(){
		GL30.glBindVertexArray(vaoId);
		GL20.glEnableVertexAttribArray(0);
		GL11.glDrawElements(GL11.GL_TRIANGLES, vertexCount, GL11.GL_UNSIGNED_INT, 0);
		GL20.glDisableVertexAttribArray(0);
		GL30.glBindVertexArray(0);
	}
	public void cleanUp(){
		GL30.glDeleteVertexArrays(vaoId);
		for(int vboId: vboIds){
			GL15.glDeleteBuffers(vboId);
		}
	}
	public int getVaoId(){
		return vaoId;
	}
	public int getVertexCount(){
		return vertexCount;
	}
}


This throws an EXCEPTION_ACCESS_VIOLATION in glDrawElements.... Why is that?

Thanks in advanced.

Kai

Simple: You are unbinding the element buffer in your second code listing in line 39.
This results in no element buffer being bound when render() is called and the last argument 0 of glDrawElements is not treated as an offset anymore but rather as the address of the host-side memory storing the elements. Therefore dereferencing of zero -> crash! :)
You can keep the element buffer bound (delete line 39 of second listing), as the element buffer is part of the state stored in the VAO as stated by https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt and the OpenGL 2.1 spec (table 6.8 ).
Therefore: unbinding the VAO also unbinds/resets the element buffer binding.

EDIT: Additional tip: Vertex array enabling (glEnableVertexAttribArray/glDisableVertexAttribArray) is also stored as part of the state of a VAO. So you can once glEnableVertexAttribArray(attributeNumber) in loadVboVertices(), where you know the array index you want to use (which is the attributeNumber parameter, and which is the same as the first argument to glVertexAttribPointer).
Then you can delete line 44 and 46 in your second listing.

awesomelemonade

Sorry for not replying earlier! I have to thank you very much for solving and explaining my problem!


Again! Thanks :)