Using OpenGL 2.1 with SDL 2.0: nothing is displayed

Hi there. I’m working with OpenGL 2.1 hardware and would like to use it with SDL 2.0. I can create an OpenGL context but apart the background color set with glClearColor(), nothing is showing up on the screen. If someone can see what is funky about the source below, it would be fantastic.

Most of it is from opengl-tutorial.org. If you want, you can also compile it with gcc using the command ‘g++ -o main main.cpp -lSDL2 -lGL -lGLEW’. Code for the very simple shaders is also included. Interestingly I can draw legacy OpenGL (glBegin/glEnd) stuff on the context just fine.


// main.cpp

#include <SDL2/SDL.h>
#include <GL/glew.h>

#define PROGRAM_NAME "OpenGL stub"

#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <stdlib.h>
#include <string.h>

using namespace std;

GLuint LoadShaders(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::string Line = "";
		while(getline(VertexShaderStream, Line))
			VertexShaderCode += "
" + Line;
		VertexShaderStream.close();
	}else{
		printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !
", 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::string Line = "";
		while(getline(FragmentShaderStream, Line))
			FragmentShaderCode += "
" + Line;
		FragmentShaderStream.close();
	}



	GLint Result = GL_FALSE;
	int InfoLogLength;



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

	// 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
", &VertexShaderErrorMessage[0]);
	}



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

	// 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
", &FragmentShaderErrorMessage[0]);
	}



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

	// 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
", &ProgramErrorMessage[0]);
	}

	glDeleteShader(VertexShaderID);
	glDeleteShader(FragmentShaderID);

	return ProgramID;
}

void CheckSDLErrorAndDie()
{
	const char *error = SDL_GetError();
	if (*error != '\0')
	{
		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
			"Simple DirectMedia Layer Error", SDL_GetError(), NULL);
		SDL_Quit();
		exit(1);
	}
}

// overloaded version: display a custom message
void CheckSDLErrorAndDie(const char *Message)
{
	const char *error = SDL_GetError();
	if (*error != '\0')
	{
		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
			PROGRAM_NAME, Message, NULL);
		SDL_Quit();
		exit(1);
	}
}

void ShowErrorAndDie(const char* Message) {
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, PROGRAM_NAME,
		Message, NULL);

	SDL_Quit();
	exit(1);
}

int main(int argc, char** argv)
{
	SDL_Window *MainWindow;
	SDL_GLContext MainContext;

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		ShowErrorAndDie("Unable to initialize SDL");
	}

	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);

	// 24bit double buffer
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	MainWindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_HIDDEN);
	if (!MainWindow) {
		ShowErrorAndDie("Unable to create window.");
	}

	// Attach the OpenGL context to our window

	MainContext = SDL_GL_CreateContext(MainWindow);
	CheckSDLErrorAndDie("Unable to initialize OpenGL.
Please make sure that your OpenGL driver supports at least version 2.1.");

	SDL_ShowWindow(MainWindow);

	// Enable vsync
	SDL_GL_SetSwapInterval(1);

	if (GLEW_OK != glewInit()) {
		ShowErrorAndDie("The GLEW subsystem failed to initialize.");
		SDL_Quit();
		exit(1);
	}

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

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

	// Get a handle for our buffers
	GLuint vertexPosition_modelspaceID = glGetAttribLocation(programID, "vertexPosition_modelspace");

	static const GLfloat g_vertex_buffer_data[] = { 
		-1.0f, -1.0f, 0.0f,
		 1.0f, -1.0f, 0.0f,
		 0.0f,  1.0f, 0.0f,
	};

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

	// Clear the screen
	glClear( GL_COLOR_BUFFER_BIT );

	// Use our shader
	glUseProgram(programID);

	// 1rst attribute buffer : vertices
	glEnableVertexAttribArray(vertexPosition_modelspaceID);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glVertexAttribPointer(
		vertexPosition_modelspaceID, // The attribute we want to configure
		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

	glDisableVertexAttribArray(vertexPosition_modelspaceID);

	// Swap buffers
	SDL_GL_SwapWindow(MainWindow);

	SDL_Delay(5000);

	// Cleanup VBO
	glDeleteBuffers(1, &vertexbuffer);

	// delete our OpenGL context, destroy window, and shutdown SDL
	SDL_GL_DeleteContext(MainContext);
	SDL_DestroyWindow(MainWindow);
	SDL_Quit();

	return 0;
}

// SimpleFragmentShader.fragmentshader

#version 120

void main()
{

	// Output color = red 
	gl_FragColor = vec4(1,0,0,1);

}


// SimpleVertexShader.vertexshader

#version 120
// Input vertex data, different for all executions of this shader.
attribute vec3 vertexPosition_modelspace;

void main(){

	gl_Position = vec4(vertexPosition_modelspace, 1.0);

}

try enabling vertex array with:
glEnableClientState(GL_VERTEX_ARRAY);

try enabling vertex array with:
glEnableClientState(GL_VERTEX_ARRAY);