Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created October 10, 2015 11:07
Show Gist options
  • Star 46 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save vittorioromeo/5c5ad838fe5fe1bf54f9 to your computer and use it in GitHub Desktop.
Save vittorioromeo/5c5ad838fe5fe1bf54f9 to your computer and use it in GitHub Desktop.
SDL2 + OpenGL ES 2.0 - "Hello triangle" example that works both on X11 and Emscripten
#include <exception>
#include <functional>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#define GL_GLEXT_PROTOTYPES 1
#include <SDL_opengles2.h>
#else
#include <SDL2/SDL.h>
#define GL_GLEXT_PROTOTYPES 1
#include <SDL2/SDL_opengles2.h>
#endif
// Shader sources
const GLchar* vertexSource =
"attribute vec4 position; \n"
"void main() \n"
"{ \n"
" gl_Position = vec4(position.xyz, 1.0); \n"
"} \n";
const GLchar* fragmentSource =
"precision mediump float;\n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0 );\n"
"} \n";
std::function<void()> loop;
void main_loop() { loop(); }
int main(int argc, char** argv)
{
// SDL_Init(SDL_INIT_VIDEO);
auto wnd(
SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN));
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetSwapInterval(0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
auto glc = SDL_GL_CreateContext(wnd);
auto rdr = SDL_CreateRenderer(
wnd, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
// Create Vertex Array Object
GLuint vao;
glGenVertexArraysOES(1, &vao);
glBindVertexArrayOES(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {0.0f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
// glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
loop = [&]
{
SDL_Event e;
while(SDL_PollEvent(&e))
{
if(e.type == SDL_QUIT) std::terminate();
}
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a triangle from the 3 vertices
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(wnd);
};
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(main_loop, 0, true);
#else
while(true) main_loop();
#endif
return 0;
}
@rowend36
Copy link

rowend36 commented Nov 1, 2017

Whenever you feel like it, come over to my place for a treat. You've really helped me out. I had to comment out the vertex ary objects though since my vendor doesnt support that.But still, thanks a lot.

@makoConstruct
Copy link

Any idea why I'd be getting this compilation error?

» clang++ --std=c++14 -Wreturn-type -g -O0 -D_GLIBCXX_DEBUG -DCXXPOOL_ENABLE_THREAD_AFFINITIES `sdl2-config  --cflags --libs` -lGLESv2 -lEGL ./hello_triangle.cpp -lpthread -lstdc++fs -o hello_triangle
/tmp/hello_triangle-263b5f.o: In function `main':
/home/mako/programming/toying/./hello_triangle.cpp:62: undefined reference to `glGenVertexArraysOES'
/home/mako/programming/toying/./hello_triangle.cpp:63: undefined reference to `glBindVertexArrayOES'

@makoConstruct
Copy link

I found out. At least in sdl2.0.8 Those functions will only be defined if _MSC_VER is defined, which means it only works on windows.

@Grumbel
Copy link

Grumbel commented Sep 5, 2018

To get this to work I had to remove:

"precision mediump float;\n"

and

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

@raulfpl
Copy link

raulfpl commented Oct 5, 2018

SDL_GL_SetAttribute calls should come before SDL_CreateWindow.
SDL2 documentation for SDL_GL_SetAttribute says:

Use this function to set an OpenGL window attribute before window creation.

One problem I noticed is that if you call SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); before SDL_CreateWindow on Android it will make you lose OpenGL ES context when your window loses focus. Then, when you get back to the app, nothing will be drawn on the screen as all opengl calls will fail because you have no valid context. (At least that was what happened on my device until I moved those calls to before SDL_CreateWindow or removed the line SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

@pinguin999
Copy link

Thanks for your nice example. It helped us a lot to get https://github.com/jhasse/jngl running with emscripten.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment