Skip to content

Instantly share code, notes, and snippets.

@ousttrue
Created June 3, 2019 13:39
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ousttrue/0f3a11d5d28e365b129fe08f18f4e141 to your computer and use it in GitHub Desktop.
Save ousttrue/0f3a11d5d28e365b129fe08f18f4e141 to your computer and use it in GitHub Desktop.
emscripten glfw3 or webgl sample
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
)
// 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);
}
@DeafMan1983
Copy link

Wow I never see glfw3 for WASM??? I don't know before but glfm is already for wasm now glfw3 why did writer not say about glfw3 into wasm? But I am using Ubuntu 22.04 - I hate Windows-Spreader! because many hackers use Windows 10....

Please do not tell nonsense me! I will know how do I compile glfw3 under vcpkg with wasm32-emscripten.

Thanks!

@eliemichel
Copy link

eliemichel commented Feb 26, 2023

FTR emscripten ships with its own version of glfw, so no need to worry about compiling it to wasm. To link against it add the -sUSE_GLFW=3 option to the link:

if (EMSCRIPTEN)
    target_link_options(${PROJECT_NAME} PRIVATE -sUSE_GLFW=3)
endif (EMSCRIPTEN)

@Mizux
Copy link

Mizux commented Sep 18, 2023

FTR emscripten ships with its own version of glfw, so no need to worry about compiling it to wasm. To link against it add the -sUSE_GLFW=3 option to the link:

if (EMSCRIPTEN)
    target_link_options(${PROJECT_NAME} PRIVATE -sUSE_GLFW=3)
endif (EMSCRIPTEN)

I think you can use the regular find_package(glfw3) which should pick the pkgconfig glw3.pc which should provide the link option IMHO (warning not tested)
ref: https://github.com/emscripten-core/emscripten/blob/0be5b609412d5b07f8157528df8e5088dae84858/system/lib/pkgconfig/glfw3.pc#L4C11-L4C11

@eliemichel
Copy link

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 of find_package IMHO.

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