glGenVertexArrays();

So I am working through the tutorials here: http://arcsynthesis.org/gltut/Basics/Tut01%20Making%20Shaders.html, and I don’t fully understand something. Here is the lwjgl port which someone posted in another thread someplace.

package rosick.mckesson.I.tut01;

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 static org.lwjgl.opengl.GL32.*;

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

import org.lwjgl.BufferUtils;

import rosick.LWJGLWindow;


/**
 * Visit https://github.com/rosickteam/OpenGL for project info, updates and license terms.
 * 
 * I. The Basics
 * Chapter 1. Hello, Triangle! 
 * http://www.arcsynthesis.org/gltut/Basics/Tutorial%2001.html
 * @author integeruser
 */
public class HelloTriangle01 extends LWJGLWindow {
	
	public static void main(String[] args) {
		new HelloTriangle01().start();
	}

	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	private final float vertexPositions[] = {
			0.75f,  0.75f, 0.0f, 1.0f,
			0.75f, -0.75f, 0.0f, 1.0f,
		   -0.75f, -0.75f, 0.0f, 1.0f
	};

	private final String strVertexShader = 
			"#version 330 \n" +
					"\n" +
					"layout(location = 0) in vec4 position;\n" +
					"void main()\n" +
					"{\n" +
					"    gl_Position = position;\n" +
					"}";

	private final String strFragmentShader = 
			"#version 330\n" +
					"\n" +
					"out vec4 outputCol;\n" +
					"void main()\n" +
					"{\n" +
					"   outputCol = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n" +
					"}";
		
	private int theProgram;
	private int positionBufferObject;
	private int vao;

	

	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	private void initializeProgram() {	
		ArrayList<Integer> shaderList = new ArrayList<>();
		shaderList.add(createShader(GL_VERTEX_SHADER,	strVertexShader));
		shaderList.add(createShader(GL_FRAGMENT_SHADER,	strFragmentShader));

		theProgram = createProgram(shaderList);
		
	    for (Integer shader : shaderList) {
	    	glDeleteShader(shader);
		}
	}
	
	private void initializeVertexBuffer() {
		FloatBuffer vertexPositionsBuffer = BufferUtils.createFloatBuffer(vertexPositions.length);
		vertexPositionsBuffer.put(vertexPositions);
		vertexPositionsBuffer.flip();
        
		positionBufferObject = glGenBuffers();       
		glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
	    glBufferData(GL_ARRAY_BUFFER, vertexPositionsBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

	
	@Override
	protected void init() {
		initializeProgram();
		initializeVertexBuffer(); 

		vao = glGenVertexArrays();
		glBindVertexArray(vao);
	}
	
		
	@Override
	protected void display() {	
		glClearColor(0f, 0f, 0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		glUseProgram(theProgram);

		glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);

		glDrawArrays(GL_TRIANGLES, 0, 3);

		glDisableVertexAttribArray(0);
		glUseProgram(0);
	}
	
	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	private int createShader(int eShaderType, String strShaderFile) {
        int shader = glCreateShader(eShaderType);
        glShaderSource(shader, strShaderFile);

        glCompileShader(shader);

        int status = glGetShader(shader, GL_COMPILE_STATUS);
        if (status == 0) {
    		int infoLogLength = glGetShader(shader, GL_INFO_LOG_LENGTH);

    		String strInfoLog = glGetShaderInfoLog(shader, infoLogLength);

    		String strShaderType = null;
			switch (eShaderType) {
			case GL_VERTEX_SHADER:
				strShaderType = "vertex";
				break;
			case GL_GEOMETRY_SHADER:
				strShaderType = "geometry";
				break;
			case GL_FRAGMENT_SHADER:
				strShaderType = "fragment";
				break;
			}

    		System.err.printf("Compile failure in %s shader:\n%s\n", strShaderType, strInfoLog);
        }
        
		return shader;
	}
	
	
	private int createProgram(ArrayList<Integer> shaderList) {		
		int program = glCreateProgram();

		for (Integer shader : shaderList) {
			glAttachShader(program, shader);
		}

		glLinkProgram(program);
		
		int status = glGetProgram(program, GL_LINK_STATUS);
		if (status == 0) {
			int infoLogLength = glGetProgram(program, GL_INFO_LOG_LENGTH);

			String strInfoLog = null;
			strInfoLog = glGetProgramInfoLog(program, infoLogLength);
			
			System.err.printf("Linker failure: %s\n", strInfoLog);
		}
		
		for (Integer shader : shaderList) {
			glDetachShader(program, shader);
		}

		return program;
	}
}

I understand what everything does except for this one bit of code:

		vao = glGenVertexArrays();
		glBindVertexArray(vao);

I don’t see “vao” referenced anywhere else in the program and when I comment these lines out the program still runs perfectly fine. Can anyone either help me understand this or point me in the right direction. I have been looking on google and whatnot for quite some time and still don’t really see what’s going on.

Thanks!

A Vertex Array Object stores the three method calls before your glDrawArrays call. The proper use is to call these once after creating the VAO, then bind it just before glDrawArrays. You’re currently using a hack to make vertex attributes work like in OGL 2. It’s not possible to render without a VAO with OGL 3 (well, it is with the combatility profile…). By creating a VAO and binding it at program start, you’re hacking around this restriction.

Thank you for your reply. I think I understand now what I am supposed to do. When I change the code to look like this:

@Override
   protected void init() {
      initializeProgram();
      initializeVertexBuffer(); 

      vao = glGenVertexArrays();
      glBindVertexArray(vao);

      glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
      glEnableVertexAttribArray(0);
      glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
      glDisableVertexAttribArray(0);
      glBindVertexArray(0);

      glClearColor(0f, 0f, 0f, 1.0f);
   }
   
      
   @Override
   protected void display() {   
      glClear(GL_COLOR_BUFFER_BIT);

      glUseProgram(theProgram);

      glBindVertexArray(vao);

      glDrawArrays(GL_TRIANGLES, 0, 3);

      glBindVertexArray(0);

      glUseProgram(0);
   }

Now I get nothing but a black screen. Is this the right idea or am I still off? Thanks again!

Remove the glDisableVertexAttribArray(0); and it’ll work. You might want to query the attribute location in the shader though.

Congratulations on being reasonable and using OpenGL 3! ;D

Hooray! It works like a charm. ;D Thanks again for your help.

No problem. If you need any more help with OpenGL 3 I´d be glad to help out. :wink:

Thank you very much. I’m sure I will have more questions at some point. :emo: :stuck_out_tongue: