[HTML5] Add WebGL2 (GLES3) support using the OpenGL renderer.
Note, the editor build requires the mbedtls module to be manually enabled, as it is currently needed as a ResourceUID dependency. This will need to be addressed in a separate PR.
This commit is contained in:
parent
42f8bfaff0
commit
46fdba5f8b
13
SConstruct
13
SConstruct
|
@ -16,7 +16,6 @@ from collections import OrderedDict
|
||||||
import methods
|
import methods
|
||||||
import glsl_builders
|
import glsl_builders
|
||||||
import gles3_builders
|
import gles3_builders
|
||||||
from platform_methods import run_in_subprocess
|
|
||||||
|
|
||||||
# Scan possible build platforms
|
# Scan possible build platforms
|
||||||
|
|
||||||
|
@ -706,19 +705,13 @@ if selected_platform in platform_list:
|
||||||
suffix="glsl.gen.h",
|
suffix="glsl.gen.h",
|
||||||
src_suffix=".glsl",
|
src_suffix=".glsl",
|
||||||
),
|
),
|
||||||
}
|
|
||||||
env.Append(BUILDERS=GLSL_BUILDERS)
|
|
||||||
|
|
||||||
if not env["platform"] == "server":
|
|
||||||
env.Append(
|
|
||||||
BUILDERS={
|
|
||||||
"GLES3_GLSL": env.Builder(
|
"GLES3_GLSL": env.Builder(
|
||||||
action=run_in_subprocess(gles3_builders.build_gles3_headers),
|
action=env.Run(gles3_builders.build_gles3_headers, 'Building GLES3 GLSL header: "$TARGET"'),
|
||||||
suffix="glsl.gen.h",
|
suffix="glsl.gen.h",
|
||||||
src_suffix=".glsl",
|
src_suffix=".glsl",
|
||||||
)
|
),
|
||||||
}
|
}
|
||||||
)
|
env.Append(BUILDERS=GLSL_BUILDERS)
|
||||||
|
|
||||||
scons_cache_path = os.environ.get("SCONS_CACHE")
|
scons_cache_path = os.environ.get("SCONS_CACHE")
|
||||||
if scons_cache_path != None:
|
if scons_cache_path != None:
|
||||||
|
|
|
@ -243,7 +243,7 @@ public:
|
||||||
void set_stdout_enabled(bool p_enabled);
|
void set_stdout_enabled(bool p_enabled);
|
||||||
void set_stderr_enabled(bool p_enabled);
|
void set_stderr_enabled(bool p_enabled);
|
||||||
|
|
||||||
bool is_single_window() const;
|
virtual bool is_single_window() const;
|
||||||
|
|
||||||
virtual void disable_crash_handler() {}
|
virtual void disable_crash_handler() {}
|
||||||
virtual bool is_disable_crash_handler() const { return false; }
|
virtual bool is_disable_crash_handler() const { return false; }
|
||||||
|
|
|
@ -25,10 +25,9 @@ SConscript("winmidi/SCsub")
|
||||||
# Graphics drivers
|
# Graphics drivers
|
||||||
if env["vulkan"]:
|
if env["vulkan"]:
|
||||||
SConscript("vulkan/SCsub")
|
SConscript("vulkan/SCsub")
|
||||||
SConscript("gles3/SCsub")
|
if env["opengl3"]:
|
||||||
SConscript("gl_context/SCsub")
|
SConscript("gl_context/SCsub")
|
||||||
else:
|
SConscript("gles3/SCsub")
|
||||||
SConscript("dummy/SCsub")
|
|
||||||
|
|
||||||
# Core dependencies
|
# Core dependencies
|
||||||
SConscript("png/SCsub")
|
SConscript("png/SCsub")
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IPHONE_ENABLED
|
#if !defined(IPHONE_ENABLED) && !defined(JAVASCRIPT_ENABLED)
|
||||||
// We include EGL below to get debug callback on GLES2 platforms,
|
// We include EGL below to get debug callback on GLES2 platforms,
|
||||||
// but EGL is not available on iOS.
|
// but EGL is not available on iOS.
|
||||||
#define CAN_DEBUG
|
#define CAN_DEBUG
|
||||||
|
|
|
@ -281,8 +281,7 @@
|
||||||
<label for="videoMode" style="margin-right: 1rem">Video driver:</label>
|
<label for="videoMode" style="margin-right: 1rem">Video driver:</label>
|
||||||
<select id="videoMode">
|
<select id="videoMode">
|
||||||
<option value="" selected="selected">Auto</option>
|
<option value="" selected="selected">Auto</option>
|
||||||
<option value="GLES2">WebGL</option>
|
<option value="opengl3">WebGL 2</option>
|
||||||
<option value="GLES3">WebGL 2</option>
|
|
||||||
</select>
|
</select>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
@ -562,8 +561,9 @@
|
||||||
const is_project_manager = args.filter(function(v) { return v == '--project-manager' }).length != 0;
|
const is_project_manager = args.filter(function(v) { return v == '--project-manager' }).length != 0;
|
||||||
const is_game = !is_editor && !is_project_manager;
|
const is_game = !is_editor && !is_project_manager;
|
||||||
if (video_driver) {
|
if (video_driver) {
|
||||||
args.push('--video-driver', video_driver);
|
args.push('--rendering-driver', video_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_game) {
|
if (is_game) {
|
||||||
if (game) {
|
if (game) {
|
||||||
console.error("A game is already running. Close it first");
|
console.error("A game is already running. Close it first");
|
||||||
|
@ -651,9 +651,9 @@
|
||||||
selectVideoMode();
|
selectVideoMode();
|
||||||
showTab('editor');
|
showTab('editor');
|
||||||
setLoaderEnabled(false);
|
setLoaderEnabled(false);
|
||||||
const args = ['--project-manager'];
|
const args = ['--project-manager', '--single-window'];
|
||||||
if (video_driver) {
|
if (video_driver) {
|
||||||
args.push('--video-driver', video_driver);
|
args.push('--rendering-driver', video_driver);
|
||||||
}
|
}
|
||||||
editor.start({'args': args, 'persistentDrops': true}).then(function() {
|
editor.start({'args': args, 'persistentDrops': true}).then(function() {
|
||||||
setStatusMode('hidden');
|
setStatusMode('hidden');
|
||||||
|
|
|
@ -180,6 +180,13 @@ def configure(env):
|
||||||
env.Prepend(CPPPATH=["#platform/javascript"])
|
env.Prepend(CPPPATH=["#platform/javascript"])
|
||||||
env.Append(CPPDEFINES=["JAVASCRIPT_ENABLED", "UNIX_ENABLED"])
|
env.Append(CPPDEFINES=["JAVASCRIPT_ENABLED", "UNIX_ENABLED"])
|
||||||
|
|
||||||
|
if env["opengl3"]:
|
||||||
|
env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"])
|
||||||
|
# This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1.
|
||||||
|
env.Append(LINKFLAGS=["-s", "USE_WEBGL2=1"])
|
||||||
|
# Allow use to take control of swapping WebGL buffers.
|
||||||
|
env.Append(LINKFLAGS=["-s", "OFFSCREEN_FRAMEBUFFER=1"])
|
||||||
|
|
||||||
if env["javascript_eval"]:
|
if env["javascript_eval"]:
|
||||||
env.Append(CPPDEFINES=["JAVASCRIPT_EVAL_ENABLED"])
|
env.Append(CPPDEFINES=["JAVASCRIPT_EVAL_ENABLED"])
|
||||||
|
|
||||||
|
@ -218,25 +225,11 @@ def configure(env):
|
||||||
# us since we don't know requirements at compile-time.
|
# us since we don't know requirements at compile-time.
|
||||||
env.Append(LINKFLAGS=["-s", "ALLOW_MEMORY_GROWTH=1"])
|
env.Append(LINKFLAGS=["-s", "ALLOW_MEMORY_GROWTH=1"])
|
||||||
|
|
||||||
# This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1.
|
|
||||||
env.Append(LINKFLAGS=["-s", "USE_WEBGL2=1"])
|
|
||||||
|
|
||||||
# Do not call main immediately when the support code is ready.
|
# Do not call main immediately when the support code is ready.
|
||||||
env.Append(LINKFLAGS=["-s", "INVOKE_RUN=0"])
|
env.Append(LINKFLAGS=["-s", "INVOKE_RUN=0"])
|
||||||
|
|
||||||
# Allow use to take control of swapping WebGL buffers.
|
|
||||||
env.Append(LINKFLAGS=["-s", "OFFSCREEN_FRAMEBUFFER=1"])
|
|
||||||
|
|
||||||
# callMain for manual start, cwrap for the mono version.
|
# callMain for manual start, cwrap for the mono version.
|
||||||
env.Append(LINKFLAGS=["-s", "EXPORTED_RUNTIME_METHODS=['callMain','cwrap']"])
|
env.Append(LINKFLAGS=["-s", "EXPORTED_RUNTIME_METHODS=['callMain','cwrap']"])
|
||||||
|
|
||||||
# Add code that allow exiting runtime.
|
# Add code that allow exiting runtime.
|
||||||
env.Append(LINKFLAGS=["-s", "EXIT_RUNTIME=1"])
|
env.Append(LINKFLAGS=["-s", "EXIT_RUNTIME=1"])
|
||||||
|
|
||||||
# TODO remove once we have GLES support back (temporary fix undefined symbols due to dead code elimination).
|
|
||||||
env.Append(
|
|
||||||
LINKFLAGS=[
|
|
||||||
"-s",
|
|
||||||
"EXPORTED_FUNCTIONS=['_main', '_emscripten_webgl_get_current_context']",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
#include "platform/javascript/display_server_javascript.h"
|
#include "platform/javascript/display_server_javascript.h"
|
||||||
|
|
||||||
|
#ifdef GLES3_ENABLED
|
||||||
|
#include "drivers/gles3/rasterizer_gles3.h"
|
||||||
|
#endif
|
||||||
#include "platform/javascript/os_javascript.h"
|
#include "platform/javascript/os_javascript.h"
|
||||||
#include "servers/rendering/rasterizer_dummy.h"
|
#include "servers/rendering/rasterizer_dummy.h"
|
||||||
|
|
||||||
|
@ -50,14 +53,6 @@ DisplayServerJavaScript *DisplayServerJavaScript::get_singleton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Window (canvas)
|
// Window (canvas)
|
||||||
void DisplayServerJavaScript::focus_canvas() {
|
|
||||||
godot_js_display_canvas_focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DisplayServerJavaScript::is_canvas_focused() {
|
|
||||||
return godot_js_display_canvas_is_focused() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DisplayServerJavaScript::check_size_force_redraw() {
|
bool DisplayServerJavaScript::check_size_force_redraw() {
|
||||||
return godot_js_display_size_update() != 0;
|
return godot_js_display_size_update() != 0;
|
||||||
}
|
}
|
||||||
|
@ -141,11 +136,12 @@ void DisplayServerJavaScript::key_callback(int p_pressed, int p_repeat, int p_mo
|
||||||
int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers) {
|
int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers) {
|
||||||
DisplayServerJavaScript *ds = get_singleton();
|
DisplayServerJavaScript *ds = get_singleton();
|
||||||
|
|
||||||
|
Point2 pos(p_x, p_y);
|
||||||
|
Input::get_singleton()->set_mouse_position(pos);
|
||||||
Ref<InputEventMouseButton> ev;
|
Ref<InputEventMouseButton> ev;
|
||||||
ev.instantiate();
|
ev.instantiate();
|
||||||
ev->set_pressed(p_pressed);
|
ev->set_position(pos);
|
||||||
ev->set_position(Point2(p_x, p_y));
|
ev->set_global_position(pos);
|
||||||
ev->set_global_position(ev->get_position());
|
|
||||||
ev->set_pressed(p_pressed);
|
ev->set_pressed(p_pressed);
|
||||||
dom2godot_mod(ev, p_modifiers);
|
dom2godot_mod(ev, p_modifiers);
|
||||||
|
|
||||||
|
@ -222,13 +218,15 @@ void DisplayServerJavaScript::mouse_move_callback(double p_x, double p_y, double
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point2 pos(p_x, p_y);
|
||||||
|
Input::get_singleton()->set_mouse_position(pos);
|
||||||
Ref<InputEventMouseMotion> ev;
|
Ref<InputEventMouseMotion> ev;
|
||||||
ev.instantiate();
|
ev.instantiate();
|
||||||
dom2godot_mod(ev, p_modifiers);
|
dom2godot_mod(ev, p_modifiers);
|
||||||
ev->set_button_mask(input_mask);
|
ev->set_button_mask(input_mask);
|
||||||
|
|
||||||
ev->set_position(Point2(p_x, p_y));
|
ev->set_position(pos);
|
||||||
ev->set_global_position(ev->get_position());
|
ev->set_global_position(pos);
|
||||||
|
|
||||||
ev->set_relative(Vector2(p_rel_x, p_rel_y));
|
ev->set_relative(Vector2(p_rel_x, p_rel_y));
|
||||||
Input::get_singleton()->set_mouse_position(ev->get_position());
|
Input::get_singleton()->set_mouse_position(ev->get_position());
|
||||||
|
@ -397,6 +395,10 @@ DisplayServer::MouseMode DisplayServerJavaScript::mouse_get_mode() const {
|
||||||
return MOUSE_MODE_VISIBLE;
|
return MOUSE_MODE_VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point2i DisplayServerJavaScript::mouse_get_position() const {
|
||||||
|
return Input::get_singleton()->get_mouse_position();
|
||||||
|
}
|
||||||
|
|
||||||
// Wheel
|
// Wheel
|
||||||
int DisplayServerJavaScript::mouse_wheel_callback(double p_delta_x, double p_delta_y) {
|
int DisplayServerJavaScript::mouse_wheel_callback(double p_delta_x, double p_delta_y) {
|
||||||
if (!godot_js_display_canvas_is_focused()) {
|
if (!godot_js_display_canvas_is_focused()) {
|
||||||
|
@ -580,7 +582,9 @@ void DisplayServerJavaScript::process_joypads() {
|
||||||
|
|
||||||
Vector<String> DisplayServerJavaScript::get_rendering_drivers_func() {
|
Vector<String> DisplayServerJavaScript::get_rendering_drivers_func() {
|
||||||
Vector<String> drivers;
|
Vector<String> drivers;
|
||||||
drivers.push_back("dummy");
|
#ifdef GLES3_ENABLED
|
||||||
|
drivers.push_back("opengl3");
|
||||||
|
#endif
|
||||||
return drivers;
|
return drivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,40 +682,34 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
|
||||||
// Expose method for requesting quit.
|
// Expose method for requesting quit.
|
||||||
godot_js_os_request_quit_cb(request_quit_callback);
|
godot_js_os_request_quit_cb(request_quit_callback);
|
||||||
|
|
||||||
RasterizerDummy::make_current(); // TODO OpenGL in Godot 4.0... or webgpu?
|
#ifdef GLES3_ENABLED
|
||||||
#if 0
|
// TODO "vulkan" defaults to webgl2 for now.
|
||||||
|
bool wants_webgl2 = p_rendering_driver == "opengl3" || p_rendering_driver == "vulkan";
|
||||||
|
bool webgl2_init_failed = wants_webgl2 && !godot_js_display_has_webgl(2);
|
||||||
|
if (wants_webgl2 && !webgl2_init_failed) {
|
||||||
EmscriptenWebGLContextAttributes attributes;
|
EmscriptenWebGLContextAttributes attributes;
|
||||||
emscripten_webgl_init_context_attributes(&attributes);
|
emscripten_webgl_init_context_attributes(&attributes);
|
||||||
attributes.alpha = GLOBAL_GET("display/window/per_pixel_transparency/allowed");
|
//attributes.alpha = GLOBAL_GET("display/window/per_pixel_transparency/allowed");
|
||||||
|
attributes.alpha = true;
|
||||||
attributes.antialias = false;
|
attributes.antialias = false;
|
||||||
ERR_FAIL_INDEX_V(p_video_driver, VIDEO_DRIVER_MAX, ERR_INVALID_PARAMETER);
|
attributes.majorVersion = 2;
|
||||||
|
|
||||||
if (p_desired.layered) {
|
webgl_ctx = emscripten_webgl_create_context(canvas_id, &attributes);
|
||||||
set_window_per_pixel_transparency_enabled(true);
|
if (emscripten_webgl_make_context_current(webgl_ctx) != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||||
}
|
webgl2_init_failed = true;
|
||||||
|
|
||||||
bool gl_initialization_error = false;
|
|
||||||
|
|
||||||
if (RasterizerGLES3::is_viable() == OK) {
|
|
||||||
attributes.majorVersion = 1;
|
|
||||||
RasterizerGLES3::register_config();
|
|
||||||
RasterizerGLES3::make_current();
|
|
||||||
} else {
|
} else {
|
||||||
gl_initialization_error = true;
|
RasterizerGLES3::make_current();
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(canvas_id, &attributes);
|
|
||||||
if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) {
|
|
||||||
gl_initialization_error = true;
|
|
||||||
}
|
}
|
||||||
|
if (webgl2_init_failed) {
|
||||||
if (gl_initialization_error) {
|
OS::get_singleton()->alert("Your browser does not seem to support WebGL2. Please update your browser version.",
|
||||||
OS::get_singleton()->alert("Your browser does not seem to support WebGL. Please update your browser version.",
|
|
||||||
"Unable to initialize video driver");
|
"Unable to initialize video driver");
|
||||||
return ERR_UNAVAILABLE;
|
|
||||||
}
|
}
|
||||||
|
if (!wants_webgl2 || webgl2_init_failed) {
|
||||||
video_driver_index = p_video_driver;
|
RasterizerDummy::make_current();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
RasterizerDummy::make_current();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// JS Input interface (js/libs/library_godot_input.js)
|
// JS Input interface (js/libs/library_godot_input.js)
|
||||||
|
@ -738,8 +736,12 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayServerJavaScript::~DisplayServerJavaScript() {
|
DisplayServerJavaScript::~DisplayServerJavaScript() {
|
||||||
//emscripten_webgl_commit_frame();
|
#ifdef GLES3_ENABLED
|
||||||
//emscripten_webgl_destroy_context(webgl_ctx);
|
if (webgl_ctx) {
|
||||||
|
emscripten_webgl_commit_frame();
|
||||||
|
emscripten_webgl_destroy_context(webgl_ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DisplayServerJavaScript::has_feature(Feature p_feature) const {
|
bool DisplayServerJavaScript::has_feature(Feature p_feature) const {
|
||||||
|
@ -968,5 +970,9 @@ bool DisplayServerJavaScript::get_swap_cancel_ok() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayServerJavaScript::swap_buffers() {
|
void DisplayServerJavaScript::swap_buffers() {
|
||||||
//emscripten_webgl_commit_frame();
|
#ifdef GLES3_ENABLED
|
||||||
|
if (webgl_ctx) {
|
||||||
|
emscripten_webgl_commit_frame();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,10 @@ private:
|
||||||
};
|
};
|
||||||
JSKeyEvent key_event;
|
JSKeyEvent key_event;
|
||||||
|
|
||||||
|
#ifdef GLES3_ENABLED
|
||||||
|
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE webgl_ctx = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
WindowMode window_mode = WINDOW_MODE_WINDOWED;
|
WindowMode window_mode = WINDOW_MODE_WINDOWED;
|
||||||
ObjectID window_attached_instance_id = {};
|
ObjectID window_attached_instance_id = {};
|
||||||
|
|
||||||
|
@ -72,8 +76,6 @@ private:
|
||||||
bool swap_cancel_ok = false;
|
bool swap_cancel_ok = false;
|
||||||
|
|
||||||
// utilities
|
// utilities
|
||||||
static void focus_canvas();
|
|
||||||
static bool is_canvas_focused();
|
|
||||||
static void dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod);
|
static void dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod);
|
||||||
static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape);
|
static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape);
|
||||||
|
|
||||||
|
@ -121,6 +123,7 @@ public:
|
||||||
// mouse
|
// mouse
|
||||||
virtual void mouse_set_mode(MouseMode p_mode) override;
|
virtual void mouse_set_mode(MouseMode p_mode) override;
|
||||||
virtual MouseMode mouse_get_mode() const override;
|
virtual MouseMode mouse_get_mode() const override;
|
||||||
|
virtual Point2i mouse_get_position() const override;
|
||||||
|
|
||||||
// touch
|
// touch
|
||||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
String get_user_data_dir() const override;
|
String get_user_data_dir() const override;
|
||||||
|
|
||||||
bool is_userfs_persistent() const override;
|
bool is_userfs_persistent() const override;
|
||||||
|
bool is_single_window() const override { return true; }
|
||||||
|
|
||||||
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue