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);
}