Skip to content

Instantly share code, notes, and snippets.

@jgranick
Last active June 3, 2019 14:19
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jgranick/5430948 to your computer and use it in GitHub Desktop.
Save jgranick/5430948 to your computer and use it in GitHub Desktop.
SimpleGL
SetOutputFilter DEFLATE
emcc -o SimpleGL.js SimpleGL.cpp SDLStage.cpp -s FULL_ES2=1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1, IE=edge">
<title>SimpleGL</title>
</head>
<body style="padding: 0; margin: 0; background-color: #FFFFFF;">
<canvas id="canvas" width="640" height="480" />
<script type="text/javascript">
var Module = {};
Module.canvas = document.getElementById('canvas');
</script>
<script type="text/javascript" src="./SimpleGL.js"></script>
</body>
</html>
#include "SDLStage.h"
SDLStage::SDLStage (int width, int height, int frameRate, int flags) {
if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == 0) {
screen = SDL_SetVideoMode (width, height, 0, flags);
if (screen != NULL) {
previousTime = 0;
ticksPerFrame = (int)(1000 / frameRate);
active = true;
paused = false;
} else {
cerr << "Could not set video mode: " << SDL_GetError () << endl;
}
} else {
cerr << "Could not initialize SDL: " << SDL_GetError () << endl;
}
}
SDLStage::~SDLStage () {
SDL_Quit ();
}
void SDLStage::handleEvent (SDL_Event &event) {
switch (event.type) {
case SDL_ACTIVEEVENT:
if (event.active.state & SDL_APPACTIVE) {
if (event.active.gain == 0) {
//paused = true;
} else {
//paused = false;
}
}
break;
case SDL_VIDEOEXPOSE:
render ();
break;
case SDL_QUIT:
active = false;
break;
}
if (eventListener != NULL) {
(*eventListener) (event);
}
event.type = -1;
}
void SDLStage::render () {
if (renderCallback != NULL) {
(*renderCallback) (screen);
}
}
void SDLStage::setCaption (string title) {
if (active) {
SDL_WM_SetCaption (title.c_str (), title.c_str ());
}
}
void SDLStage::setEventListener (void (*listener) (SDL_Event&)) {
eventListener = listener;
}
void SDLStage::setRenderCallback (void (*callback) (SDL_Surface*)) {
renderCallback = callback;
}
void SDLStage::setUpdateCallback (void (*callback) (int)) {
updateCallback = callback;
}
void SDLStage::step () {
SDL_Event event;
#ifndef EMSCRIPTEN
if (paused) {
if (SDL_WaitEvent (&event)) {
handleEvent (event);
}
} else {
#endif
while (SDL_PollEvent (&event)) {
handleEvent (event);
if (!active) {
break;
}
}
if (active) {
int currentTime = SDL_GetTicks ();
int deltaTime = currentTime - previousTime;
update (currentTime - previousTime);
render ();
#ifndef EMSCRIPTEN
while (deltaTime < ticksPerFrame) {
SDL_TimerID timer = SDL_AddTimer (ticksPerFrame - deltaTime, timer_onComplete, NULL);
SDL_WaitEvent (&event);
SDL_RemoveTimer (timer);
if (event.type != SDL_USEREVENT) {
handleEvent (event);
deltaTime = SDL_GetTicks () - previousTime;
} else {
event.type = -1;
break;
}
}
#endif
previousTime = currentTime;
}
#ifndef EMSCRIPTEN
}
#endif
}
void SDLStage::update (int deltaTime) {
if (updateCallback != NULL) {
(*updateCallback) (deltaTime);
}
}
// Event Handlers
Uint32 timer_onComplete (Uint32 interval, void *param) {
SDL_Event event;
SDL_UserEvent userevent;
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = NULL;
userevent.data2 = NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent (&event);
return 0;
}
#ifndef SDLSTAGE_H
#define SDLSTAGE_H
#include <iostream>
#include <string>
#include "SDL/SDL.h"
using namespace std;
class SDLStage {
public:
SDLStage (int width, int height, int frameRate, int flags);
~SDLStage ();
bool active;
void setCaption (string title);
void setEventListener (void (*listener) (SDL_Event&));
void setRenderCallback (void (*callback) (SDL_Surface*));
void setUpdateCallback (void (*callback) (int));
void step ();
private:
void (*eventListener) (SDL_Event&);
bool paused;
int previousTime;
void (*renderCallback) (SDL_Surface*);
SDL_Surface* screen;
int ticksPerFrame;
void (*updateCallback) (int);
void handleEvent (SDL_Event &event);
void render ();
void update (int deltaTime);
};
Uint32 timer_onComplete (Uint32 interval, void *param);
#endif
#include <SDL/SDL_image.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include "SDLStage.h"
#ifdef EMSCRIPTEN
#include <emscripten.h>
#endif
GLuint programObject;
SDLStage* stage;
void handleEvent (SDL_Event &event) {
}
GLuint loadShader (GLenum type, const char *source) {
GLuint shader;
GLint compiled;
shader = glCreateShader (type);
if (shader == 0) {
cerr << "Error creating shader" << endl;
return 0;
}
glShaderSource (shader, 1, &source, NULL);
glCompileShader (shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*) malloc (sizeof (char) * infoLen);
glGetShaderInfoLog (shader, infoLen, NULL, infoLog);
cerr << "Error compiling shader: " << infoLog << endl;
free (infoLog);
}
glDeleteShader (shader);
return 0;
}
return shader;
}
int initOpenGL () {
const char vertexShaderString[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
const char fragmentShaderString[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLint linked;
vertexShader = loadShader (GL_VERTEX_SHADER, vertexShaderString);
fragmentShader = loadShader (GL_FRAGMENT_SHADER, fragmentShaderString);
programObject = glCreateProgram ();
if (programObject == 0) {
cerr << "Could not create OpenGL program" << endl;
return 0;
}
glAttachShader (programObject, vertexShader);
glAttachShader (programObject, fragmentShader);
glBindAttribLocation (programObject, 0, "vPosition");
glLinkProgram (programObject);
glGetProgramiv (programObject, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv (programObject, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*) malloc (sizeof (char) * infoLen);
glGetProgramInfoLog (programObject, infoLen, NULL, infoLog);
cerr << "Error linking program: " << infoLog << endl;
free (infoLog);
}
glDeleteProgram (programObject);
return 0;
}
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
return 1;
}
void render (SDL_Surface *screen) {
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
glViewport (0, 0, screen -> w, screen -> h);
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glClear (GL_COLOR_BUFFER_BIT);
glUseProgram (programObject);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray (0);
glDrawArrays (GL_TRIANGLES, 0, 3);
SDL_GL_SwapBuffers ();
}
void update (int deltaTime) {
}
void step () {
stage -> step ();
}
int main (int argc, char** argv) {
stage = new SDLStage (640, 480, 30, SDL_OPENGL);
if (!initOpenGL ()) {
cerr << "Error initializing OpenGL" << endl;
return 1;
}
stage -> setCaption ("SimpleGL");
stage -> setEventListener (&handleEvent);
stage -> setRenderCallback (&render);
stage -> setUpdateCallback (&update);
#ifdef EMSCRIPTEN
emscripten_set_main_loop (step, 30, true);
#else
while (stage -> active) {
step ();
}
#endif
delete stage;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment