Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port to run Craft in web browser using Emscripten #175

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,42 @@ project(craft)

FILE(GLOB SOURCE_FILES src/*.c)

add_executable(
craft
${SOURCE_FILES}
deps/glew/src/glew.c
deps/lodepng/lodepng.c
deps/noise/noise.c
deps/sqlite/sqlite3.c
deps/tinycthread/tinycthread.c)
if (EMSCRIPTEN)
add_executable(
craft
${SOURCE_FILES}
#deps/glew/src/glew.c
deps/lodepng/lodepng.c
deps/noise/noise.c
deps/sqlite/sqlite3.c
deps/tinycthread/tinycthread.c)
# Generate HTML file wrapper in addition to .js
set(CMAKE_EXECUTABLE_SUFFIX ".html")
else ()
add_executable(
craft
${SOURCE_FILES}
deps/glew/src/glew.c
deps/lodepng/lodepng.c
deps/noise/noise.c
deps/sqlite/sqlite3.c
deps/tinycthread/tinycthread.c)
endif ()

add_definitions(-std=c99 -O3)

add_subdirectory(deps/glfw)
include_directories(deps/glew/include)
include_directories(deps/glfw/include)
if (EMSCRIPTEN)
# Emscripten default is GLFW 2.x but we use GLFW 3.x, also include data files
set_target_properties(craft PROPERTIES LINK_FLAGS "-s USE_GLFW=3 --embed-file ../shaders/ -s TOTAL_MEMORY=33554432 --embed-file ../textures/")
endif ()

if (NOT EMSCRIPTEN)
# Emscripten includes its own GLFW and GLEW ports
add_subdirectory(deps/glfw)
include_directories(deps/glew/include)
include_directories(deps/glfw/include)
endif ()

include_directories(deps/lodepng)
include_directories(deps/noise)
include_directories(deps/sqlite)
Expand All @@ -30,8 +52,12 @@ if(MINGW)
"C:/Program Files/CURL/include" "C:/Program Files (x86)/CURL/include")
endif()

find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})
if (NOT EMSCRIPTEN)
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})
else ()
set(CURL_LIBRARIES "")
endif ()

if(APPLE)
target_link_libraries(craft glfw
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,16 @@ terminal.

git clone https://github.com/fogleman/Craft.git
cd Craft
cmake .
mkdir build
pushd build
cmake ..
make
./craft
popd
./build/craft

To build for the web (experimental), install [Emscripten](http://emscripten.org) and instead run:

cmake -DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake ..

### Multiplayer

Expand Down
5 changes: 4 additions & 1 deletion shaders/block_fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#version 120
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

uniform sampler2D sampler;
uniform sampler2D sky_sampler;
Expand Down
9 changes: 6 additions & 3 deletions shaders/block_vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#version 120
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

uniform mat4 matrix;
uniform vec3 camera;
Expand All @@ -17,7 +20,7 @@ varying float fog_height;
varying float diffuse;

const float pi = 3.14159265;
const vec3 light_direction = normalize(vec3(-1.0, 1.0, -1.0));
vec3 light_direction = normalize(vec3(-1.0, 1.0, -1.0));

void main() {
gl_Position = matrix * position;
Expand All @@ -34,6 +37,6 @@ void main() {
fog_factor = pow(clamp(camera_distance / fog_distance, 0.0, 1.0), 4.0);
float dy = position.y - camera.y;
float dx = distance(position.xz, camera.xz);
fog_height = (atan(dy, dx) + pi / 2) / pi;
fog_height = (atan(dy, dx) + pi / 2.0) / pi;
}
}
4 changes: 3 additions & 1 deletion shaders/line_fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif

void main() {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
Expand Down
4 changes: 3 additions & 1 deletion shaders/line_vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif

uniform mat4 matrix;

Expand Down
4 changes: 3 additions & 1 deletion shaders/sky_fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif

uniform sampler2D sampler;
uniform float timer;
Expand Down
4 changes: 3 additions & 1 deletion shaders/sky_vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif

uniform mat4 matrix;

Expand Down
4 changes: 3 additions & 1 deletion shaders/text_fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif

uniform sampler2D sampler;
uniform bool is_sign;
Expand Down
4 changes: 3 additions & 1 deletion shaders/text_vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif

uniform mat4 matrix;

Expand Down
6 changes: 6 additions & 0 deletions src/auth.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#ifndef __EMSCRIPTEN__
#include <curl/curl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand All @@ -21,6 +23,9 @@ size_t write_function(char *data, size_t size, size_t count, void *arg) {
int get_access_token(
char *result, int length, char *username, char *identity_token)
{
#ifdef __EMSCRIPTEN__
return 0;
#else
static char url[] = "https://craft.michaelfogleman.com/api/1/identity";
strncpy(result, "", length);
CURL *curl = curl_easy_init();
Expand All @@ -46,4 +51,5 @@ int get_access_token(
}
}
return 0;
#endif
}
99 changes: 66 additions & 33 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#ifndef __EMSCRIPTEN__
#include <curl/curl.h>
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -2583,9 +2588,26 @@ void reset_model() {
g->time_changed = 1;
}

void one_iter();
static FPS fps = {0, 0, 0};
static double last_commit;
static double last_update;
static double previous;
static State *s;
static Player *me;
static Attrib block_attrib = {0};
static Attrib line_attrib = {0};
static Attrib text_attrib = {0};
static Attrib sky_attrib = {0};
static GLuint sky_buffer;
static int g_running;
static int g_inner_break;

int main(int argc, char **argv) {
// INITIALIZATION //
#ifndef __EMSCRIPTEN__
curl_global_init(CURL_GLOBAL_DEFAULT);
#endif
srand(time(NULL));
rand();

Expand All @@ -2600,7 +2622,6 @@ int main(int argc, char **argv) {
}

glfwMakeContextCurrent(g->window);
glfwSwapInterval(VSYNC);
glfwSetInputMode(g->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetKeyCallback(g->window, on_key);
glfwSetCharCallback(g->window, on_char);
Expand All @@ -2613,7 +2634,9 @@ int main(int argc, char **argv) {

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
#ifndef __EMSCRIPTEN__ // TODO: remove, what is replacement? glLogicOp not in >=GLES2: https://github.com/kripken/emscripten/issues/1416
glLogicOp(GL_INVERT);
#endif
glClearColor(0, 0, 0, 1);

// LOAD TEXTURES //
Expand Down Expand Up @@ -2652,10 +2675,6 @@ int main(int argc, char **argv) {
load_png_texture("textures/sign.png");

// LOAD SHADERS //
Attrib block_attrib = {0};
Attrib line_attrib = {0};
Attrib text_attrib = {0};
Attrib sky_attrib = {0};
GLuint program;

program = load_program(
Expand Down Expand Up @@ -2727,8 +2746,8 @@ int main(int argc, char **argv) {
}

// OUTER LOOP //
int running = 1;
while (running) {
g_running = 1;
while (g_running) {
// DATABASE INITIALIZATION //
if (g->mode == MODE_OFFLINE || USE_CACHE) {
db_enable();
Expand All @@ -2752,13 +2771,13 @@ int main(int argc, char **argv) {

// LOCAL VARIABLES //
reset_model();
FPS fps = {0, 0, 0};
double last_commit = glfwGetTime();
double last_update = glfwGetTime();
GLuint sky_buffer = gen_sky_buffer();
//FPS fps = {0, 0, 0};
last_commit = glfwGetTime();
last_update = glfwGetTime();
sky_buffer = gen_sky_buffer();

Player *me = g->players;
State *s = &g->players->state;
me = g->players;
s = &g->players->state;
me->id = 0;
me->name[0] = '\0';
me->buffer = 0;
Expand All @@ -2772,8 +2791,37 @@ int main(int argc, char **argv) {
}

// BEGIN MAIN LOOP //
double previous = glfwGetTime();
previous = glfwGetTime();
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(one_iter, 60, 1);
#else
glfwSwapInterval(VSYNC);
g_inner_break = 0;
while (1) {
one_iter();
if (g_inner_break) break;
}
#endif

// SHUTDOWN //
db_save_state(s->x, s->y, s->z, s->rx, s->ry);
db_close();
db_disable();
client_stop();
client_disable();
del_buffer(sky_buffer);
delete_all_chunks();
delete_all_players();
}

glfwTerminate();
#ifndef __EMSCRIPTEN__
curl_global_cleanup();
#endif
return 0;
}

void one_iter() {
// WINDOW SIZE AND SCALE //
g->scale = get_scale_factor();
glfwGetFramebufferSize(g->window, &g->width, &g->height);
Expand Down Expand Up @@ -2937,27 +2985,12 @@ int main(int argc, char **argv) {
glfwSwapBuffers(g->window);
glfwPollEvents();
if (glfwWindowShouldClose(g->window)) {
running = 0;
break;
g_running = 0;
g_inner_break = 1;
}
if (g->mode_changed) {
g->mode_changed = 0;
break;
g_inner_break = 1;
}
}

// SHUTDOWN //
db_save_state(s->x, s->y, s->z, s->rx, s->ry);
db_close();
db_disable();
client_stop();
client_disable();
del_buffer(sky_buffer);
delete_all_chunks();
delete_all_players();
}

glfwTerminate();
curl_global_cleanup();
return 0;
}