Last active
June 7, 2020 13:29
-
-
Save neguse/dc5d04ec65bec7d82d47f0a2a9745637 to your computer and use it in GitHub Desktop.
SDL2+WebGL2でEmscriptenビルド
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
# SDL2+WebGL2でEmscriptenビルドしてみる | |
## ビルド方法 | |
### 今回用意した環境 | |
* Visual Studio 2019 Community | |
* cmake | |
* Emscripten | |
### vcpkgでSDL2をインストール | |
``` | |
vcpkg install --triplet wasm32-emscripten sdl2 | |
``` | |
### プロジェクトの設定 | |
Visual Studioでリポジトリのディレクトリを開くとCMakeSettings.jsonというファイルができる | |
CMakeSettings.jsonを以下のように編集 | |
``` | |
{ | |
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. | |
"configurations": [ | |
{ | |
"name": "x64-Debug", | |
// 元からあるやつはそのまま | |
}, | |
{ | |
"name": "wasm32-Debug", | |
"generator": "Ninja", | |
"configurationType": "Debug", | |
// "inheritEnvironments": [ "msvc_x64_x64" ], | |
"buildRoot": "${projectDir}\\out\\build\\${name}", | |
"installRoot": "${projectDir}\\out\\install\\${name}", | |
"cmakeCommandArgs": "", | |
"buildCommandArgs": "", | |
"ctestCommandArgs": "", | |
"cmakeToolchain": "path/to/Microsoft/vcpkg/scripts/buildsystems/vcpkg.cmake", | |
"variables": [ | |
{ | |
"name": "VCPKG_CHAINLOAD_TOOLCHAIN_FILE", | |
"value": "path/to/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake" | |
}, | |
{ | |
"name": "CMAKE_CROSSCOMPILING_EMULATOR", | |
"value": "path/to/emsdk/node/12.9.1_64bit/bin/node.exe" | |
}, | |
{ | |
"name": "VCPKG_TARGET_TRIPLET", | |
"value": "wasm32-emscripten" | |
} | |
] | |
} | |
``` | |
### ビルドと起動 | |
Visual Studio上のConfigurationを`wasm32-Debug`に切り替えてビルドする。 | |
`out\build\wasm32-Debug`にhtmlファイルができるので、このディレクトリ上で`python -m http.server`のような適当なWebサーバを立ち上げてブラウザからアクセスする。 |
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
cmake_minimum_required(VERSION 3.0.0) | |
project(sdl2webgl2 VERSION 0.1.0) | |
set(CMAKE_CXX_STANDARD 17) | |
set(CMAKE_CXX_STANDARD_REQUIRED ON) | |
set(CMAKE_CXX_EXTENSIONS OFF) | |
find_package(SDL2 CONFIG REQUIRED) | |
file(GLOB_RECURSE sources "*.cpp") | |
add_executable(sdl2webgl2 ${sources}) | |
if (EMSCRIPTEN) | |
set(CMAKE_EXECUTABLE_SUFFIX ".html") | |
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2") | |
endif() | |
target_include_directories(sdl2webgl2 PUBLIC ".") | |
target_link_libraries(sdl2webgl2 PRIVATE SDL2::SDL2main SDL2::SDL2-static) |
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 <stdio.h> | |
#include <algorithm> | |
#include <fstream> | |
#include <iostream> | |
#include <sstream> | |
#include <string> | |
#include <vector> | |
using namespace std; | |
#include <GL/glew.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "shader.hpp" | |
GLuint LoadShaders(const char* vertex_file, const char* fragment_file) { | |
// Create the shaders | |
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); | |
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); | |
GLint Result = GL_FALSE; | |
int InfoLogLength; | |
// Compile Vertex Shader | |
printf("Compiling shader : %s\n", vertex_file); | |
char const* VertexSourcePointer = vertex_file; | |
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); | |
glCompileShader(VertexShaderID); | |
// Check Vertex Shader | |
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); | |
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); | |
if (InfoLogLength > 0) { | |
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1); | |
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, | |
&VertexShaderErrorMessage[0]); | |
printf("%s\n", &VertexShaderErrorMessage[0]); | |
} | |
// Compile Fragment Shader | |
printf("Compiling shader : %s\n", fragment_file); | |
char const* FragmentSourcePointer = fragment_file; | |
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); | |
glCompileShader(FragmentShaderID); | |
// Check Fragment Shader | |
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); | |
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); | |
if (InfoLogLength > 0) { | |
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1); | |
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, | |
&FragmentShaderErrorMessage[0]); | |
printf("%s\n", &FragmentShaderErrorMessage[0]); | |
} | |
// Link the program | |
printf("Linking program\n"); | |
GLuint ProgramID = glCreateProgram(); | |
glAttachShader(ProgramID, VertexShaderID); | |
glAttachShader(ProgramID, FragmentShaderID); | |
glLinkProgram(ProgramID); | |
// Check the program | |
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); | |
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); | |
if (InfoLogLength > 0) { | |
std::vector<char> ProgramErrorMessage(InfoLogLength + 1); | |
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, | |
&ProgramErrorMessage[0]); | |
printf("%s\n", &ProgramErrorMessage[0]); | |
} | |
glDetachShader(ProgramID, VertexShaderID); | |
glDetachShader(ProgramID, FragmentShaderID); | |
glDeleteShader(VertexShaderID); | |
glDeleteShader(FragmentShaderID); | |
return ProgramID; | |
} |
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
#pragma once | |
#include <GLES3/gl3.h> | |
GLuint LoadShaders(const char* vertex_file, const char* fragment_file); |
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 <SDL2/SDL.h> | |
#include <emscripten.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <functional> | |
SDL_Window* window; | |
// Include GLM | |
#include <glm/glm.hpp> | |
using namespace glm; | |
#include <shader.hpp> | |
std::function<void(void)> updater; | |
void main_func() { updater(); } | |
int main(void) { | |
if (SDL_Init(SDL_INIT_VIDEO)) { | |
fprintf(stderr, "Failed to initialize SDL\n"); | |
getchar(); | |
return -1; | |
} | |
// SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); | |
// Open a window and create its OpenGL context | |
window = SDL_CreateWindow(nullptr, SDL_WINDOWPOS_CENTERED, | |
SDL_WINDOWPOS_CENTERED, 1024, 768, | |
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | | |
SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); | |
if (window == NULL) { | |
fprintf(stderr, | |
"Failed to open SDL window. If you have an Intel GPU, they are " | |
"not 3.3 compatible. Try the 2.1 version of the tutorials.\n"); | |
getchar(); | |
return -1; | |
} | |
SDL_GLContext ctx = SDL_GL_CreateContext(window); | |
if (ctx == nullptr) { | |
fprintf(stderr, "Failed to create GL context.\n"); | |
getchar(); | |
return -1; | |
} | |
SDL_GL_MakeCurrent(window, ctx); | |
// Dark blue background | |
glClearColor(0.0f, 0.0f, 0.4f, 0.0f); | |
GLuint VertexArrayID; | |
glGenVertexArrays(1, &VertexArrayID); | |
glBindVertexArray(VertexArrayID); | |
const char* vertex_shader = R"(#version 300 es | |
precision mediump float; | |
// Input vertex data, different for all executions of this shader. | |
layout(location = 0) in vec3 vertexPosition_modelspace; | |
void main(){ | |
gl_Position.xyz = vertexPosition_modelspace; | |
gl_Position.w = 1.0; | |
})"; | |
const char* fragment_shader = R"(#version 300 es | |
precision mediump float; | |
// Ouput data | |
out vec3 color; | |
void main() | |
{ | |
// Output color = red | |
color = vec3(1, 0, 0); | |
})"; | |
// Create and compile our GLSL program from the shaders | |
GLuint programID = LoadShaders(vertex_shader, fragment_shader); | |
static const GLfloat g_vertex_buffer_data[] = { | |
-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, | |
}; | |
GLuint vertexbuffer; | |
glGenBuffers(1, &vertexbuffer); | |
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), | |
g_vertex_buffer_data, GL_STATIC_DRAW); | |
emscripten_set_main_loop(main_func, 0, 0); | |
updater = [&]() { | |
// Clear the screen | |
glClear(GL_COLOR_BUFFER_BIT); | |
// Use our shader | |
glUseProgram(programID); | |
// 1rst attribute buffer : vertices | |
glEnableVertexAttribArray(0); | |
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); | |
glVertexAttribPointer(0, // attribute 0. No particular reason for 0, | |
// but must match the layout in the shader. | |
3, // size | |
GL_FLOAT, // type | |
GL_FALSE, // normalized? | |
0, // stride | |
(void*)0 // array buffer offset | |
); | |
// Draw the triangle ! | |
glDrawArrays(GL_TRIANGLES, 0, | |
3); // 3 indices starting at 0 -> 1 triangle | |
glDisableVertexAttribArray(0); | |
// Swap buffers | |
SDL_GL_SwapWindow(window); | |
}; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment