Last active
November 2, 2023 18:28
-
-
Save devappd/01ee73ad8bb0e157533c5d0f047a6eb9 to your computer and use it in GitHub Desktop.
Minimal OpenGL Emscripten example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mkdir -p bin | |
emcc -o bin/main.html main.cpp -s USE_SDL=2 -s FULL_ES2=1 -s SINGLE_FILE=1 | |
emcc -o bin/main-asyncify.html main.cpp -s USE_SDL=2 -s FULL_ES2=1 -s ASYNCIFY=1 -s SINGLE_FILE=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <exception> | |
#include <functional> | |
#define GL_GLEXT_PROTOTYPES 1 | |
#include <emscripten.h> | |
#include <SDL/SDL.h> | |
#include <SDL_opengles2.h> | |
// Shader sources | |
const GLchar* vertexSource = | |
"attribute vec4 position; \n" | |
"varying vec3 color; \n" | |
"void main() \n" | |
"{ \n" | |
" gl_Position = vec4(position.xyz, 1.0); \n" | |
" color = gl_Position.xyz + vec3(0.5); \n" | |
"} \n"; | |
// Fragment/pixel shader | |
const GLchar* fragmentSource = | |
"precision mediump float; \n" | |
"varying vec3 color; \n" | |
"void main() \n" | |
"{ \n" | |
" gl_FragColor = vec4 ( color, 1.0 ); \n" | |
"} \n"; | |
std::function<void()> loop; | |
void main_loop() { loop(); } | |
int main(int argc, char** argv) | |
{ | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); | |
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); | |
auto wnd( | |
SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, | |
640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN)); | |
auto glc = SDL_GL_CreateContext(wnd); | |
SDL_GL_SetSwapInterval(0); | |
auto rdr = SDL_CreateRenderer( | |
wnd, -1, SDL_RENDERER_ACCELERATED); | |
// 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); | |
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment