Created
June 3, 2019 13:39
-
-
Save ousttrue/0f3a11d5d28e365b129fe08f18f4e141 to your computer and use it in GitHub Desktop.
emscripten glfw3 or webgl sample
This file contains hidden or 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
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0) | |
PROJECT(em_gl VERSION 0.1.0) | |
LINK_DIRECTORIES( | |
$ENV{VCPKG_ROOT}/installed/x64-windows/lib | |
) | |
FILE(GLOB SRC | |
*.cpp | |
*.h | |
) | |
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC}) | |
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PUBLIC | |
$ENV{VCPKG_ROOT}/installed/x64-windows/include | |
${CMAKE_CURRENT_LIST_DIR}/../emsdk/fastcomp/emscripten/system/include | |
) | |
TARGET_LINK_LIBRARIES(${PROJECT_NAME} | |
glad | |
glfw3dll | |
) |
This file contains hidden or 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
// emcc main.cpp -o index.html -s USE_WEBGL2=1 -s USE_GLFW=3 -s WASM=1 -std=c++1z | |
// base: https://www.glfw.org/docs/latest/quick.html#quick_example | |
// ref: https://gist.github.com/SuperV1234/5c5ad838fe5fe1bf54f9 | |
#include <functional> | |
#include <vector> | |
#ifdef __EMSCRIPTEN__ | |
#include <emscripten.h> | |
#define GL_GLEXT_PROTOTYPES | |
#define EGL_EGLEXT_PROTOTYPES | |
#else | |
#include <glad/glad.h> | |
#endif | |
#include <GLFW/glfw3.h> | |
#include "linmath.h" | |
#include <stdlib.h> | |
#include <stdio.h> | |
static const struct | |
{ | |
float x, y; | |
float r, g, b; | |
} vertices[3] = | |
{ | |
{-0.6f, -0.4f, 1.f, 0.f, 0.f}, | |
{0.6f, -0.4f, 0.f, 1.f, 0.f}, | |
{0.f, 0.6f, 0.f, 0.f, 1.f}}; | |
static const char *vertex_shader_text = | |
"uniform mat4 MVP;\n" | |
"attribute vec3 vCol;\n" | |
"attribute vec2 vPos;\n" | |
"varying vec3 color;\n" | |
"void main()\n" | |
"{\n" | |
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n" | |
" color = vCol;\n" | |
"}\n"; | |
static const char *fragment_shader_text = | |
"precision mediump float;\n" | |
"varying vec3 color;\n" | |
"void main()\n" | |
"{\n" | |
" gl_FragColor = vec4(color, 1.0);\n" | |
"}\n"; | |
static void error_callback(int error, const char *description) | |
{ | |
fprintf(stderr, "Error: %s\n", description); | |
} | |
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) | |
{ | |
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) | |
glfwSetWindowShouldClose(window, GLFW_TRUE); | |
} | |
std::function<void()> loop; | |
void main_loop() { loop(); } | |
void check_error(GLuint shader) | |
{ | |
GLint result; | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &result); | |
if (result == GL_FALSE) | |
{ | |
GLint log_length; | |
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); | |
std::vector<GLchar> log(log_length); | |
GLsizei length; | |
glGetShaderInfoLog(shader, log.size(), &length, log.data()); | |
error_callback(0, log.data()); | |
} | |
} | |
int main(void) | |
{ | |
GLint mvp_location, vpos_location, vcol_location; | |
glfwSetErrorCallback(error_callback); | |
if (!glfwInit()) | |
exit(EXIT_FAILURE); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | |
auto window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL); | |
if (!window) | |
{ | |
glfwTerminate(); | |
exit(EXIT_FAILURE); | |
} | |
glfwSetKeyCallback(window, key_callback); | |
glfwMakeContextCurrent(window); | |
#ifdef __EMSCRIPTEN__ | |
#else | |
gladLoadGL(); | |
#endif | |
glfwSwapInterval(1); | |
// NOTE: OpenGL error checks have been omitted for brevity | |
GLuint vertex_buffer; | |
glGenBuffers(1, &vertex_buffer); | |
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |
auto vertex_shader = glCreateShader(GL_VERTEX_SHADER); | |
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL); | |
glCompileShader(vertex_shader); | |
check_error(vertex_shader); | |
auto fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); | |
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL); | |
glCompileShader(fragment_shader); | |
check_error(fragment_shader); | |
auto program = glCreateProgram(); | |
glAttachShader(program, vertex_shader); | |
glAttachShader(program, fragment_shader); | |
glLinkProgram(program); | |
mvp_location = glGetUniformLocation(program, "MVP"); | |
vpos_location = glGetAttribLocation(program, "vPos"); | |
vcol_location = glGetAttribLocation(program, "vCol"); | |
glEnableVertexAttribArray(vpos_location); | |
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE, | |
sizeof(vertices[0]), (void *)0); | |
glEnableVertexAttribArray(vcol_location); | |
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE, | |
sizeof(vertices[0]), (void *)(sizeof(float) * 2)); | |
loop = [&] { | |
float ratio; | |
int width, height; | |
mat4x4 m, p, mvp; | |
glfwGetFramebufferSize(window, &width, &height); | |
ratio = width / (float)height; | |
glViewport(0, 0, width, height); | |
glClear(GL_COLOR_BUFFER_BIT); | |
mat4x4_identity(m); | |
mat4x4_rotate_Z(m, m, (float)glfwGetTime()); | |
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f); | |
mat4x4_mul(mvp, p, m); | |
glUseProgram(program); | |
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat *)mvp); | |
glDrawArrays(GL_TRIANGLES, 0, 3); | |
glfwSwapBuffers(window); | |
glfwPollEvents(); | |
}; | |
#ifdef __EMSCRIPTEN__ | |
emscripten_set_main_loop(main_loop, 0, true); | |
#else | |
while (!glfwWindowShouldClose(window)) | |
main_loop(); | |
#endif | |
glfwDestroyWindow(window); | |
glfwTerminate(); | |
exit(EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TBH I never use the "regular"
find_package(glfw3)
as this poorly generalises to Windows, which has no true notion of system-wide installation for dev libraries. Always include glfw as a subdirectory for native builds, it is so lightweight that it is not worth going through the portability trouble offind_package
IMHO.