Simple openGL triangle


I wanted use OpenGL calls into an OF app by following this tutorial.
Main purpose is to learn to use both OpenGL calls and OF calls if needed. Well, the example is very simple but i didn’t manage to get a simple triangle working.

I have seen this post:

It discusses a similar issue, but in my case i don’t think it is related to coordinate system since bypassing OF calls.

I must be missing something very basic, but for now i only see a blue screen.
What am I missing?

This is my currrent code:

#include "ofMain.h"
#include "ofApp.h"

int main( ){
	ofGLWindowSettings settings;
	settings.setGLVersion(3, 3); /// < select your GL Version here
	ofCreateWindow(settings); ///< create your window here
	ofRunApp(new ofApp());


#include "ofApp.h"

void ofApp::setup(){

	// Create and compile our GLSL program from the shaders
	programID = LoadShader("SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader");

void ofApp::update(){


void ofApp::draw(){

	// Dark blue background
	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

	glGenVertexArrays(1, &VertexArrayID);

	static const GLfloat vertices[] = {
		-1.0f, -1.0f, 0.0f,
		1.0f, -1.0f, 0.0f,
		0.0f,  1.0f, 0.0f,

	glGenBuffers(1, &vertexbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// Clear the screen

	// Use our shader

	// 1rst attribute buffer : vertices
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

 		0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
 		3,                  // size
 		GL_FLOAT,           // type
 		GL_FALSE,           // normalized?
 		0,                  // stride
 		(void*)0            // array buffer offset

	// Draw the triangle !
	glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle

void ofApp::exit()
	// Cleanup VBO
 	glDeleteBuffers(1, &vertexbuffer);
 	glDeleteVertexArrays(1, &VertexArrayID);


#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{

		void setup();
		void update();
		void draw();
		void exit();

		GLuint VertexArrayID;
		// This will identify our vertex buffer
		GLuint vertexbuffer;
		// the shader program
		GLuint programID;

		GLuint LoadShader(const char * vertex_file_path, const char * fragment_file_path) {

			// Create the shaders
			GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
			GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

			// Read the Vertex Shader code from the file
			std::string VertexShaderCode;
			std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
			if (VertexShaderStream.is_open()) {
				std::stringstream sstr;
				sstr << VertexShaderStream.rdbuf();
				VertexShaderCode = sstr.str();
			else {
				printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
				return 0;

			// Read the Fragment Shader code from the file
			std::string FragmentShaderCode;
			std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
			if (FragmentShaderStream.is_open()) {
				std::stringstream sstr;
				sstr << FragmentShaderStream.rdbuf();
				FragmentShaderCode = sstr.str();

			GLint Result = GL_FALSE;
			int InfoLogLength;

			// Compile Vertex Shader
			printf("Compiling shader : %s\n", vertex_file_path);
			char const * VertexSourcePointer = VertexShaderCode.c_str();
			glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);

			// Check Vertex Shader
			glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
			glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
			if (InfoLogLength > 0) {
				std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
				glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
				printf("%s\n", &VertexShaderErrorMessage[0]);

			// Compile Fragment Shader
			printf("Compiling shader : %s\n", fragment_file_path);
			char const * FragmentSourcePointer = FragmentShaderCode.c_str();
			glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);

			// Check Fragment Shader
			glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
			glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
			if (InfoLogLength > 0) {
				std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
				glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
				printf("%s\n", &FragmentShaderErrorMessage[0]);

			// Link the program
			printf("Linking program\n");
			GLuint ProgramID = glCreateProgram();
			glAttachShader(ProgramID, VertexShaderID);
			glAttachShader(ProgramID, FragmentShaderID);

			// Check the program
			glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
			glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
			if (InfoLogLength > 0) {
				std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
				glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
				printf("%s\n", &ProgramErrorMessage[0]);

			glDetachShader(ProgramID, VertexShaderID);
			glDetachShader(ProgramID, FragmentShaderID);


			return ProgramID;

Hi. At
the Stride for glVertexAttribPointer is 3 * sizeof(float) instead of 0. Does that make a difference? What’s in the shader files?


Thank you very much for looking into this. It didn’t work out, but the reference you provided is very helpful. I will read it carefully and see if anything lights up.


Did you ever figure this out? I’ve just started with OF and opengl and I am hitting this same hurtle where glDrawArrays and programmable shaders seem mutually exclusive.

Oddly, it seems like the programmable shader setting in the main() method doesn’t cause glDrawArrays to stop working if the GL version is set to 2.1, however, this does not let the shader files load, so you still either have to choose between custom shaders or using glDrawArrays.

Hi, OF abstracts out the renderers so you dont need to deal with all this kinda hurdle.
Don’t code this way.
ofMesh, ofVboMesh and ofShader provide all the functionalities needed but abstracted from GL (which allows you to seamlessly switch from one renderer to another)