summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/SCsub3
-rw-r--r--drivers/alsa/SCsub2
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp4
-rw-r--r--drivers/alsamidi/SCsub2
-rw-r--r--drivers/alsamidi/alsa_midi.cpp9
-rw-r--r--drivers/alsamidi/alsa_midi.h8
-rw-r--r--drivers/convex_decomp/SCsub5
-rw-r--r--drivers/convex_decomp/b2d_decompose.h5
-rw-r--r--drivers/coreaudio/SCsub2
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp3
-rw-r--r--drivers/coremidi/SCsub2
-rw-r--r--drivers/coremidi/core_midi.cpp3
-rw-r--r--drivers/coremidi/core_midi.h7
-rw-r--r--drivers/dummy/rasterizer_dummy.h10
-rw-r--r--drivers/dummy/texture_loader_dummy.cpp4
-rw-r--r--drivers/gl_context/SCsub7
-rw-r--r--drivers/gl_context/context_gl.h2
-rw-r--r--drivers/gles2/SCsub2
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp11
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp28
-rw-r--r--drivers/gles2/rasterizer_gles2.h3
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp1971
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h192
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp440
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h60
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp33
-rw-r--r--drivers/gles2/shader_compiler_gles2.h6
-rw-r--r--drivers/gles2/shader_gles2.cpp109
-rw-r--r--drivers/gles2/shader_gles2.h31
-rw-r--r--drivers/gles2/shaders/cubemap_filter.glsl14
-rw-r--r--drivers/gles2/shaders/scene.glsl1575
-rw-r--r--drivers/gles2/shaders/stdlib.glsl10
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp125
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h1
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp8
-rw-r--r--drivers/gles3/rasterizer_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp115
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h1
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp40
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h7
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp32
-rw-r--r--drivers/gles3/shader_compiler_gles3.h2
-rw-r--r--drivers/gles3/shader_gles3.cpp7
-rw-r--r--drivers/gles3/shader_gles3.h11
-rw-r--r--drivers/gles3/shaders/canvas.glsl10
-rw-r--r--drivers/gles3/shaders/scene.glsl34
-rw-r--r--drivers/gles3/shaders/tonemap.glsl2
-rw-r--r--drivers/png/SCsub18
-rw-r--r--drivers/png/image_loader_png.cpp4
-rw-r--r--drivers/png/image_loader_png.h2
-rw-r--r--drivers/png/resource_saver_png.cpp4
-rw-r--r--drivers/png/resource_saver_png.h4
-rw-r--r--drivers/pulseaudio/SCsub2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp13
-rw-r--r--drivers/register_driver_types.cpp6
-rw-r--r--drivers/rtaudio/SCsub5
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp4
-rw-r--r--drivers/unix/SCsub2
-rw-r--r--drivers/unix/dir_access_unix.cpp15
-rw-r--r--drivers/unix/dir_access_unix.h5
-rw-r--r--drivers/unix/file_access_unix.cpp3
-rw-r--r--drivers/unix/file_access_unix.h5
-rw-r--r--drivers/unix/ip_unix.h2
-rw-r--r--drivers/unix/mutex_posix.cpp3
-rw-r--r--drivers/unix/mutex_posix.h3
-rw-r--r--drivers/unix/net_socket_posix.cpp621
-rw-r--r--drivers/unix/net_socket_posix.h (renamed from drivers/windows/stream_peer_tcp_winsock.h)97
-rw-r--r--drivers/unix/os_unix.cpp75
-rw-r--r--drivers/unix/os_unix.h4
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp317
-rw-r--r--drivers/unix/packet_peer_udp_posix.h88
-rw-r--r--drivers/unix/rw_lock_posix.cpp4
-rw-r--r--drivers/unix/rw_lock_posix.h2
-rw-r--r--drivers/unix/semaphore_posix.cpp2
-rw-r--r--drivers/unix/semaphore_posix.h2
-rw-r--r--drivers/unix/socket_helpers.h156
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp411
-rw-r--r--drivers/unix/stream_peer_tcp_posix.h90
-rw-r--r--drivers/unix/syslog_logger.cpp2
-rw-r--r--drivers/unix/syslog_logger.h4
-rw-r--r--drivers/unix/tcp_server_posix.cpp207
-rw-r--r--drivers/unix/tcp_server_posix.h58
-rw-r--r--drivers/unix/thread_posix.cpp4
-rw-r--r--drivers/unix/thread_posix.h2
-rw-r--r--drivers/wasapi/SCsub2
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp9
-rw-r--r--drivers/windows/SCsub2
-rw-r--r--drivers/windows/dir_access_windows.cpp4
-rw-r--r--drivers/windows/dir_access_windows.h2
-rw-r--r--drivers/windows/file_access_windows.h6
-rw-r--r--drivers/windows/mutex_windows.cpp3
-rw-r--r--drivers/windows/mutex_windows.h5
-rw-r--r--drivers/windows/packet_peer_udp_winsock.cpp298
-rw-r--r--drivers/windows/packet_peer_udp_winsock.h89
-rw-r--r--drivers/windows/rw_lock_windows.cpp5
-rw-r--r--drivers/windows/rw_lock_windows.h3
-rw-r--r--drivers/windows/semaphore_windows.cpp2
-rw-r--r--drivers/windows/semaphore_windows.h4
-rw-r--r--drivers/windows/shell_windows.h4
-rw-r--r--drivers/windows/stream_peer_tcp_winsock.cpp375
-rw-r--r--drivers/windows/tcp_server_winsock.cpp189
-rw-r--r--drivers/windows/tcp_server_winsock.h61
-rw-r--r--drivers/windows/thread_windows.cpp2
-rw-r--r--drivers/windows/thread_windows.h13
-rw-r--r--drivers/winmidi/SCsub2
-rw-r--r--drivers/winmidi/win_midi.cpp3
-rw-r--r--drivers/winmidi/win_midi.h6
-rw-r--r--drivers/xaudio2/SCsub2
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp4
-rw-r--r--drivers/zlib/SCsub26
110 files changed, 4401 insertions, 3926 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index f9cfa3fb05..320d4dc4bb 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -4,9 +4,6 @@ Import('env')
env.drivers_sources = []
-if 'builtin_zlib' in env and env['builtin_zlib']:
- SConscript("zlib/SCsub")
-
# OS drivers
SConscript('unix/SCsub')
SConscript('windows/SCsub')
diff --git a/drivers/alsa/SCsub b/drivers/alsa/SCsub
index ee39fd2631..28b315ae66 100644
--- a/drivers/alsa/SCsub
+++ b/drivers/alsa/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 1f53d52951..50697b8834 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -32,8 +32,8 @@
#ifdef ALSA_ENABLED
-#include "os/os.h"
-#include "project_settings.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
#include <errno.h>
diff --git a/drivers/alsamidi/SCsub b/drivers/alsamidi/SCsub
index 233593b0f9..4c24925192 100644
--- a/drivers/alsamidi/SCsub
+++ b/drivers/alsamidi/SCsub
@@ -4,5 +4,3 @@ Import('env')
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/alsamidi/alsa_midi.cpp b/drivers/alsamidi/alsa_midi.cpp
index 599470d7e0..33ad7e3f17 100644
--- a/drivers/alsamidi/alsa_midi.cpp
+++ b/drivers/alsamidi/alsa_midi.cpp
@@ -30,11 +30,12 @@
#ifdef ALSAMIDI_ENABLED
-#include <errno.h>
-
#include "alsa_midi.h"
-#include "os/os.h"
-#include "print_string.h"
+
+#include "core/os/os.h"
+#include "core/print_string.h"
+
+#include <errno.h>
static int get_message_size(uint8_t message) {
switch (message & 0xF0) {
diff --git a/drivers/alsamidi/alsa_midi.h b/drivers/alsamidi/alsa_midi.h
index 90e458a365..5741036166 100644
--- a/drivers/alsamidi/alsa_midi.h
+++ b/drivers/alsamidi/alsa_midi.h
@@ -33,13 +33,13 @@
#ifndef ALSA_MIDI_H
#define ALSA_MIDI_H
-#include <alsa/asoundlib.h>
-#include <stdio.h>
-
+#include "core/os/midi_driver.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "core/vector.h"
-#include "os/midi_driver.h"
+
+#include <alsa/asoundlib.h>
+#include <stdio.h>
class MIDIDriverALSAMidi : public MIDIDriver {
diff --git a/drivers/convex_decomp/SCsub b/drivers/convex_decomp/SCsub
index f017e55120..65ba5332b7 100644
--- a/drivers/convex_decomp/SCsub
+++ b/drivers/convex_decomp/SCsub
@@ -11,6 +11,7 @@ thirdparty_sources = [
"b2Triangle.cpp",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-env.add_source_files(env.drivers_sources, thirdparty_sources)
-Export('env')
+env_thirdparty = env.Clone()
+env_thirdparty.disable_warnings()
+env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources)
diff --git a/drivers/convex_decomp/b2d_decompose.h b/drivers/convex_decomp/b2d_decompose.h
index b21792047e..f6b08b957c 100644
--- a/drivers/convex_decomp/b2d_decompose.h
+++ b/drivers/convex_decomp/b2d_decompose.h
@@ -31,8 +31,9 @@
#ifndef B2D_DECOMPOSE_H
#define B2D_DECOMPOSE_H
-#include "vector.h"
-#include "vector2.h"
+#include "core/math/vector2.h"
+#include "core/vector.h"
+
Vector<Vector<Vector2> > b2d_decompose(const Vector<Vector2> &p_polygon);
#endif // B2D_DECOMPOSE_H
diff --git a/drivers/coreaudio/SCsub b/drivers/coreaudio/SCsub
index 233593b0f9..4c24925192 100644
--- a/drivers/coreaudio/SCsub
+++ b/drivers/coreaudio/SCsub
@@ -4,5 +4,3 @@ Import('env')
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 45d62e797f..09e50e4aaa 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -31,8 +31,9 @@
#ifdef COREAUDIO_ENABLED
#include "audio_driver_coreaudio.h"
+
+#include "core/os/os.h"
#include "core/project_settings.h"
-#include "os/os.h"
#define kOutputBus 0
#define kInputBus 1
diff --git a/drivers/coremidi/SCsub b/drivers/coremidi/SCsub
index 233593b0f9..4c24925192 100644
--- a/drivers/coremidi/SCsub
+++ b/drivers/coremidi/SCsub
@@ -4,5 +4,3 @@ Import('env')
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/coremidi/core_midi.cpp b/drivers/coremidi/core_midi.cpp
index 6d4624e05b..e8106c4543 100644
--- a/drivers/coremidi/core_midi.cpp
+++ b/drivers/coremidi/core_midi.cpp
@@ -31,7 +31,8 @@
#ifdef COREMIDI_ENABLED
#include "core_midi.h"
-#include "print_string.h"
+
+#include "core/print_string.h"
#include <CoreAudio/HostTime.h>
#include <CoreServices/CoreServices.h>
diff --git a/drivers/coremidi/core_midi.h b/drivers/coremidi/core_midi.h
index c6b443764f..ea6b0fcb06 100644
--- a/drivers/coremidi/core_midi.h
+++ b/drivers/coremidi/core_midi.h
@@ -33,12 +33,11 @@
#ifndef CORE_MIDI_H
#define CORE_MIDI_H
-#include <stdio.h>
+#include "core/os/midi_driver.h"
+#include "core/vector.h"
#include <CoreMIDI/CoreMIDI.h>
-
-#include "core/vector.h"
-#include "os/midi_driver.h"
+#include <stdio.h>
class MIDIDriverCoreMidi : public MIDIDriver {
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index 0381d3f0c1..9315026623 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -27,16 +27,16 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#ifndef RASTERIZER_DUMMY_H
#define RASTERIZER_DUMMY_H
-#include "camera_matrix.h"
+#include "core/math/camera_matrix.h"
+#include "core/self_list.h"
#include "scene/resources/mesh.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
-#include "self_list.h"
-
class RasterizerSceneDummy : public RasterizerScene {
public:
/* SHADOW ATLAS API */
@@ -267,6 +267,7 @@ public:
void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {}
Variant material_get_param(RID p_material, const StringName &p_param) const { return Variant(); }
+ Variant material_get_param_default(RID p_material, const StringName &p_param) const { return Variant(); }
void material_set_line_width(RID p_material, float p_width) {}
@@ -516,6 +517,7 @@ public:
void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {}
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {}
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {}
+ void reflection_probe_set_resolution(RID p_probe, int p_resolution) {}
AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); }
VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; }
@@ -801,6 +803,8 @@ public:
_create_func = _create_current;
}
+ virtual bool is_low_end() const { return true; }
+
RasterizerDummy() {}
~RasterizerDummy() {}
};
diff --git a/drivers/dummy/texture_loader_dummy.cpp b/drivers/dummy/texture_loader_dummy.cpp
index b099019d17..8153fbd10b 100644
--- a/drivers/dummy/texture_loader_dummy.cpp
+++ b/drivers/dummy/texture_loader_dummy.cpp
@@ -29,8 +29,10 @@
/*************************************************************************/
#include "texture_loader_dummy.h"
+
#include "core/os/file_access.h"
-#include "print_string.h"
+#include "core/print_string.h"
+
#include <string.h>
RES ResourceFormatDummyTexture::load(const String &p_path, const String &p_original_path, Error *r_error) {
diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub
index 4d66a9f9f1..efb26a7908 100644
--- a/drivers/gl_context/SCsub
+++ b/drivers/gl_context/SCsub
@@ -10,13 +10,14 @@ if (env["platform"] in ["haiku", "osx", "windows", "x11"]):
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env.add_source_files(env.drivers_sources, thirdparty_sources)
env.Append(CPPPATH=[thirdparty_dir])
env.Append(CPPFLAGS=['-DGLAD_ENABLED'])
env.Append(CPPFLAGS=['-DGLES_OVER_GL'])
+ env_thirdparty = env.Clone()
+ env_thirdparty.disable_warnings()
+ env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources)
+
# Godot source files
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h
index 60781a3453..37f334454b 100644
--- a/drivers/gl_context/context_gl.h
+++ b/drivers/gl_context/context_gl.h
@@ -33,7 +33,7 @@
#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
-#include "typedefs.h"
+#include "core/typedefs.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
diff --git a/drivers/gles2/SCsub b/drivers/gles2/SCsub
index 2471dd3739..9923e52c73 100644
--- a/drivers/gles2/SCsub
+++ b/drivers/gles2/SCsub
@@ -2,6 +2,6 @@
Import('env')
-env.add_source_files(env.drivers_sources,"*.cpp")
+env.add_source_files(env.drivers_sources, "*.cpp")
SConscript("shaders/SCsub")
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 9a9ede761a..263f210fa2 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -27,11 +27,14 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#include "rasterizer_canvas_gles2.h"
-#include "os/os.h"
-#include "project_settings.h"
+
+#include "core/os/os.h"
+#include "core/project_settings.h"
#include "rasterizer_scene_gles2.h"
#include "servers/visual/visual_server_raster.h"
+
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
#endif
@@ -562,7 +565,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
buffer[(1 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
buffer[(1 * 4 * 4) + 15] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- // thrid row
+ // third row
buffer[(2 * 4 * 4) + 0] = np->rect.position.x;
buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
@@ -808,8 +811,6 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
bool rebind_shader = true;
- Size2 rt_size = Size2(storage->frame.current_rt->width, storage->frame.current_rt->height);
-
state.current_tex = RID();
state.current_tex_ptr = NULL;
state.current_normal = RID();
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 76ee80aa07..1dd594cc20 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -27,12 +27,12 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#include "rasterizer_gles2.h"
-#include "gl_context/context_gl.h"
-#include "os/os.h"
-#include "project_settings.h"
-#include <string.h>
+#include "core/os/os.h"
+#include "core/project_settings.h"
+#include "drivers/gl_context/context_gl.h"
#define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
#define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
@@ -321,9 +321,25 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
Rect2 screenrect;
+ if (p_scale) {
+
+ if (window_w > window_h) {
+ //scale horizontally
+ screenrect.size.y = window_h;
+ screenrect.size.x = imgrect.size.x * window_h / imgrect.size.y;
+ screenrect.position.x = (window_w - screenrect.size.x) / 2;
- screenrect = imgrect;
- screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor();
+ } else {
+ //scale vertically
+ screenrect.size.x = window_w;
+ screenrect.size.y = imgrect.size.y * window_w / imgrect.size.x;
+ screenrect.position.y = (window_h - screenrect.size.y) / 2;
+ }
+ } else {
+
+ screenrect = imgrect;
+ screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor();
+ }
RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(texture);
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index 98c73b776b..45a9db73f2 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -27,6 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#ifndef RASTERIZERGLES2_H
#define RASTERIZERGLES2_H
@@ -65,6 +66,8 @@ public:
static void make_current();
static void register_config();
+ virtual bool is_low_end() const { return true; }
+
RasterizerGLES2();
~RasterizerGLES2();
};
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index e21998d55e..22cc45a0f6 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -27,16 +27,17 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#include "rasterizer_scene_gles2.h"
-#include "math/transform.h"
-#include "math_funcs.h"
-#include "os/os.h"
-#include "project_settings.h"
+
+#include "core/math/math_funcs.h"
+#include "core/math/transform.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
+#include "core/vmap.h"
#include "rasterizer_canvas_gles2.h"
#include "servers/visual/visual_server_raster.h"
-#include "vmap.h"
-
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
#endif
@@ -109,8 +110,8 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -436,29 +437,182 @@ void RasterizerSceneGLES2::reflection_atlas_set_subdivision(RID p_ref_atlas, int
////////////////////////////////////////////////////
RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
- return RID();
+
+ RasterizerStorageGLES2::ReflectionProbe *probe = storage->reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!probe, RID());
+
+ ReflectionProbeInstance *rpi = memnew(ReflectionProbeInstance);
+
+ rpi->probe_ptr = probe;
+ rpi->self = reflection_probe_instance_owner.make_rid(rpi);
+ rpi->probe = p_probe;
+ rpi->reflection_atlas_index = -1;
+ rpi->render_step = -1;
+ rpi->last_pass = 0;
+ rpi->current_resolution = 0;
+ rpi->dirty = true;
+
+ rpi->last_pass = 0;
+ rpi->index = 0;
+
+ for (int i = 0; i < 6; i++) {
+ glGenFramebuffers(1, &rpi->fbo[i]);
+ }
+
+ glGenFramebuffers(1, &rpi->fbo_blur);
+ glGenRenderbuffers(1, &rpi->depth);
+ glGenTextures(1, &rpi->cubemap);
+
+ return rpi->self;
}
void RasterizerSceneGLES2::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!rpi);
+ rpi->transform = p_transform;
}
void RasterizerSceneGLES2::reflection_probe_release_atlas_index(RID p_instance) {
}
bool RasterizerSceneGLES2::reflection_probe_instance_needs_redraw(RID p_instance) {
- return false;
+ const ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ bool need_redraw = rpi->probe_ptr->resolution != rpi->current_resolution || rpi->dirty || rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS;
+ rpi->dirty = false;
+ return need_redraw;
}
bool RasterizerSceneGLES2::reflection_probe_instance_has_reflection(RID p_instance) {
- return false;
+ return true;
}
bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
- return false;
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ rpi->render_step = 0;
+
+ if (rpi->probe_ptr->resolution != rpi->current_resolution) {
+
+ //update cubemap if resolution changed
+ int size = rpi->probe_ptr->resolution;
+ rpi->current_resolution = size;
+
+ int lod = 0;
+
+ GLenum internal_format = GL_RGBA;
+ GLenum format = GL_RGBA;
+ GLenum type = GL_UNSIGNED_BYTE;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
+
+ // Set the initial (empty) mipmaps, all need to be set for this to work in GLES2, even if later wont be used.
+ while (size >= 1) {
+
+ for (int i = 0; i < 6; i++) {
+ glTexImage2D(_cube_side_enum[i], lod, internal_format, size, size, 0, format, type, NULL);
+ if (size == rpi->current_resolution) {
+ //adjust framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0);
+ glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth);
+
+#ifdef DEBUG_ENABLED
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
+#endif
+ }
+ }
+
+ lod++;
+
+ size >>= 1;
+ }
+
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+
+ return true;
}
bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_instance) {
- return false;
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ int size = rpi->probe_ptr->resolution;
+
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_BLEND);
+ glDepthMask(GL_FALSE);
+
+ for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
+ glDisableVertexAttribArray(i);
+ }
+ }
+
+ //vdc cache
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo_blur);
+ // now render to the framebuffer, mipmap level for mipmap level
+ int lod = 1;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to
+
+ size >>= 1;
+ int mipmaps = 6;
+ int mm_level = mipmaps - 1;
+
+ storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
+ storage->shaders.cubemap_filter.bind();
+
+ //blur
+ while (size >= 1) {
+
+ for (int i = 0; i < 6; i++) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, lod);
+
+ glViewport(0, 0, size, size);
+ storage->bind_quad_array();
+ storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
+ float roughness = CLAMP(lod / (float)(mipmaps - 1), 0, 1);
+ storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness);
+ storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ size >>= 1;
+
+ mm_level--;
+
+ lod++;
+ }
+
+ // restore ranges
+
+ glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return true;
}
/* ENVIRONMENT API */
@@ -603,6 +757,8 @@ RID RasterizerSceneGLES2::light_instance_create(RID p_light) {
light_instance->light = p_light;
light_instance->light_ptr = storage->light_owner.getornull(p_light);
+ light_instance->light_index = 0xFFFF;
+
ERR_FAIL_COND_V(!light_instance->light_ptr, RID());
light_instance->self = light_instance_owner.make_rid(light_instance);
@@ -708,9 +864,39 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX;
bool has_alpha = has_base_alpha || has_blend_alpha;
- // TODO add this stuff
- // bool mirror = p_instance->mirror;
- // bool no_cull = false;
+ bool mirror = p_instance->mirror;
+
+ if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED) {
+ mirror = false;
+ } else if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_FRONT) {
+ mirror = !mirror;
+ }
+
+ //if (p_material->shader->spatial.uses_sss) {
+ // state.used_sss = true;
+ //}
+
+ if (p_material->shader->spatial.uses_screen_texture) {
+ state.used_screen_texture = true;
+ }
+
+ if (p_depth_pass) {
+
+ if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))
+ return; //bye
+
+ if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+ //shader does not use discard and does not write a vertex position, use generic material
+ if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
+ p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided);
+ mirror = false;
+ } else {
+ p_material = storage->material_owner.getptr(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material : default_material);
+ }
+ }
+
+ has_alpha = false;
+ }
RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
@@ -723,46 +909,130 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
e->instance = p_instance;
e->owner = p_owner;
e->sort_key = 0;
+ e->depth_key = 0;
+ e->use_accum = false;
+ e->light_index = RenderList::MAX_LIGHTS;
+ e->use_accum_ptr = &e->use_accum;
+ e->instancing = (e->instance->base_type == VS::INSTANCE_MULTIMESH) ? 1 : 0;
+
+ if (e->geometry->last_pass != render_pass) {
+ e->geometry->last_pass = render_pass;
+ e->geometry->index = current_geometry_index++;
+ }
- // TODO check render pass of geometry
-
- // TODO check directional light flag
+ e->geometry_index = e->geometry->index;
- if (p_depth_pass) {
- // if we are in the depth pass we can sort out a few things to improve performance
+ if (e->material->last_pass != render_pass) {
+ e->material->last_pass = render_pass;
+ e->material->index = current_material_index++;
- if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
- return;
+ if (e->material->shader->last_pass != render_pass) {
+ e->material->shader->index = current_shader_index++;
}
+ }
- if (p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+ e->material_index = e->material->index;
- // shader doesn't use discard or writes a custom vertex position,
- // so we can use a stripped down shader instead
+ e->refprobe_0_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
+ e->refprobe_1_index = RenderList::MAX_REFLECTION_PROBES; //refprobe disabled by default
- // TODO twosided and worldcoord stuff
+ if (!p_depth_pass) {
+
+ e->depth_layer = e->instance->depth_layer;
+ e->priority = p_material->render_priority;
+
+ int rpsize = e->instance->reflection_probe_instances.size();
+ if (rpsize > 0) {
+ bool first = true;
+ rpsize = MIN(rpsize, 2); //more than 2 per object are not supported, this keeps it stable
- p_material = storage->material_owner.getptr(default_material_twosided);
+ for (int i = 0; i < rpsize; i++) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(e->instance->reflection_probe_instances[i]);
+ if (rpi->last_pass != render_pass) {
+ continue;
+ }
+ if (first) {
+ e->refprobe_0_index = rpi->index;
+ first = false;
+ } else {
+ e->refprobe_1_index = rpi->index;
+ break;
+ }
+ }
+
+ /* if (e->refprobe_0_index > e->refprobe_1_index) { //if both are valid, swap them to keep order as best as possible
+ uint64_t tmp = e->refprobe_0_index;
+ e->refprobe_0_index = e->refprobe_1_index;
+ e->refprobe_1_index = tmp;
+ }*/
}
- has_alpha = false;
- }
+ //add directional lights
- e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
- e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
+ if (p_material->shader->spatial.unshaded) {
+ e->light_mode = LIGHTMODE_UNSHADED;
+ } else {
- if (p_material->shader->spatial.unshaded) {
- e->sort_key |= SORT_KEY_UNSHADED_FLAG;
- }
+ bool copy = false;
- if (!p_depth_pass) {
- e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
+ for (int i = 0; i < render_directional_lights; i++) {
- e->sort_key |= uint64_t(p_material->render_priority + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT;
- } else {
- // TODO
+ if (copy) {
+ RenderList::Element *e2 = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
+ if (!e2) {
+ break;
+ }
+ *e2 = *e; //this includes accum ptr :)
+ e = e2;
+ }
+
+ //directional sort key
+ e->light_type1 = 0;
+ e->light_type2 = 1;
+ e->light_index = i;
+
+ copy = true;
+ }
+
+ //add omni / spots
+
+ for (int i = 0; i < e->instance->light_instances.size(); i++) {
+
+ LightInstance *li = light_instance_owner.getornull(e->instance->light_instances[i]);
+
+ if (li->light_index >= render_light_instance_count) {
+ continue; // too many
+ }
+
+ if (copy) {
+ RenderList::Element *e2 = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
+ if (!e2) {
+ break;
+ }
+ *e2 = *e; //this includes accum ptr :)
+ e = e2;
+ }
+
+ //directional sort key
+ e->light_type1 = 1;
+ e->light_type2 = li->light_ptr->type == VisualServer::LIGHT_OMNI ? 0 : 1;
+ e->light_index = li->light_index;
+
+ copy = true;
+ }
+
+ if (e->instance->lightmap.is_valid()) {
+ e->light_mode = LIGHTMODE_LIGHTMAP;
+ } else if (!e->instance->lightmap_capture_data.empty()) {
+ e->light_mode = LIGHTMODE_LIGHTMAP_CAPTURE;
+ } else {
+ e->light_mode = LIGHTMODE_NORMAL;
+ }
+ }
}
+ // do not add anything here, as lights are duplicated elements..
+
if (p_material->shader->spatial.uses_time) {
VisualServerRaster::redraw_request();
}
@@ -770,6 +1040,13 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) {
+ render_pass++;
+ current_material_index = 0;
+ current_geometry_index = 0;
+ current_light_index = 0;
+ current_refprobe_index = 0;
+ current_shader_index = 0;
+
for (int i = 0; i < p_cull_count; i++) {
InstanceBase *instance = p_cull_result[i];
@@ -820,9 +1097,7 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p
} break;
- default: {
-
- } break;
+ default: {}
}
}
}
@@ -837,13 +1112,13 @@ static const GLenum gl_primitive[] = {
GL_TRIANGLE_FAN
};
-void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, bool p_alpha_pass, Size2i p_skeleton_tex_size) {
+bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, bool p_alpha_pass, Size2i p_skeleton_tex_size) {
// material parameters
state.scene_shader.set_custom_shader(p_material->shader->custom_code_id);
- state.scene_shader.bind();
+ bool shader_rebind = state.scene_shader.bind();
if (p_material->shader->spatial.no_depth_test) {
glDisable(GL_DEPTH_TEST);
@@ -922,203 +1197,178 @@ void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
glBindTexture(t->target, t->tex_id);
}
state.scene_shader.use_material((void *)p_material);
+
+ return shader_rebind;
}
void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton) {
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, p_skeleton != NULL);
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, !storage->config.float_texture_supported);
- // state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, true);
-
switch (p_element->instance->base_type) {
case VS::INSTANCE_MESH: {
RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry);
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, false);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_COLOR_INTERP, s->attribs[VS::ARRAY_COLOR].enabled);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV_INTERP, s->attribs[VS::ARRAY_TEX_UV].enabled);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV2_INTERP, s->attribs[VS::ARRAY_TEX_UV2].enabled);
-
- } break;
-
- case VS::INSTANCE_MULTIMESH: {
- RasterizerStorageGLES2::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES2::MultiMesh *>(p_element->owner);
- RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry);
-
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_COLOR_INTERP, true);
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, true);
-
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV_INTERP, s->attribs[VS::ARRAY_TEX_UV].enabled);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV2_INTERP, s->attribs[VS::ARRAY_TEX_UV2].enabled);
- } break;
-
- case VS::INSTANCE_IMMEDIATE: {
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, false);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_COLOR_INTERP, true);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV_INTERP, true);
- state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_UV2_INTERP, true);
- } break;
-
- default: {
-
- } break;
- }
-
- if (storage->config.float_texture_supported) {
- if (p_skeleton) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
- glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id);
- }
-
- return;
- }
-
- if (p_skeleton) {
- ERR_FAIL_COND(p_skeleton->use_2d);
-
- PoolVector<float> &transform_buffer = storage->resources.skeleton_transform_cpu_buffer;
-
- switch (p_element->instance->base_type) {
- case VS::INSTANCE_MESH: {
- RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry);
+ glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id);
- if (!s->attribs[VS::ARRAY_BONES].enabled || !s->attribs[VS::ARRAY_WEIGHTS].enabled) {
- break; // the whole instance has a skeleton, but this surface is not affected by it.
- }
+ if (s->index_array_len > 0) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id);
+ }
- // 3 * vec4 per vertex
- if (transform_buffer.size() < s->array_len * 12) {
- transform_buffer.resize(s->array_len * 12);
+ for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
+ if (s->attribs[i].enabled) {
+ glEnableVertexAttribArray(i);
+ glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset);
+ } else {
+ glDisableVertexAttribArray(i);
+ switch (i) {
+ case VS::ARRAY_NORMAL: {
+ glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1);
+ } break;
+ case VS::ARRAY_COLOR: {
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+
+ } break;
+ default: {}
+ }
}
+ }
- const size_t bones_offset = s->attribs[VS::ARRAY_BONES].offset;
- const size_t bones_stride = s->attribs[VS::ARRAY_BONES].stride;
- const size_t bone_weight_offset = s->attribs[VS::ARRAY_WEIGHTS].offset;
- const size_t bone_weight_stride = s->attribs[VS::ARRAY_WEIGHTS].stride;
-
- {
- PoolVector<float>::Write write = transform_buffer.write();
- float *buffer = write.ptr();
+ bool clear_skeleton_buffer = !storage->config.float_texture_supported;
- PoolVector<uint8_t>::Read vertex_array_read = s->data.read();
- const uint8_t *vertex_data = vertex_array_read.ptr();
+ if (p_skeleton) {
- for (int i = 0; i < s->array_len; i++) {
+ if (storage->config.float_texture_supported) {
+ //use float texture workflow
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+ glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id);
+ } else {
+ //use transform buffer workflow
+ ERR_FAIL_COND(p_skeleton->use_2d);
- // do magic
+ PoolVector<float> &transform_buffer = storage->resources.skeleton_transform_cpu_buffer;
- size_t bones[4];
- float bone_weight[4];
+ if (!s->attribs[VS::ARRAY_BONES].enabled || !s->attribs[VS::ARRAY_WEIGHTS].enabled) {
+ break; // the whole instance has a skeleton, but this surface is not affected by it.
+ }
- if (s->attribs[VS::ARRAY_BONES].type == GL_UNSIGNED_BYTE) {
- // read as byte
- const uint8_t *bones_ptr = vertex_data + bones_offset + (i * bones_stride);
- bones[0] = bones_ptr[0];
- bones[1] = bones_ptr[1];
- bones[2] = bones_ptr[2];
- bones[3] = bones_ptr[3];
- } else {
- // read as short
- const uint16_t *bones_ptr = (const uint16_t *)(vertex_data + bones_offset + (i * bones_stride));
- bones[0] = bones_ptr[0];
- bones[1] = bones_ptr[1];
- bones[2] = bones_ptr[2];
- bones[3] = bones_ptr[3];
- }
+ // 3 * vec4 per vertex
+ if (transform_buffer.size() < s->array_len * 12) {
+ transform_buffer.resize(s->array_len * 12);
+ }
- if (s->attribs[VS::ARRAY_WEIGHTS].type == GL_FLOAT) {
- // read as float
- const float *weight_ptr = (const float *)(vertex_data + bone_weight_offset + (i * bone_weight_stride));
- bone_weight[0] = weight_ptr[0];
- bone_weight[1] = weight_ptr[1];
- bone_weight[2] = weight_ptr[2];
- bone_weight[3] = weight_ptr[3];
- } else {
- // read as half
- const uint16_t *weight_ptr = (const uint16_t *)(vertex_data + bone_weight_offset + (i * bone_weight_stride));
- bone_weight[0] = (weight_ptr[0] / (float)0xFFFF);
- bone_weight[1] = (weight_ptr[1] / (float)0xFFFF);
- bone_weight[2] = (weight_ptr[2] / (float)0xFFFF);
- bone_weight[3] = (weight_ptr[3] / (float)0xFFFF);
+ const size_t bones_offset = s->attribs[VS::ARRAY_BONES].offset;
+ const size_t bones_stride = s->attribs[VS::ARRAY_BONES].stride;
+ const size_t bone_weight_offset = s->attribs[VS::ARRAY_WEIGHTS].offset;
+ const size_t bone_weight_stride = s->attribs[VS::ARRAY_WEIGHTS].stride;
+
+ {
+ PoolVector<float>::Write write = transform_buffer.write();
+ float *buffer = write.ptr();
+
+ PoolVector<uint8_t>::Read vertex_array_read = s->data.read();
+ const uint8_t *vertex_data = vertex_array_read.ptr();
+
+ for (int i = 0; i < s->array_len; i++) {
+
+ // do magic
+
+ size_t bones[4];
+ float bone_weight[4];
+
+ if (s->attribs[VS::ARRAY_BONES].type == GL_UNSIGNED_BYTE) {
+ // read as byte
+ const uint8_t *bones_ptr = vertex_data + bones_offset + (i * bones_stride);
+ bones[0] = bones_ptr[0];
+ bones[1] = bones_ptr[1];
+ bones[2] = bones_ptr[2];
+ bones[3] = bones_ptr[3];
+ } else {
+ // read as short
+ const uint16_t *bones_ptr = (const uint16_t *)(vertex_data + bones_offset + (i * bones_stride));
+ bones[0] = bones_ptr[0];
+ bones[1] = bones_ptr[1];
+ bones[2] = bones_ptr[2];
+ bones[3] = bones_ptr[3];
+ }
+
+ if (s->attribs[VS::ARRAY_WEIGHTS].type == GL_FLOAT) {
+ // read as float
+ const float *weight_ptr = (const float *)(vertex_data + bone_weight_offset + (i * bone_weight_stride));
+ bone_weight[0] = weight_ptr[0];
+ bone_weight[1] = weight_ptr[1];
+ bone_weight[2] = weight_ptr[2];
+ bone_weight[3] = weight_ptr[3];
+ } else {
+ // read as half
+ const uint16_t *weight_ptr = (const uint16_t *)(vertex_data + bone_weight_offset + (i * bone_weight_stride));
+ bone_weight[0] = (weight_ptr[0] / (float)0xFFFF);
+ bone_weight[1] = (weight_ptr[1] / (float)0xFFFF);
+ bone_weight[2] = (weight_ptr[2] / (float)0xFFFF);
+ bone_weight[3] = (weight_ptr[3] / (float)0xFFFF);
+ }
+
+ Transform transform;
+
+ Transform bone_transforms[4] = {
+ storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[0]),
+ storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[1]),
+ storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[2]),
+ storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[3]),
+ };
+
+ transform.origin =
+ bone_weight[0] * bone_transforms[0].origin +
+ bone_weight[1] * bone_transforms[1].origin +
+ bone_weight[2] * bone_transforms[2].origin +
+ bone_weight[3] * bone_transforms[3].origin;
+
+ transform.basis =
+ bone_transforms[0].basis * bone_weight[0] +
+ bone_transforms[1].basis * bone_weight[1] +
+ bone_transforms[2].basis * bone_weight[2] +
+ bone_transforms[3].basis * bone_weight[3];
+
+ float row[3][4] = {
+ { transform.basis[0][0], transform.basis[0][1], transform.basis[0][2], transform.origin[0] },
+ { transform.basis[1][0], transform.basis[1][1], transform.basis[1][2], transform.origin[1] },
+ { transform.basis[2][0], transform.basis[2][1], transform.basis[2][2], transform.origin[2] },
+ };
+
+ size_t transform_buffer_offset = i * 12;
+
+ copymem(&buffer[transform_buffer_offset], row, sizeof(row));
}
+ }
- size_t offset = i * 12;
-
- Transform transform;
-
- Transform bone_transforms[4] = {
- storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[0]),
- storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[1]),
- storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[2]),
- storage->skeleton_bone_get_transform(p_element->instance->skeleton, bones[3]),
- };
-
- transform.origin =
- bone_weight[0] * bone_transforms[0].origin +
- bone_weight[1] * bone_transforms[1].origin +
- bone_weight[2] * bone_transforms[2].origin +
- bone_weight[3] * bone_transforms[3].origin;
+ storage->_update_skeleton_transform_buffer(transform_buffer, s->array_len * 12);
- transform.basis =
- bone_transforms[0].basis * bone_weight[0] +
- bone_transforms[1].basis * bone_weight[1] +
- bone_transforms[2].basis * bone_weight[2] +
- bone_transforms[3].basis * bone_weight[3];
+ //enable transform buffer and bind it
+ glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer);
- float row[3][4] = {
- { transform.basis[0][0], transform.basis[0][1], transform.basis[0][2], transform.origin[0] },
- { transform.basis[1][0], transform.basis[1][1], transform.basis[1][2], transform.origin[1] },
- { transform.basis[2][0], transform.basis[2][1], transform.basis[2][2], transform.origin[2] },
- };
+ glEnableVertexAttribArray(INSTANCE_BONE_BASE + 0);
+ glEnableVertexAttribArray(INSTANCE_BONE_BASE + 1);
+ glEnableVertexAttribArray(INSTANCE_BONE_BASE + 2);
- size_t transform_buffer_offset = i * 12;
+ glVertexAttribPointer(INSTANCE_BONE_BASE + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 0));
+ glVertexAttribPointer(INSTANCE_BONE_BASE + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 1));
+ glVertexAttribPointer(INSTANCE_BONE_BASE + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 2));
- copymem(&buffer[transform_buffer_offset], row, sizeof(row));
- }
+ clear_skeleton_buffer = false;
}
+ }
- storage->_update_skeleton_transform_buffer(transform_buffer, s->array_len * 12);
- } break;
-
- default: {
-
- } break;
- }
- }
-}
-
-void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
+ if (clear_skeleton_buffer) {
- switch (p_element->instance->base_type) {
+ glDisableVertexAttribArray(INSTANCE_BONE_BASE + 0);
+ glDisableVertexAttribArray(INSTANCE_BONE_BASE + 1);
+ glDisableVertexAttribArray(INSTANCE_BONE_BASE + 2);
+ }
- case VS::INSTANCE_MESH: {
+ } break;
+ case VS::INSTANCE_MULTIMESH: {
RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry);
- // set up
-
- if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) {
- glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer);
-
- glEnableVertexAttribArray(VS::ARRAY_MAX + 0);
- glEnableVertexAttribArray(VS::ARRAY_MAX + 1);
- glEnableVertexAttribArray(VS::ARRAY_MAX + 2);
-
- glVertexAttribPointer(VS::ARRAY_MAX + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 0));
- glVertexAttribPointer(VS::ARRAY_MAX + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 1));
- glVertexAttribPointer(VS::ARRAY_MAX + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 2));
- } else {
- // just to make sure
- glDisableVertexAttribArray(VS::ARRAY_MAX + 0);
- glDisableVertexAttribArray(VS::ARRAY_MAX + 1);
- glDisableVertexAttribArray(VS::ARRAY_MAX + 2);
-
- glVertexAttrib4f(VS::ARRAY_MAX + 0, 1, 0, 0, 0);
- glVertexAttrib4f(VS::ARRAY_MAX + 1, 0, 1, 0, 0);
- glVertexAttrib4f(VS::ARRAY_MAX + 2, 0, 0, 1, 0);
- }
-
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id);
if (s->index_array_len > 0) {
@@ -1131,61 +1381,58 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset);
} else {
glDisableVertexAttribArray(i);
+ switch (i) {
+ case VS::ARRAY_NORMAL: {
+ glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1);
+ } break;
+ case VS::ARRAY_COLOR: {
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+
+ } break;
+ default: {}
+ }
}
}
- // drawing
-
- if (s->index_array_len > 0) {
- glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0);
- } else {
- glDrawArrays(gl_primitive[s->primitive], 0, s->array_len);
- }
-
- // tear down
-
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
- glDisableVertexAttribArray(i);
- }
+ // prepare multimesh (disable)
+ glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 0);
+ glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 1);
+ glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 2);
+ glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 3);
+ glDisableVertexAttribArray(INSTANCE_ATTRIB_BASE + 4);
+ glDisableVertexAttribArray(INSTANCE_BONE_BASE + 0);
+ glDisableVertexAttribArray(INSTANCE_BONE_BASE + 1);
+ glDisableVertexAttribArray(INSTANCE_BONE_BASE + 2);
- if (s->index_array_len > 0) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
+ } break;
- if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) {
- glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer);
+ case VS::INSTANCE_IMMEDIATE: {
+ } break;
- glDisableVertexAttribArray(VS::ARRAY_MAX + 0);
- glDisableVertexAttribArray(VS::ARRAY_MAX + 1);
- glDisableVertexAttribArray(VS::ARRAY_MAX + 2);
- }
+ default: {}
+ }
+}
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
- } break;
+ switch (p_element->instance->base_type) {
- case VS::INSTANCE_MULTIMESH: {
+ case VS::INSTANCE_MESH: {
- RasterizerStorageGLES2::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES2::MultiMesh *>(p_element->owner);
RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry);
- int amount = MIN(multi_mesh->size, multi_mesh->visible_instances);
- if (amount == -1) {
- amount = multi_mesh->size;
- }
+ // drawing
+ if (s->index_array_len > 0) {
+ glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0);
+ } else {
+ glDrawArrays(gl_primitive[s->primitive], 0, s->array_len);
+ }
+ /*
if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) {
+ //clean up after skeleton
glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer);
- glEnableVertexAttribArray(VS::ARRAY_MAX + 0);
- glEnableVertexAttribArray(VS::ARRAY_MAX + 1);
- glEnableVertexAttribArray(VS::ARRAY_MAX + 2);
-
- glVertexAttribPointer(VS::ARRAY_MAX + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 0));
- glVertexAttribPointer(VS::ARRAY_MAX + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 1));
- glVertexAttribPointer(VS::ARRAY_MAX + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 12, (const void *)(sizeof(float) * 4 * 2));
- } else {
- // just to make sure
glDisableVertexAttribArray(VS::ARRAY_MAX + 0);
glDisableVertexAttribArray(VS::ARRAY_MAX + 1);
glDisableVertexAttribArray(VS::ARRAY_MAX + 2);
@@ -1194,37 +1441,20 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
glVertexAttrib4f(VS::ARRAY_MAX + 1, 0, 1, 0, 0);
glVertexAttrib4f(VS::ARRAY_MAX + 2, 0, 0, 1, 0);
}
+*/
+ } break;
- glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id);
-
- if (s->index_array_len > 0) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id);
- }
-
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
- if (s->attribs[i].enabled) {
- glEnableVertexAttribArray(i);
- glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset);
- } else {
- glDisableVertexAttribArray(i);
- }
- }
+ case VS::INSTANCE_MULTIMESH: {
- glDisableVertexAttribArray(12); // transform 0
- glDisableVertexAttribArray(13); // transform 1
- glDisableVertexAttribArray(14); // transform 2
- glDisableVertexAttribArray(15); // color
- glDisableVertexAttribArray(8); // custom data
+ RasterizerStorageGLES2::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES2::MultiMesh *>(p_element->owner);
+ RasterizerStorageGLES2::Surface *s = static_cast<RasterizerStorageGLES2::Surface *>(p_element->geometry);
- if (!s->attribs[VS::ARRAY_COLOR].enabled) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ int amount = MIN(multi_mesh->size, multi_mesh->visible_instances);
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+ if (amount == -1) {
+ amount = multi_mesh->size;
}
- glVertexAttrib4f(15, 1, 1, 1, 1);
- glVertexAttrib4f(8, 0, 0, 0, 0);
-
int stride = multi_mesh->color_floats + multi_mesh->custom_data_floats + multi_mesh->xform_floats;
int color_ofs = multi_mesh->xform_floats;
@@ -1232,49 +1462,34 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
// drawing
+ const float *base_buffer = multi_mesh->data.ptr();
+
for (int i = 0; i < amount; i++) {
- float *buffer = &multi_mesh->data.write[i * stride];
+ const float *buffer = base_buffer + i * stride;
{
- // inline of multimesh_get_transform since it's such a pain
- // to get a RID from here...
- Transform transform;
-
- transform.basis.elements[0][0] = buffer[0];
- transform.basis.elements[0][1] = buffer[1];
- transform.basis.elements[0][2] = buffer[2];
- transform.origin.x = buffer[3];
- transform.basis.elements[1][0] = buffer[4];
- transform.basis.elements[1][1] = buffer[5];
- transform.basis.elements[1][2] = buffer[6];
- transform.origin.y = buffer[7];
- transform.basis.elements[2][0] = buffer[8];
- transform.basis.elements[2][1] = buffer[9];
- transform.basis.elements[2][2] = buffer[10];
- transform.origin.z = buffer[11];
-
- float row[3][4] = {
- { transform.basis[0][0], transform.basis[0][1], transform.basis[0][2], transform.origin[0] },
- { transform.basis[1][0], transform.basis[1][1], transform.basis[1][2], transform.origin[1] },
- { transform.basis[2][0], transform.basis[2][1], transform.basis[2][2], transform.origin[2] },
- };
-
- glVertexAttrib4fv(12, row[0]);
- glVertexAttrib4fv(13, row[1]);
- glVertexAttrib4fv(14, row[2]);
+
+ glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 0, &buffer[0]);
+ glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 1, &buffer[4]);
+ glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 2, &buffer[8]);
}
if (multi_mesh->color_floats) {
if (multi_mesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
uint8_t *color_data = (uint8_t *)(buffer + color_ofs);
- glVertexAttrib4f(15, color_data[0] / 255.0, color_data[1] / 255.0, color_data[2] / 255.0, color_data[3] / 255.0);
+ glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, color_data[0] / 255.0, color_data[1] / 255.0, color_data[2] / 255.0, color_data[3] / 255.0);
} else {
- glVertexAttrib4fv(15, buffer + color_ofs);
+ glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs);
}
}
if (multi_mesh->custom_data_floats) {
- glVertexAttrib4fv(8, buffer + custom_data_ofs);
+ if (multi_mesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+ uint8_t *custom_data = (uint8_t *)(buffer + custom_data_ofs);
+ glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 4, custom_data[0] / 255.0, custom_data[1] / 255.0, custom_data[2] / 255.0, custom_data[3] / 255.0);
+ } else {
+ glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 4, buffer + custom_data_ofs);
+ }
}
if (s->index_array_len > 0) {
@@ -1284,25 +1499,6 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
}
}
- // tear down
-
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
- glDisableVertexAttribArray(i);
- }
-
- if (s->index_array_len > 0) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
-
- if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) {
- glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer);
-
- glDisableVertexAttribArray(VS::ARRAY_MAX + 0);
- glDisableVertexAttribArray(VS::ARRAY_MAX + 1);
- glDisableVertexAttribArray(VS::ARRAY_MAX + 2);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
} break;
case VS::INSTANCE_IMMEDIATE: {
@@ -1416,508 +1612,696 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
}
} break;
+ default: {}
}
}
-void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_directional_lights, int p_directional_light_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add) {
+void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
-
- Vector2 screen_pixel_size;
- screen_pixel_size.x = 1.0 / storage->frame.current_rt->width;
- screen_pixel_size.y = 1.0 / storage->frame.current_rt->height;
+ //turn off all by default
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, false);
- bool use_radiance_map = false;
+ if (!p_light) { //no light, return off
+ return;
+ }
- VMap<RID, Vector<RenderList::Element *> > lit_objects;
+ //turn on lighting
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, true);
- for (int i = 0; i < p_element_count; i++) {
- RenderList::Element *e = p_elements[i];
+ switch (p_light->light_ptr->type) {
+ case VS::LIGHT_DIRECTIONAL: {
- RasterizerStorageGLES2::Material *material = e->material;
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, true);
+ switch (p_light->light_ptr->directional_shadow_mode) {
+ case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
+ //no need
+ } break;
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
- RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
+ } break;
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
+ } break;
+ }
- if (p_base_env) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
- glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env);
- use_radiance_map = true;
- }
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, use_radiance_map);
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, p_light->light_ptr->directional_blend_splits);
+ if (!state.render_no_shadows && p_light->light_ptr->shadow) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
+ }
- if (material->shader->spatial.unshaded) {
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
- } else {
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, use_radiance_map);
- }
+ } break;
+ case VS::LIGHT_OMNI: {
+
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true);
+ if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
+ }
+ } break;
+ case VS::LIGHT_SPOT: {
+
+ state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true);
+ if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
+ }
+ } break;
+ }
+}
- // opaque pass
+void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shadow_atlas, const Transform &p_view_transform) {
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, false);
+ RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
- _setup_geometry(e, skeleton);
+ //common parameters
+ float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+ float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
+ float sign = light_ptr->negative ? -1 : 1;
- _setup_material(material, p_reverse_cull, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPECULAR, specular);
+ Color color = light_ptr->color * sign * energy * Math_PI;
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, color);
- if (use_radiance_map) {
- state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform);
- }
+ //specific parameters
- if (p_shadow) {
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_BIAS, p_shadow_bias);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_NORMAL_BIAS, p_shadow_normal_bias);
- }
+ switch (light_ptr->type) {
+ case VS::LIGHT_DIRECTIONAL: {
+ //not using inverse for performance, view should be normalized anyway
+ Vector3 direction = p_view_transform.basis.xform_inv(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
- if (p_env) {
- state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, p_env->bg_energy);
- state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, p_env->ambient_sky_contribution);
- state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, p_env->ambient_color);
- state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, p_env->ambient_energy);
+ CameraMatrix matrices[4];
- } else {
- state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0);
- state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0);
- state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, Color(1.0, 1.0, 1.0, 1.0));
- state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0);
- }
+ if (!state.render_no_shadows && light_ptr->shadow && directional_shadow.depth) {
- glEnable(GL_BLEND);
+ int shadow_count = 0;
+ Color split_offsets;
- if (p_alpha_pass || p_directional_add) {
- int desired_blend_mode;
- if (p_directional_add) {
- desired_blend_mode = RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD;
- } else {
- desired_blend_mode = material->shader->spatial.blend_mode;
- }
+ switch (light_ptr->directional_shadow_mode) {
+ case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
+ shadow_count = 1;
+ } break;
- switch (desired_blend_mode) {
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
+ shadow_count = 2;
+ } break;
- case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX: {
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
+ shadow_count = 4;
+ } break;
+ }
- } break;
- case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD: {
+ for (int k = 0; k < shadow_count; k++) {
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(p_alpha_pass ? GL_SRC_ALPHA : GL_ONE, GL_ONE);
+ uint32_t x = light->directional_rect.position.x;
+ uint32_t y = light->directional_rect.position.y;
+ uint32_t width = light->directional_rect.size.x;
+ uint32_t height = light->directional_rect.size.y;
- } break;
- case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_SUB: {
+ if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- } break;
- case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MUL: {
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
- } else {
- glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
- }
+ width /= 2;
+ height /= 2;
- } break;
- }
- } else {
- // no blend mode given - assume mix
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- }
+ if (k == 0) {
- state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
- state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
- state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
- state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
+ } else if (k == 1) {
+ x += width;
+ } else if (k == 2) {
+ y += height;
+ } else if (k == 3) {
+ x += width;
+ y += height;
+ }
- state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+ } else if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
- state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
- state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
- state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
+ height /= 2;
- _render_geometry(e);
+ if (k == 0) {
- if (material->shader->spatial.unshaded)
- continue;
+ } else {
+ y += height;
+ }
+ }
- if (p_shadow)
- continue;
+ split_offsets[k] = light->shadow_transform[k].split;
- for (int light = 0; light < e->instance->light_instances.size(); light++) {
+ Transform modelview = (p_view_transform.inverse() * light->shadow_transform[k].transform).affine_inverse();
- RID light_instance = e->instance->light_instances[light];
+ CameraMatrix bias;
+ bias.set_light_bias();
+ CameraMatrix rectm;
+ Rect2 atlas_rect = Rect2(float(x) / directional_shadow.size, float(y) / directional_shadow.size, float(width) / directional_shadow.size, float(height) / directional_shadow.size);
+ rectm.set_light_atlas_rect(atlas_rect);
- lit_objects[light_instance].push_back(e);
- }
- }
+ CameraMatrix shadow_mtx = rectm * bias * light->shadow_transform[k].camera * modelview;
+ matrices[k] = shadow_mtx;
- if (p_shadow) {
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
- return;
- }
+ /*Color light_clamp;
+ light_clamp[0] = atlas_rect.position.x;
+ light_clamp[1] = atlas_rect.position.y;
+ light_clamp[2] = atlas_rect.size.x;
+ light_clamp[3] = atlas_rect.size.y;*/
+ }
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, true);
+ // state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
+ state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / directional_shadow.size, 1.0 / directional_shadow.size));
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPLIT_OFFSETS, split_offsets);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, matrices[0]);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX2, matrices[1]);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX3, matrices[2]);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX4, matrices[3]);
+ }
+ } break;
+ case VS::LIGHT_OMNI: {
- glEnable(GL_BLEND);
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ Vector3 position = p_view_transform.xform_inv(light->transform.origin);
- for (int lo = 0; lo < lit_objects.size(); lo++) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
- RID key = lit_objects.getk(lo);
+ float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
- LightInstance *light = light_instance_owner.getornull(key);
- RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
+ float attenuation = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
- const Vector<RenderList::Element *> &list = lit_objects.getv(lo);
+ if (!state.render_no_shadows && light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
- for (int i = 0; i < list.size(); i++) {
+ uint32_t key = shadow_atlas->shadow_owners[light->self];
- RenderList::Element *e = list[i];
- RasterizerStorageGLES2::Material *material = e->material;
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
- RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
+ ERR_BREAK(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size());
- {
- _setup_geometry(e, skeleton);
+ uint32_t atlas_size = shadow_atlas->size;
+ uint32_t quadrant_size = atlas_size >> 1;
- _setup_material(material, p_reverse_cull, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
- if (shadow_atlas != NULL) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- }
+ uint32_t x = (quadrant & 1) * quadrant_size;
+ uint32_t y = (quadrant >> 1) * quadrant_size;
- state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
- state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
- state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
- state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+ uint32_t width = shadow_size;
+ uint32_t height = shadow_size;
- state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
- state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
- state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
- }
+ if (light->light_ptr->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
+ height /= 2;
+ } else {
+ width /= 2;
+ }
- switch (light_ptr->type) {
- case VS::LIGHT_OMNI: {
+ Transform proj = (p_view_transform.inverse() * light->transform).inverse();
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)1);
+ Color light_clamp;
+ light_clamp[0] = float(x) / atlas_size;
+ light_clamp[1] = float(y) / atlas_size;
+ light_clamp[2] = float(width) / atlas_size;
+ light_clamp[3] = float(height) / atlas_size;
- Vector3 position = p_view_transform.inverse().xform(light->transform.origin);
+ state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / shadow_atlas->size, 1.0 / shadow_atlas->size));
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, proj);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
+ }
+ } break;
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
+ case VS::LIGHT_SPOT: {
- float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
+ Vector3 position = p_view_transform.xform_inv(light->transform.origin);
- Color attenuation = Color(0.0, 0.0, 0.0, 0.0);
- attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
- if (light_ptr->shadow && shadow_atlas->shadow_owners.has(light->self)) {
+ Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
+ float attenuation = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
+ float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
+ float spot_attenuation = light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
+ float angle = light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE];
+ angle = Math::cos(Math::deg2rad(angle));
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_RANGE, spot_attenuation);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ANGLE, angle);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
- uint32_t key = shadow_atlas->shadow_owners[light->self];
+ if (!state.render_no_shadows && light->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
+ uint32_t key = shadow_atlas->shadow_owners[light->self];
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
- ERR_CONTINUE(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size());
+ ERR_BREAK(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size());
- uint32_t atlas_size = shadow_atlas->size;
- uint32_t quadrant_size = atlas_size >> 1;
+ uint32_t atlas_size = shadow_atlas->size;
+ uint32_t quadrant_size = atlas_size >> 1;
- uint32_t x = (quadrant & 1) * quadrant_size;
- uint32_t y = (quadrant >> 1) * quadrant_size;
+ uint32_t x = (quadrant & 1) * quadrant_size;
+ uint32_t y = (quadrant >> 1) * quadrant_size;
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- uint32_t width = shadow_size;
- uint32_t height = shadow_size;
+ uint32_t width = shadow_size;
+ uint32_t height = shadow_size;
- if (light->light_ptr->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
- height /= 2;
- } else {
- width /= 2;
- }
+ Rect2 rect(float(x) / atlas_size, float(y) / atlas_size, float(width) / atlas_size, float(height) / atlas_size);
- Transform proj = (p_view_transform.inverse() * light->transform).inverse();
+ Color light_clamp;
+ light_clamp[0] = rect.position.x;
+ light_clamp[1] = rect.position.y;
+ light_clamp[2] = rect.size.x;
+ light_clamp[3] = rect.size.y;
- Color light_clamp;
- light_clamp[0] = float(x) / atlas_size;
- light_clamp[1] = float(y) / atlas_size;
- light_clamp[2] = float(width) / atlas_size;
- light_clamp[3] = float(height) / atlas_size;
+ Transform modelview = (p_view_transform.inverse() * light->transform).inverse();
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, proj);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
+ CameraMatrix bias;
+ bias.set_light_bias();
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_HAS_SHADOW, 1.0);
- } else {
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_HAS_SHADOW, 0.0);
- }
- } break;
+ CameraMatrix rectm;
+ rectm.set_light_atlas_rect(rect);
- case VS::LIGHT_SPOT: {
- Vector3 position = p_view_transform.inverse().xform(light->transform.origin);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)2);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
+ CameraMatrix shadow_matrix = rectm * bias * light->shadow_transform[0].camera * modelview;
- Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
- Color attenuation = Color(0.0, 0.0, 0.0, 0.0);
- attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
- float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
- float spot_attenuation = light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
- float angle = light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE];
- angle = Math::cos(Math::deg2rad(angle));
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_RANGE, spot_attenuation);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ANGLE, angle);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
+ state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_PIXEL_SIZE, Size2(1.0 / shadow_atlas->size, 1.0 / shadow_atlas->size));
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, shadow_matrix);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
+ }
- if (light->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) {
- uint32_t key = shadow_atlas->shadow_owners[light->self];
+ } break;
+ default: {}
+ }
+}
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x03;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+void RasterizerSceneGLES2::_setup_refprobes(ReflectionProbeInstance *p_refprobe1, ReflectionProbeInstance *p_refprobe2, const Transform &p_view_transform, Environment *p_env) {
- ERR_CONTINUE(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size());
+ if (p_refprobe1) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_USE_BOX_PROJECT, p_refprobe1->probe_ptr->box_projection);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_BOX_EXTENTS, p_refprobe1->probe_ptr->extents);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_BOX_OFFSET, p_refprobe1->probe_ptr->origin_offset);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_EXTERIOR, !p_refprobe1->probe_ptr->interior);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_INTENSITY, p_refprobe1->probe_ptr->intensity);
- uint32_t atlas_size = shadow_atlas->size;
- uint32_t quadrant_size = atlas_size >> 1;
+ Color ambient;
+ if (p_refprobe1->probe_ptr->interior) {
+ ambient = p_refprobe1->probe_ptr->interior_ambient * p_refprobe1->probe_ptr->interior_ambient_energy;
+ ambient.a = p_refprobe1->probe_ptr->interior_ambient_probe_contrib;
+ } else if (p_env) {
+ ambient = p_env->ambient_color * p_env->ambient_energy;
+ ambient.a = p_env->ambient_sky_contribution;
+ }
- uint32_t x = (quadrant & 1) * quadrant_size;
- uint32_t y = (quadrant >> 1) * quadrant_size;
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_AMBIENT, ambient);
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ Transform proj = (p_view_transform.inverse() * p_refprobe1->transform).affine_inverse();
- uint32_t width = shadow_size;
- uint32_t height = shadow_size;
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE1_LOCAL_MATRIX, proj);
+ }
- Rect2 rect(float(x) / atlas_size, float(y) / atlas_size, float(width) / atlas_size, float(height) / atlas_size);
+ if (p_refprobe2) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_USE_BOX_PROJECT, p_refprobe2->probe_ptr->box_projection);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_EXTENTS, p_refprobe2->probe_ptr->extents);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_OFFSET, p_refprobe2->probe_ptr->origin_offset);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, !p_refprobe2->probe_ptr->interior);
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_INTENSITY, p_refprobe2->probe_ptr->intensity);
+
+ Color ambient;
+ if (p_refprobe2->probe_ptr->interior) {
+ ambient = p_refprobe2->probe_ptr->interior_ambient * p_refprobe2->probe_ptr->interior_ambient_energy;
+ ambient.a = p_refprobe2->probe_ptr->interior_ambient_probe_contrib;
+ } else if (p_env) {
+ ambient = p_env->ambient_color * p_env->ambient_energy;
+ ambient.a = p_env->ambient_sky_contribution;
+ }
- Color light_clamp;
- light_clamp[0] = rect.position.x;
- light_clamp[1] = rect.position.y;
- light_clamp[2] = rect.size.x;
- light_clamp[3] = rect.size.y;
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_AMBIENT, ambient);
- Transform modelview = (p_view_transform.inverse() * light->transform).inverse();
+ Transform proj = (p_view_transform.inverse() * p_refprobe2->transform).affine_inverse();
- CameraMatrix bias;
- bias.set_light_bias();
+ state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_LOCAL_MATRIX, proj);
+ }
+}
- CameraMatrix rectm;
- rectm.set_light_atlas_rect(rect);
+void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow) {
- CameraMatrix shadow_matrix = rectm * bias * light->shadow_transform[0].camera * modelview;
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_HAS_SHADOW, 1.0);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX, shadow_matrix);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
+ Vector2 screen_pixel_size = state.screen_pixel_size;
- } else {
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_HAS_SHADOW, 0.0);
- }
+ bool use_radiance_map = false;
+ if (!p_shadow && p_base_env) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env);
+ use_radiance_map = true;
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, true); //since prev unshaded is false, this needs to be true if exists
+ }
- } break;
+ bool prev_unshaded = false;
+ bool prev_instancing = false;
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false);
+ RasterizerStorageGLES2::Material *prev_material = NULL;
+ RasterizerStorageGLES2::Geometry *prev_geometry = NULL;
+ RasterizerStorageGLES2::Skeleton *prev_skeleton = NULL;
+ RasterizerStorageGLES2::GeometryOwner *prev_owner = NULL;
- default: break;
- }
+ Transform view_transform_inverse = p_view_transform.inverse();
+ CameraMatrix projection_inverse = p_projection.inverse();
- float energy = light->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- float specular = light->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
+ bool prev_base_pass = false;
+ LightInstance *prev_light = NULL;
+ bool prev_vertex_lit = false;
+ ReflectionProbeInstance *prev_refprobe_1 = NULL;
+ ReflectionProbeInstance *prev_refprobe_2 = NULL;
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ENERGY, energy);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, light->light_ptr->color.to_linear());
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPECULAR, specular);
+ int prev_blend_mode = -2; //will always catch the first go
- _render_geometry(e);
- }
+ if (p_alpha_pass) {
+ glEnable(GL_BLEND);
+ } else {
+ glDisable(GL_BLEND);
}
- for (int dl = 0; dl < p_directional_light_count; dl++) {
- RID light_rid = p_directional_lights[dl];
- LightInstance *light = light_instance_owner.getornull(light_rid);
- RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
-
- switch (light_ptr->directional_shadow_mode) {
- case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
- } break;
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
- } break;
-
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
- } break;
- default:
- break;
- }
+ RasterizerStorageGLES2::Texture *prev_lightmap = NULL;
+ float lightmap_energy = 1.0;
+ bool prev_use_lightmap_capture = false;
- for (int i = 0; i < p_element_count; i++) {
-
- RenderList::Element *e = p_elements[i];
- RasterizerStorageGLES2::Material *material = e->material;
- RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
+ for (int i = 0; i < p_element_count; i++) {
+ RenderList::Element *e = p_elements[i];
- {
- _setup_material(material, p_reverse_cull, false, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+ RasterizerStorageGLES2::Material *material = e->material;
- if (directional_shadow.depth) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); // TODO move into base pass
- glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+ bool rebind = false;
+ bool accum_pass = *e->use_accum_ptr;
+ *e->use_accum_ptr = true; //set to accum for next time this is found
+ LightInstance *light = NULL;
+ ReflectionProbeInstance *refprobe_1 = NULL;
+ ReflectionProbeInstance *refprobe_2 = NULL;
+ RasterizerStorageGLES2::Texture *lightmap = NULL;
+ bool use_lightmap_capture = false;
+ bool rebind_light = false;
+ bool rebind_reflection = false;
+ bool rebind_lightmap = false;
+
+ if (!p_shadow) {
+
+ bool unshaded = material->shader->spatial.unshaded;
+
+ if (unshaded != prev_unshaded) {
+ rebind = true;
+ if (unshaded) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, true);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, false);
+ } else {
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, use_radiance_map);
}
- state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
- state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
- state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
- state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
+ prev_unshaded = unshaded;
+ }
- state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+ bool base_pass = !accum_pass && !unshaded; //conditions for a base pass
- state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
- state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
- state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
+ if (base_pass != prev_base_pass) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::BASE_PASS, base_pass);
+ rebind = true;
+ prev_base_pass = base_pass;
}
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)0);
- Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
- float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
+ if (!unshaded && e->light_index < RenderList::MAX_LIGHTS) {
+ light = render_light_instances[e->light_index];
+ }
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ENERGY, energy);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPECULAR, specular);
+ if (light != prev_light) {
- float sign = light_ptr->negative ? -1 : 1;
+ _setup_light_type(light, shadow_atlas);
+ rebind = true;
+ rebind_light = true;
+ }
- Color linear_col = light_ptr->color.to_linear();
- Color color;
- for (int c = 0; c < 3; c++)
- color[c] = linear_col[c] * sign * energy * Math_PI;
+ int blend_mode = p_alpha_pass ? material->shader->spatial.blend_mode : -1; // -1 no blend, no mix
- color[3] = 0;
+ if (accum_pass) { //accum pass force pass
+ blend_mode = RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD;
+ }
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, color);
+ if (prev_blend_mode != blend_mode) {
- CameraMatrix matrices[4];
+ if (prev_blend_mode == -1 && blend_mode != -1) {
+ //does blend
+ glEnable(GL_BLEND);
+ } else if (blend_mode == -1 && prev_blend_mode != -1) {
+ //do not blend
+ glDisable(GL_BLEND);
+ }
- if (light_ptr->shadow && directional_shadow.depth) {
+ switch (blend_mode) {
+ //-1 not handled because not blend is enabled anyway
+ case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MIX: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- int shadow_count = 0;
- Color split_offsets;
+ } break;
+ case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_ADD: {
+
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(p_alpha_pass ? GL_SRC_ALPHA : GL_ONE, GL_ONE);
- switch (light_ptr->directional_shadow_mode) {
- case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
- shadow_count = 1;
} break;
+ case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_SUB: {
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
- shadow_count = 2;
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
} break;
+ case RasterizerStorageGLES2::Shader::Spatial::BLEND_MODE_MUL: {
+ glBlendEquation(GL_FUNC_ADD);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
+ } else {
+ glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
+ }
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
- shadow_count = 4;
} break;
}
- for (int k = 0; k < shadow_count; k++) {
+ prev_blend_mode = blend_mode;
+ }
- uint32_t x = light->directional_rect.position.x;
- uint32_t y = light->directional_rect.position.y;
- uint32_t width = light->directional_rect.size.x;
- uint32_t height = light->directional_rect.size.y;
+ //condition to enable vertex lighting on this object
+ bool vertex_lit = light && (material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading) && !unshaded;
- if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+ if (vertex_lit != prev_vertex_lit) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, vertex_lit);
+ prev_vertex_lit = vertex_lit;
+ }
- width /= 2;
- height /= 2;
+ if (!unshaded && !accum_pass && e->refprobe_0_index != RenderList::MAX_REFLECTION_PROBES) {
+ ERR_FAIL_INDEX(e->refprobe_0_index, reflection_probe_count);
+ refprobe_1 = reflection_probe_instances[e->refprobe_0_index];
+ }
+ if (!unshaded && !accum_pass && e->refprobe_1_index != RenderList::MAX_REFLECTION_PROBES) {
+ ERR_FAIL_INDEX(e->refprobe_1_index, reflection_probe_count);
+ refprobe_2 = reflection_probe_instances[e->refprobe_1_index];
+ }
- if (k == 0) {
+ if (refprobe_1 != prev_refprobe_1 || refprobe_2 != prev_refprobe_2) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != NULL);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != NULL);
+ if (refprobe_1 != NULL && refprobe_1 != prev_refprobe_1) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap);
+ }
+ if (refprobe_2 != NULL && refprobe_2 != prev_refprobe_2) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap);
+ }
+ rebind = true;
+ rebind_reflection = true;
+ }
- } else if (k == 1) {
- x += width;
- } else if (k == 2) {
- y += height;
- } else if (k == 3) {
- x += width;
- y += height;
- }
+ use_lightmap_capture = !unshaded && !accum_pass && !e->instance->lightmap_capture_data.empty();
- } else if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+ if (use_lightmap_capture != prev_use_lightmap_capture) {
- height /= 2;
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, use_lightmap_capture);
+ rebind = true;
+ }
- if (k == 0) {
+ if (!unshaded && !accum_pass && e->instance->lightmap.is_valid()) {
- } else {
- y += height;
- }
+ lightmap = storage->texture_owner.getornull(e->instance->lightmap);
+ lightmap_energy = 1.0;
+ if (lightmap) {
+ RasterizerStorageGLES2::LightmapCapture *capture = storage->lightmap_capture_data_owner.getornull(e->instance->lightmap_capture->base);
+ if (capture) {
+ lightmap_energy = capture->energy;
}
+ }
+ }
- split_offsets[k] = light->shadow_transform[k].split;
+ if (lightmap != prev_lightmap) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, lightmap != NULL);
+ if (lightmap != NULL) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+ glBindTexture(GL_TEXTURE_2D, lightmap->tex_id);
+ }
+ rebind = true;
+ rebind_lightmap = true;
+ }
+ }
- Transform modelview = (p_view_transform * light->shadow_transform[k].transform).inverse();
+ bool instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH;
- CameraMatrix bias;
- bias.set_light_bias();
- CameraMatrix rectm;
- Rect2 atlas_rect = Rect2(float(x) / directional_shadow.size, float(y) / directional_shadow.size, float(width) / directional_shadow.size, float(height) / directional_shadow.size);
- rectm.set_light_atlas_rect(atlas_rect);
+ if (instancing != prev_instancing) {
- CameraMatrix shadow_mtx = rectm * bias * light->shadow_transform[k].camera * modelview;
- matrices[k] = shadow_mtx.inverse();
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, instancing);
+ rebind = true;
+ }
- Color light_clamp;
- light_clamp[0] = atlas_rect.position.x;
- light_clamp[1] = atlas_rect.position.y;
- light_clamp[2] = atlas_rect.size.x;
- light_clamp[3] = atlas_rect.size.y;
+ RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_HAS_SHADOW, 1.0);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_CLAMP, light_clamp);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPLIT_OFFSETS, split_offsets);
- }
+ if (skeleton != prev_skeleton) {
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX1, matrices[0]);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX2, matrices[1]);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX3, matrices[2]);
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX4, matrices[3]);
+ if (skeleton) {
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, true);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, !storage->config.float_texture_supported);
} else {
- state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_HAS_SHADOW, 0.0);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, false);
}
- _render_geometry(e);
+ rebind = true;
+ }
+
+ if (e->owner != prev_owner || e->geometry != prev_geometry || skeleton != prev_skeleton) {
+ _setup_geometry(e, skeleton);
}
- }
- state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, false);
+ bool shader_rebind = false;
+ if (rebind || material != prev_material) {
+ shader_rebind = _setup_material(material, p_reverse_cull, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+ }
+
+ if (i == 0 || shader_rebind) { //first time must rebind
+
+ if (p_shadow) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_BIAS, p_shadow_bias);
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_NORMAL_BIAS, p_shadow_normal_bias);
+ if (state.shadow_is_dual_parabolloid) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_DUAL_PARABOLOID_RENDER_SIDE, state.dual_parbolloid_direction);
+ state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_DUAL_PARABOLOID_RENDER_ZFAR, state.dual_parbolloid_zfar);
+ }
+ } else {
+ if (use_radiance_map) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform);
+ }
+
+ if (p_env) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, p_env->bg_energy);
+ state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, p_env->ambient_sky_contribution);
+
+ state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, p_env->ambient_color);
+ state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, p_env->ambient_energy);
+
+ } else {
+ state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0);
+ state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0);
+ state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, Color(1.0, 1.0, 1.0, 1.0));
+ state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0);
+ }
+
+ //rebind all these
+ rebind_light = true;
+ rebind_reflection = true;
+ rebind_lightmap = true;
+ }
+
+ state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, view_transform_inverse);
+ state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
+ state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
+ state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, projection_inverse);
+
+ state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+
+ state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
+ state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
+ }
+
+ if (rebind_light && light) {
+ _setup_light(light, shadow_atlas, p_view_transform);
+ }
+
+ if (rebind_reflection && (refprobe_1 || refprobe_2)) {
+ _setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env);
+ }
+ if (rebind_lightmap && lightmap) {
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_ENERGY, lightmap_energy);
+ }
+
+ state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
+
+ if (use_lightmap_capture) { //this is per instance, must be set always if present
+ glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr());
+ state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false);
+ }
+
+ _render_geometry(e);
+
+ prev_geometry = e->geometry;
+ prev_owner = e->owner;
+ prev_material = material;
+ prev_skeleton = skeleton;
+ prev_instancing = instancing;
+ prev_light = light;
+ prev_refprobe_1 = refprobe_1;
+ prev_refprobe_2 = refprobe_2;
+ prev_lightmap = lightmap;
+ prev_use_lightmap_capture = use_lightmap_capture;
+ }
+
+ _setup_light_type(NULL, NULL); //clear light stuff
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::BASE_PASS, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false);
}
void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) {
@@ -2012,10 +2396,84 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C
void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
- glEnable(GL_BLEND);
+ GLuint current_fb = 0;
+ Environment *env = NULL;
+
+ int viewport_width, viewport_height;
+
+ if (p_reflection_probe.is_valid()) {
+ ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
+ ERR_FAIL_COND(!probe);
+ state.render_no_shadows = !probe->probe_ptr->enable_shadows;
+
+ if (!probe->probe_ptr->interior) { //use env only if not interior
+ env = environment_owner.getornull(p_environment);
+ }
+
+ current_fb = probe->fbo[p_reflection_probe_pass];
+ state.screen_pixel_size.x = 1.0 / probe->probe_ptr->resolution;
+ state.screen_pixel_size.y = 1.0 / probe->probe_ptr->resolution;
+
+ viewport_width = probe->probe_ptr->resolution;
+ viewport_height = probe->probe_ptr->resolution;
+
+ } else {
+ state.render_no_shadows = false;
+ current_fb = storage->frame.current_rt->fbo;
+ env = environment_owner.getornull(p_environment);
+ state.screen_pixel_size.x = 1.0 / storage->frame.current_rt->width;
+ state.screen_pixel_size.y = 1.0 / storage->frame.current_rt->height;
+ viewport_width = storage->frame.current_rt->width;
+ viewport_height = storage->frame.current_rt->height;
+ }
+ //push back the directional lights
+
+ if (p_light_cull_count) {
+ //harcoded limit of 256 lights
+ render_light_instance_count = MIN(RenderList::MAX_LIGHTS, p_light_cull_count);
+ render_light_instances = (LightInstance **)alloca(sizeof(LightInstance *) * render_light_instance_count);
+ render_directional_lights = 0;
- GLuint current_fb = storage->frame.current_rt->fbo;
- Environment *env = environment_owner.getornull(p_environment);
+ //doing this because directional lights are at the end, put them at the beginning
+ int index = 0;
+ for (int i = render_light_instance_count - 1; i >= 0; i--) {
+ RID light_rid = p_light_cull_result[i];
+
+ LightInstance *light = light_instance_owner.getornull(light_rid);
+
+ if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) {
+ render_directional_lights++;
+ //as goin in reverse, directional lights are always first anyway
+ }
+
+ light->light_index = index;
+ render_light_instances[index] = light;
+
+ index++;
+ }
+
+ } else {
+ render_light_instances = NULL;
+ render_directional_lights = 0;
+ render_light_instance_count = 0;
+ }
+
+ if (p_reflection_probe_cull_count) {
+
+ reflection_probe_instances = (ReflectionProbeInstance **)alloca(sizeof(ReflectionProbeInstance *) * p_reflection_probe_cull_count);
+ reflection_probe_count = p_reflection_probe_cull_count;
+ for (int i = 0; i < p_reflection_probe_cull_count; i++) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_cull_result[i]);
+ ERR_CONTINUE(!rpi);
+ rpi->last_pass = render_pass + 1; //will be incremented later
+ rpi->index = i;
+ reflection_probe_instances[i] = rpi;
+ }
+
+ } else {
+ reflection_probe_instances = NULL;
+ reflection_probe_count = 0;
+ }
// render list stuff
@@ -2025,6 +2483,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
// other stuff
glBindFramebuffer(GL_FRAMEBUFFER, current_fb);
+ glViewport(0, 0, viewport_width, viewport_height);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
@@ -2068,34 +2527,23 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
}
}
- Vector<RID> directional_lights;
-
- for (int i = 0; i < p_light_cull_count; i++) {
- RID light_rid = p_light_cull_result[i];
-
- LightInstance *light = light_instance_owner.getornull(light_rid);
-
- if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) {
- directional_lights.push_back(light_rid);
- }
- }
-
// render opaque things first
render_list.sort_by_key(false);
- _render_render_list(render_list.elements, render_list.element_count, directional_lights.ptr(), directional_lights.size(), p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false, false);
+ _render_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false);
// alpha pass
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- render_list.sort_by_key(true);
- _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, directional_lights.ptr(), directional_lights.size(), p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false, false);
+ render_list.sort_by_depth(true);
+
+ _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
- // #define GLES2_SHADOW_ATLAS_DEBUG_VIEW
+ //#define GLES2_SHADOW_ATLAS_DEBUG_VIEW
#ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
@@ -2114,10 +2562,31 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
storage->_copy_screen();
}
#endif
+
+ //#define GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW
+
+#ifdef GLES2_SHADOW_DIRECTIONAL_DEBUG_VIEW
+ if (true) {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+
+ glViewport(0, 0, storage->frame.current_rt->width / 4, storage->frame.current_rt->height / 4);
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false);
+ storage->shaders.copy.bind();
+
+ storage->_copy_screen();
+ }
+#endif
}
void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
+ state.render_no_shadows = false;
+
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
@@ -2128,13 +2597,13 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
uint32_t y;
uint32_t width;
uint32_t height;
- uint32_t vp_height;
float zfar = 0;
bool flip_facing = false;
int custom_vp_size = 0;
-
GLuint fbo = 0;
+ state.shadow_is_dual_parabolloid = false;
+ state.dual_parbolloid_direction = 0.0;
int current_cubemap = -1;
float bias = 0;
@@ -2213,14 +2682,12 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult;
fbo = directional_shadow.fbo;
- vp_height = directional_shadow.size;
} else {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
fbo = shadow_atlas->fbo;
- vp_height = shadow_atlas->size;
uint32_t key = shadow_atlas->shadow_owners[p_light];
@@ -2263,8 +2730,32 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
zfar = light->param[VS::LIGHT_PARAM_RANGE];
current_cubemap = cubemap_index;
+ } else {
+ //dual parabolloid
+ state.shadow_is_dual_parabolloid = true;
+ light_projection = light_instance->shadow_transform[0].camera;
+ light_transform = light_instance->shadow_transform[0].transform;
+
+ if (light->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
+
+ height /= 2;
+ y += p_pass * height;
+ } else {
+ width /= 2;
+ x += p_pass * width;
+ }
+
+ state.dual_parbolloid_direction = p_pass == 0 ? 1.0 : -1.0;
+ flip_facing = (p_pass == 1);
+ zfar = light->param[VS::LIGHT_PARAM_RANGE];
+ bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS];
+
+ state.dual_parbolloid_zfar = zfar;
+
+ state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, true);
}
- } else {
+
+ } else if (light->type == VS::LIGHT_SPOT) {
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
@@ -2303,11 +2794,16 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
+ if (light->reverse_cull) {
+ flip_facing = !flip_facing;
+ }
+
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true);
- _render_render_list(render_list.elements, render_list.element_count, NULL, 0, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, false, false, true, false);
+ _render_render_list(render_list.elements, render_list.element_count, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, flip_facing, false, true);
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false);
// convert cubemap to dual paraboloid if needed
if (light->type == VS::LIGHT_OMNI && light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && p_pass == 5) {
@@ -2357,6 +2853,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
}
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
+ glColorMask(1, 1, 1, 1);
}
void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
@@ -2364,6 +2861,44 @@ void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
}
bool RasterizerSceneGLES2::free(RID p_rid) {
+
+ if (light_instance_owner.owns(p_rid)) {
+
+ LightInstance *light_instance = light_instance_owner.getptr(p_rid);
+
+ //remove from shadow atlases..
+ for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(E->get());
+ ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
+ uint32_t key = shadow_atlas->shadow_owners[p_rid];
+ uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+ uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
+ shadow_atlas->shadow_owners.erase(p_rid);
+ }
+
+ light_instance_owner.free(p_rid);
+ memdelete(light_instance);
+
+ } else if (shadow_atlas_owner.owns(p_rid)) {
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid);
+ shadow_atlas_set_size(p_rid, 0);
+ shadow_atlas_owner.free(p_rid);
+ memdelete(shadow_atlas);
+ } else if (reflection_probe_instance_owner.owns(p_rid)) {
+
+ ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid);
+
+ reflection_probe_release_atlas_index(p_rid);
+ reflection_probe_instance_owner.free(p_rid);
+ memdelete(reflection_instance);
+
+ } else {
+ return false;
+ }
+
return true;
}
@@ -2376,6 +2911,8 @@ void RasterizerSceneGLES2::initialize() {
render_list.init();
+ render_pass = 1;
+
shadow_atlas_realloc_tolerance_msec = 500;
{
@@ -2393,6 +2930,27 @@ void RasterizerSceneGLES2::initialize() {
}
{
+ default_worldcoord_shader = storage->shader_create();
+ storage->shader_set_code(default_worldcoord_shader, "shader_type spatial; render_mode world_vertex_coords;\n");
+ default_worldcoord_material = storage->material_create();
+ storage->material_set_shader(default_worldcoord_material, default_worldcoord_shader);
+
+ default_worldcoord_shader_twosided = storage->shader_create();
+ default_worldcoord_material_twosided = storage->material_create();
+ storage->shader_set_code(default_worldcoord_shader_twosided, "shader_type spatial; render_mode cull_disabled,world_vertex_coords;\n");
+ storage->material_set_shader(default_worldcoord_material_twosided, default_worldcoord_shader_twosided);
+ }
+
+ {
+ //default material and shader
+
+ default_overdraw_shader = storage->shader_create();
+ storage->shader_set_code(default_overdraw_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
+ default_overdraw_material = storage->material_create();
+ storage->material_set_shader(default_overdraw_material, default_overdraw_shader);
+ }
+
+ {
glGenBuffers(1, &state.sky_verts);
glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, NULL, GL_DYNAMIC_DRAW);
@@ -2462,8 +3020,8 @@ void RasterizerSceneGLES2::initialize() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -2474,9 +3032,12 @@ void RasterizerSceneGLES2::initialize() {
ERR_PRINT("Directional shadow framebuffer status invalid");
}
}
+
+ shadow_filter_mode = SHADOW_FILTER_NEAREST;
}
void RasterizerSceneGLES2::iteration() {
+ shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
}
void RasterizerSceneGLES2::finalize() {
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index 72dbe14387..14b9116952 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -27,6 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#ifndef RASTERIZERSCENEGLES2_H
#define RASTERIZERSCENEGLES2_H
@@ -52,12 +53,39 @@
class RasterizerSceneGLES2 : public RasterizerScene {
public:
+ enum ShadowFilterMode {
+ SHADOW_FILTER_NEAREST,
+ SHADOW_FILTER_PCF5,
+ SHADOW_FILTER_PCF13,
+ };
+
+ enum {
+ INSTANCE_ATTRIB_BASE = 8,
+ INSTANCE_BONE_BASE = 13,
+ };
+
+ ShadowFilterMode shadow_filter_mode;
+
RID default_material;
RID default_material_twosided;
RID default_shader;
RID default_shader_twosided;
+ RID default_worldcoord_material;
+ RID default_worldcoord_material_twosided;
+ RID default_worldcoord_shader;
+ RID default_worldcoord_shader_twosided;
+
+ RID default_overdraw_material;
+ RID default_overdraw_shader;
+
+ uint64_t render_pass;
uint64_t scene_pass;
+ uint32_t current_material_index;
+ uint32_t current_geometry_index;
+ uint32_t current_light_index;
+ uint32_t current_refprobe_index;
+ uint32_t current_shader_index;
RasterizerStorageGLES2 *storage;
struct State {
@@ -171,11 +199,19 @@ public:
bool cull_front;
bool cull_disabled;
bool used_sss;
- bool used_screen_texture;
bool using_contact_shadows;
VS::ViewportDebugDraw debug_draw;
*/
+
+ bool used_screen_texture;
+ bool shadow_is_dual_parabolloid;
+ float dual_parbolloid_direction;
+ float dual_parbolloid_zfar;
+
+ bool render_no_shadows;
+
+ Vector2 screen_pixel_size;
} state;
/* SHADOW ATLAS API */
@@ -259,6 +295,38 @@ public:
/* REFLECTION PROBE INSTANCE */
+ struct ReflectionProbeInstance : public RID_Data {
+
+ RasterizerStorageGLES2::ReflectionProbe *probe_ptr;
+ RID probe;
+ RID self;
+ RID atlas;
+
+ int reflection_atlas_index;
+
+ int render_step;
+ int reflection_index;
+
+ GLuint fbo[6];
+ GLuint cubemap;
+ GLuint depth;
+
+ GLuint fbo_blur;
+
+ int current_resolution;
+ mutable bool dirty;
+
+ uint64_t last_pass;
+ uint32_t index;
+
+ Transform transform;
+ };
+
+ mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
+
+ ReflectionProbeInstance **reflection_probe_instances;
+ int reflection_probe_count;
+
virtual RID reflection_probe_instance_create(RID p_probe);
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
virtual void reflection_probe_release_atlas_index(RID p_instance);
@@ -372,6 +440,10 @@ public:
virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
virtual void light_instance_mark_visible(RID p_light_instance);
+ LightInstance **render_light_instances;
+ int render_directional_lights;
+ int render_light_instance_count;
+
/* REFLECTION INSTANCE */
virtual RID gi_probe_instance_create();
@@ -381,40 +453,19 @@ public:
/* RENDER LIST */
+ enum LightMode {
+ LIGHTMODE_NORMAL,
+ LIGHTMODE_UNSHADED,
+ LIGHTMODE_LIGHTMAP,
+ LIGHTMODE_LIGHTMAP_CAPTURE,
+ };
+
struct RenderList {
+
enum {
- DEFAULT_MAX_ELEMENTS = 65536,
- SORT_FLAG_SKELETON = 1,
- SORT_FLAG_INSTANCING = 2,
- MAX_DIRECTIONAL_LIGHTS = 16,
- MAX_LIGHTS = 4096,
- MAX_REFLECTIONS = 1024,
-
- SORT_KEY_PRIORITY_SHIFT = 56,
- SORT_KEY_PRIORITY_MASK = 0xFF,
- //depth layer for opaque (56-52)
- SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT = 52,
- SORT_KEY_OPAQUE_DEPTH_LAYER_MASK = 0xF,
-//64 bits unsupported in MSVC
-#define SORT_KEY_UNSHADED_FLAG (uint64_t(1) << 49)
-#define SORT_KEY_NO_DIRECTIONAL_FLAG (uint64_t(1) << 48)
-#define SORT_KEY_LIGHTMAP_CAPTURE_FLAG (uint64_t(1) << 47)
-#define SORT_KEY_LIGHTMAP_FLAG (uint64_t(1) << 46)
-#define SORT_KEY_GI_PROBES_FLAG (uint64_t(1) << 45)
-#define SORT_KEY_VERTEX_LIT_FLAG (uint64_t(1) << 44)
- SORT_KEY_SHADING_SHIFT = 44,
- SORT_KEY_SHADING_MASK = 63,
- //44-28 material index
- SORT_KEY_MATERIAL_INDEX_SHIFT = 28,
- //28-8 geometry index
- SORT_KEY_GEOMETRY_INDEX_SHIFT = 8,
- //bits 5-7 geometry type
- SORT_KEY_GEOMETRY_TYPE_SHIFT = 5,
- //bits 0-5 for flags
- SORT_KEY_OPAQUE_PRE_PASS = 8,
- SORT_KEY_CULL_DISABLED_FLAG = 4,
- SORT_KEY_SKELETON_FLAG = 2,
- SORT_KEY_MIRROR_FLAG = 1
+ MAX_LIGHTS = 255,
+ MAX_REFLECTION_PROBES = 255,
+ DEFAULT_MAX_ELEMENTS = 65536
};
int max_elements;
@@ -426,7 +477,38 @@ public:
RasterizerStorageGLES2::Material *material;
RasterizerStorageGLES2::GeometryOwner *owner;
- uint64_t sort_key;
+ bool use_accum; //is this an add pass for multipass
+ bool *use_accum_ptr;
+
+ union {
+ //TODO: should be endian swapped on big endian
+ struct {
+ int32_t depth_layer : 16;
+ int32_t priority : 16;
+ };
+
+ uint32_t depth_key;
+ };
+
+ union {
+ struct {
+ //from least significant to most significant in sort, TODO: should be endian swapped on big endian
+
+ uint64_t geometry_index : 14;
+ uint64_t instancing : 1;
+ uint64_t skeleton : 1;
+ uint64_t shader_index : 10;
+ uint64_t material_index : 10;
+ uint64_t light_index : 8;
+ uint64_t light_type2 : 1; // if 1==0 : nolight/directional, else omni/spot
+ uint64_t refprobe_1_index : 8;
+ uint64_t refprobe_0_index : 8;
+ uint64_t light_type1 : 1; //no light, directional is 0, omni spot is 1
+ uint64_t light_mode : 2; // LightMode enum
+ };
+
+ uint64_t sort_key;
+ };
};
Element *base_elements;
@@ -444,7 +526,11 @@ public:
struct SortByKey {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->sort_key < B->sort_key;
+ if (A->depth_key == B->depth_key) {
+ return A->sort_key < B->sort_key;
+ } else {
+ return A->depth_key < B->depth_key;
+ }
}
};
@@ -475,29 +561,6 @@ public:
}
}
- struct SortByReverseDepthAndPriority {
-
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- uint32_t layer_A = uint32_t(A->sort_key >> SORT_KEY_PRIORITY_SHIFT);
- uint32_t layer_B = uint32_t(B->sort_key >> SORT_KEY_PRIORITY_SHIFT);
- if (layer_A == layer_B) {
- return A->instance->depth > B->instance->depth;
- } else {
- return layer_A < layer_B;
- }
- }
- };
-
- void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
-
- SortArray<Element *, SortByReverseDepthAndPriority> sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
- }
-
// element adding and stuff
_FORCE_INLINE_ Element *add_element() {
@@ -548,7 +611,6 @@ public:
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
void _render_render_list(RenderList::Element **p_elements, int p_element_count,
- const RID *p_directional_lights, int p_directional_light_count,
const Transform &p_view_transform,
const CameraMatrix &p_projection,
RID p_shadow_atlas,
@@ -558,14 +620,16 @@ public:
float p_shadow_normal_bias,
bool p_reverse_cull,
bool p_alpha_pass,
- bool p_shadow,
- bool p_directional_add);
+ bool p_shadow);
void _draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy);
- void _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, bool p_alpha_pass, Size2i p_skeleton_tex_size = Size2i(0, 0));
- void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton);
- void _render_geometry(RenderList::Element *p_element);
+ _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, bool p_alpha_pass, Size2i p_skeleton_tex_size = Size2i(0, 0));
+ _FORCE_INLINE_ void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton);
+ _FORCE_INLINE_ void _setup_light_type(LightInstance *p_light, ShadowAtlas *shadow_atlas);
+ _FORCE_INLINE_ void _setup_light(LightInstance *p_light, ShadowAtlas *shadow_atlas, const Transform &p_view_transform);
+ _FORCE_INLINE_ void _setup_refprobes(ReflectionProbeInstance *p_refprobe1, ReflectionProbeInstance *p_refprobe2, const Transform &p_view_transform, Environment *p_env);
+ _FORCE_INLINE_ void _render_geometry(RenderList::Element *p_element);
virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 3cee42983d..6314a69a90 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -27,14 +27,13 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#include "rasterizer_storage_gles2.h"
-#include "project_settings.h"
+#include "core/math/transform.h"
+#include "core/project_settings.h"
#include "rasterizer_canvas_gles2.h"
#include "rasterizer_scene_gles2.h"
-
-#include "math/transform.h"
-
#include "servers/visual/shader_language.h"
GLuint RasterizerStorageGLES2::system_fbo = 0;
@@ -53,6 +52,10 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define _GL_HALF_FLOAT_OES 0x8D61
#endif
+#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+
+#define _DEPTH_COMPONENT24_OES 0x81A6
+
void RasterizerStorageGLES2::bind_quad_array() const {
glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
@@ -355,7 +358,6 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
GLenum type;
bool compressed = false;
- bool srgb = false;
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video
@@ -496,22 +498,6 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
-//set swizle for older format compatibility
-#ifdef GLES_OVER_GL
- switch (texture->format) {
-
- case Image::FORMAT_L8: {
-
- } break;
- case Image::FORMAT_LA8: {
-
- } break;
- default: {
-
- } break;
- }
-#endif
-
int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1;
int w = img->get_width();
@@ -591,7 +577,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
PoolVector<uint8_t> data;
- int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0);
+ int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
PoolVector<uint8_t>::Write wb = data.write();
@@ -627,8 +613,8 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
return Ref<Image>(img);
#else
- ERR_EXPLAIN("Sorry, It's not posible to obtain images back in OpenGL ES");
- return Ref<Image>();
+ ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES");
+ ERR_FAIL_V(Ref<Image>());
#endif
}
@@ -964,6 +950,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
float roughness = mm_level ? lod / (float)(mipmaps - 1) : 1;
+ roughness = MIN(1.0, roughness); //keep max at 1
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -1309,8 +1296,13 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
pi.hint_string = "CubeMap";
} break;
- default: {
-
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER3D:
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D: {
+ // Not implemented in GLES2
} break;
}
@@ -1420,6 +1412,19 @@ Variant RasterizerStorageGLES2::material_get_param(RID p_material, const StringN
return material->params[p_param];
}
+ return material_get_param_default(p_material, p_param);
+}
+
+Variant RasterizerStorageGLES2::material_get_param_default(RID p_material, const StringName &p_param) const {
+ const Material *material = material_owner.get(p_material);
+ ERR_FAIL_COND_V(!material, Variant());
+
+ if (material->shader) {
+ if (material->shader->uniforms.has(p_param)) {
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type);
+ }
+ }
return Variant();
}
@@ -1552,7 +1557,7 @@ void RasterizerStorageGLES2::_update_material(Material *p_material) {
}
}
- // uniforms and other thigns will be set in the use_material method in ShaderGLES2
+ // uniforms and other things will be set in the use_material method in ShaderGLES2
if (p_material->shader && p_material->shader->texture_count > 0) {
@@ -2622,10 +2627,10 @@ void RasterizerStorageGLES2::update_dirty_multimeshes() {
if (multimesh->mesh.is_valid()) {
mesh_aabb = mesh_get_aabb(multimesh->mesh, RID());
- } else {
- mesh_aabb.size += Vector3(0.001, 0.001, 0.001);
}
+ mesh_aabb.size += Vector3(0.001, 0.001, 0.001); //in case mesh is empty in one of the sides
+
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
int count = multimesh->data.size();
float *data = multimesh->data.ptrw();
@@ -3097,6 +3102,7 @@ void RasterizerStorageGLES2::light_set_param(RID p_light, VS::LightParam p_param
light->version++;
light->instance_change_notify();
} break;
+ default: {}
}
light->param[p_param] = p_value;
@@ -3288,69 +3294,194 @@ AABB RasterizerStorageGLES2::light_get_aabb(RID p_light) const {
/* PROBE API */
RID RasterizerStorageGLES2::reflection_probe_create() {
- return RID();
+
+ ReflectionProbe *reflection_probe = memnew(ReflectionProbe);
+
+ reflection_probe->intensity = 1.0;
+ reflection_probe->interior_ambient = Color();
+ reflection_probe->interior_ambient_energy = 1.0;
+ reflection_probe->max_distance = 0;
+ reflection_probe->extents = Vector3(1, 1, 1);
+ reflection_probe->origin_offset = Vector3(0, 0, 0);
+ reflection_probe->interior = false;
+ reflection_probe->box_projection = false;
+ reflection_probe->enable_shadows = false;
+ reflection_probe->cull_mask = (1 << 20) - 1;
+ reflection_probe->update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE;
+ reflection_probe->resolution = 128;
+
+ return reflection_probe_owner.make_rid(reflection_probe);
}
void RasterizerStorageGLES2::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->update_mode = p_mode;
+ reflection_probe->instance_change_notify();
}
void RasterizerStorageGLES2::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->intensity = p_intensity;
}
void RasterizerStorageGLES2::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior_ambient = p_ambient;
}
void RasterizerStorageGLES2::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior_ambient_energy = p_energy;
}
void RasterizerStorageGLES2::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior_ambient_probe_contrib = p_contrib;
}
void RasterizerStorageGLES2::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
-}
-void RasterizerStorageGLES2::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->max_distance = p_distance;
+ reflection_probe->instance_change_notify();
}
+void RasterizerStorageGLES2::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+ reflection_probe->extents = p_extents;
+ reflection_probe->instance_change_notify();
+}
void RasterizerStorageGLES2::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->origin_offset = p_offset;
+ reflection_probe->instance_change_notify();
}
void RasterizerStorageGLES2::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
-}
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior = p_enable;
+}
void RasterizerStorageGLES2::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->box_projection = p_enable;
}
void RasterizerStorageGLES2::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
-}
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->enable_shadows = p_enable;
+ reflection_probe->instance_change_notify();
+}
void RasterizerStorageGLES2::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->cull_mask = p_layers;
+ reflection_probe->instance_change_notify();
+}
+
+void RasterizerStorageGLES2::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->resolution = p_resolution;
}
AABB RasterizerStorageGLES2::reflection_probe_get_aabb(RID p_probe) const {
- return AABB();
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, AABB());
+
+ AABB aabb;
+ aabb.position = -reflection_probe->extents;
+ aabb.size = reflection_probe->extents * 2.0;
+
+ return aabb;
}
VS::ReflectionProbeUpdateMode RasterizerStorageGLES2::reflection_probe_get_update_mode(RID p_probe) const {
- return VS::REFLECTION_PROBE_UPDATE_ALWAYS;
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS);
+
+ return reflection_probe->update_mode;
}
uint32_t RasterizerStorageGLES2::reflection_probe_get_cull_mask(RID p_probe) const {
- return 0;
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->cull_mask;
}
Vector3 RasterizerStorageGLES2::reflection_probe_get_extents(RID p_probe) const {
- return Vector3();
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->extents;
}
Vector3 RasterizerStorageGLES2::reflection_probe_get_origin_offset(RID p_probe) const {
- return Vector3();
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->origin_offset;
}
bool RasterizerStorageGLES2::reflection_probe_renders_shadows(RID p_probe) const {
- return false;
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->enable_shadows;
}
float RasterizerStorageGLES2::reflection_probe_get_origin_max_distance(RID p_probe) const {
- return 0;
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->max_distance;
+}
+
+int RasterizerStorageGLES2::reflection_probe_get_resolution(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->resolution;
}
RID RasterizerStorageGLES2::gi_probe_create() {
@@ -3451,46 +3582,100 @@ void RasterizerStorageGLES2::gi_probe_dynamic_data_update(RID p_gi_probe_data, i
///////
RID RasterizerStorageGLES2::lightmap_capture_create() {
- return RID();
+
+ LightmapCapture *capture = memnew(LightmapCapture);
+ return lightmap_capture_data_owner.make_rid(capture);
}
void RasterizerStorageGLES2::lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {
-}
-AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const {
- return AABB();
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+ capture->bounds = p_bounds;
+ capture->instance_change_notify();
}
+AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const {
-void RasterizerStorageGLES2::lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) {
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, AABB());
+ return capture->bounds;
}
+void RasterizerStorageGLES2::lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) {
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+
+ ERR_FAIL_COND(p_octree.size() == 0 || (p_octree.size() % sizeof(LightmapCaptureOctree)) != 0);
+
+ capture->octree.resize(p_octree.size() / sizeof(LightmapCaptureOctree));
+ if (p_octree.size()) {
+ PoolVector<LightmapCaptureOctree>::Write w = capture->octree.write();
+ PoolVector<uint8_t>::Read r = p_octree.read();
+ copymem(w.ptr(), r.ptr(), p_octree.size());
+ }
+ capture->instance_change_notify();
+}
PoolVector<uint8_t> RasterizerStorageGLES2::lightmap_capture_get_octree(RID p_capture) const {
- return PoolVector<uint8_t>();
+
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, PoolVector<uint8_t>());
+
+ if (capture->octree.size() == 0)
+ return PoolVector<uint8_t>();
+
+ PoolVector<uint8_t> ret;
+ ret.resize(capture->octree.size() * sizeof(LightmapCaptureOctree));
+ {
+ PoolVector<LightmapCaptureOctree>::Read r = capture->octree.read();
+ PoolVector<uint8_t>::Write w = ret.write();
+ copymem(w.ptr(), r.ptr(), ret.size());
+ }
+
+ return ret;
}
void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+ capture->cell_xform = p_xform;
}
Transform RasterizerStorageGLES2::lightmap_capture_get_octree_cell_transform(RID p_capture) const {
- return Transform();
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, Transform());
+ return capture->cell_xform;
}
void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+ capture->cell_subdiv = p_subdiv;
}
int RasterizerStorageGLES2::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const {
- return 0;
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, 0);
+ return capture->cell_subdiv;
}
void RasterizerStorageGLES2::lightmap_capture_set_energy(RID p_capture, float p_energy) {
+
+ LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND(!capture);
+ capture->energy = p_energy;
}
float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const {
- return 0.0;
+
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, 0);
+ return capture->energy;
}
const PoolVector<RasterizerStorage::LightmapCaptureOctree> *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const {
- return NULL;
+ const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
+ ERR_FAIL_COND_V(!capture, NULL);
+ return &capture->octree;
}
///////
@@ -3582,15 +3767,115 @@ void RasterizerStorageGLES2::update_particles() {
////////
void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
+
+ Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+
+ skeleton->instances.insert(p_instance);
}
void RasterizerStorageGLES2::instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
+
+ Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+
+ skeleton->instances.erase(p_instance);
}
void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
+
+ Instantiable *inst = NULL;
+ switch (p_instance->base_type) {
+ case VS::INSTANCE_MESH: {
+ inst = mesh_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ case VS::INSTANCE_MULTIMESH: {
+ inst = multimesh_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ case VS::INSTANCE_IMMEDIATE: {
+ inst = immediate_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ /*case VS::INSTANCE_PARTICLES: {
+ inst = particles_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;*/
+ case VS::INSTANCE_REFLECTION_PROBE: {
+ inst = reflection_probe_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ case VS::INSTANCE_LIGHT: {
+ inst = light_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ /*case VS::INSTANCE_GI_PROBE: {
+ inst = gi_probe_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;*/
+ case VS::INSTANCE_LIGHTMAP_CAPTURE: {
+ inst = lightmap_capture_data_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ default: {
+ if (!inst) {
+ ERR_FAIL();
+ }
+ }
+ }
+
+ inst->instance_list.add(&p_instance->dependency_item);
}
void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
+
+ Instantiable *inst = NULL;
+
+ switch (p_instance->base_type) {
+ case VS::INSTANCE_MESH: {
+ inst = mesh_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ case VS::INSTANCE_MULTIMESH: {
+ inst = multimesh_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ case VS::INSTANCE_IMMEDIATE: {
+ inst = immediate_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ /*case VS::INSTANCE_PARTICLES: {
+ inst = particles_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;*/
+ case VS::INSTANCE_REFLECTION_PROBE: {
+ inst = reflection_probe_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ case VS::INSTANCE_LIGHT: {
+ inst = light_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ /*case VS::INSTANCE_GI_PROBE: {
+ inst = gi_probe_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break; */
+ case VS::INSTANCE_LIGHTMAP_CAPTURE: {
+ inst = lightmap_capture_data_owner.getornull(p_base);
+ ERR_FAIL_COND(!inst);
+ } break;
+ default: {
+
+ if (!inst) {
+ ERR_FAIL();
+ }
+ }
+ }
+
+ ERR_FAIL_COND(!inst);
+
+ inst->instance_list.remove(&p_instance->dependency_item);
}
/* RENDER TARGET */
@@ -3632,7 +3917,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, rt->width, rt->height);
+ glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -3848,6 +4133,10 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
return VS::INSTANCE_MULTIMESH;
} else if (immediate_owner.owns(p_rid)) {
return VS::INSTANCE_IMMEDIATE;
+ } else if (reflection_probe_owner.owns(p_rid)) {
+ return VS::INSTANCE_REFLECTION_PROBE;
+ } else if (lightmap_capture_data_owner.owns(p_rid)) {
+ return VS::INSTANCE_LIGHTMAP_CAPTURE;
} else {
return VS::INSTANCE_NONE;
}
@@ -4025,6 +4314,25 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
memdelete(light);
return true;
+ } else if (reflection_probe_owner.owns(p_rid)) {
+
+ // delete the texture
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get(p_rid);
+ reflection_probe->instance_remove_deps();
+
+ reflection_probe_owner.free(p_rid);
+ memdelete(reflection_probe);
+
+ return true;
+ } else if (lightmap_capture_data_owner.owns(p_rid)) {
+
+ // delete the texture
+ LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid);
+ lightmap_capture->instance_remove_deps();
+
+ lightmap_capture_data_owner.free(p_rid);
+ memdelete(lightmap_capture);
+ return true;
} else {
return false;
}
@@ -4076,15 +4384,15 @@ void RasterizerStorageGLES2::initialize() {
}
config.shrink_textures_x2 = false;
- config.float_texture_supported = config.extensions.find("GL_ARB_texture_float") != NULL || config.extensions.find("GL_OES_texture_float") != NULL;
- config.s3tc_supported = config.extensions.find("GL_EXT_texture_compression_s3tc") != NULL;
- config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") != NULL;
+
+ config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
+ config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc");
+ config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
frame.count = 0;
frame.delta = 0;
frame.current_rt = NULL;
frame.clear_request = false;
- // config.keep_original_textures = false;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
@@ -4187,13 +4495,13 @@ void RasterizerStorageGLES2::initialize() {
// radical inverse vdc cache texture
// used for cubemap filtering
- if (config.float_texture_supported) {
+ if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere
glGenTextures(1, &resources.radical_inverse_vdc_cache_tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex);
- float radical_inverse[512];
+ uint8_t radical_inverse[512];
for (uint32_t i = 0; i < 512; i++) {
uint32_t bits = i;
@@ -4205,14 +4513,23 @@ void RasterizerStorageGLES2::initialize() {
bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8);
float value = float(bits) * 2.3283064365386963e-10;
-
- radical_inverse[i] = value;
+ radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255));
}
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_FLOAT, radical_inverse);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, radical_inverse);
glBindTexture(GL_TEXTURE_2D, 0);
}
+
+#ifdef GLES_OVER_GL
+ //this needs to be enabled manually in OpenGL 2.1
+
+ glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS);
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+
+ config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
}
void RasterizerStorageGLES2::finalize() {
@@ -4227,6 +4544,7 @@ void RasterizerStorageGLES2::update_dirty_resources() {
update_dirty_shaders();
update_dirty_materials();
update_dirty_skeletons();
+ update_dirty_multimeshes();
}
RasterizerStorageGLES2::RasterizerStorageGLES2() {
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 88783d7160..b42e2dfb1f 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -27,11 +27,12 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#ifndef RASTERIZERSTORAGEGLES2_H
#define RASTERIZERSTORAGEGLES2_H
-#include "dvector.h"
-#include "self_list.h"
+#include "core/dvector.h"
+#include "core/self_list.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/shader_language.h"
#include "shader_compiler_gles2.h"
@@ -156,7 +157,7 @@ public:
//////////////////////////////////DATA///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
- struct Instanciable : public RID_Data {
+ struct Instantiable : public RID_Data {
SelfList<RasterizerScene::InstanceBase>::List instance_list;
_FORCE_INLINE_ void instance_change_notify() {
@@ -186,15 +187,15 @@ public:
}
}
- Instanciable() {}
+ Instantiable() {}
- virtual ~Instanciable() {}
+ virtual ~Instantiable() {}
};
- struct GeometryOwner : public Instanciable {
+ struct GeometryOwner : public Instantiable {
};
- struct Geometry : public Instanciable {
+ struct Geometry : public Instantiable {
enum Type {
GEOMETRY_INVALID,
@@ -405,6 +406,9 @@ public:
String path;
+ uint32_t index;
+ uint64_t last_pass;
+
struct CanvasItem {
enum BlendMode {
@@ -490,6 +494,7 @@ public:
valid = false;
custom_code_id = 0;
version = 1;
+ last_pass = 0;
}
};
@@ -562,6 +567,7 @@ public:
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
virtual Variant material_get_param(RID p_material, const StringName &p_param) const;
+ virtual Variant material_get_param_default(RID p_material, const StringName &p_param) const;
virtual void material_set_line_width(RID p_material, float p_width);
virtual void material_set_next_pass(RID p_material, RID p_next_material);
@@ -887,7 +893,7 @@ public:
/* Light API */
- struct Light : Instanciable {
+ struct Light : Instantiable {
VS::LightType type;
float param[VS::LIGHT_PARAM_MAX];
@@ -949,6 +955,26 @@ public:
virtual uint64_t light_get_version(RID p_light) const;
/* PROBE API */
+
+ struct ReflectionProbe : Instantiable {
+
+ VS::ReflectionProbeUpdateMode update_mode;
+ float intensity;
+ Color interior_ambient;
+ float interior_ambient_energy;
+ float interior_ambient_probe_contrib;
+ float max_distance;
+ Vector3 extents;
+ Vector3 origin_offset;
+ bool interior;
+ bool box_projection;
+ bool enable_shadows;
+ uint32_t cull_mask;
+ int resolution;
+ };
+
+ mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
+
virtual RID reflection_probe_create();
virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode);
@@ -963,11 +989,14 @@ public:
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution);
virtual AABB reflection_probe_get_aabb(RID p_probe) const;
virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
+ virtual int reflection_probe_get_resolution(RID p_probe) const;
+
virtual Vector3 reflection_probe_get_extents(RID p_probe) const;
virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const;
@@ -1017,6 +1046,21 @@ public:
/* LIGHTMAP */
+ struct LightmapCapture : public Instantiable {
+
+ PoolVector<LightmapCaptureOctree> octree;
+ AABB bounds;
+ Transform cell_xform;
+ int cell_subdiv;
+ float energy;
+ LightmapCapture() {
+ energy = 1.0;
+ cell_subdiv = 1;
+ }
+ };
+
+ mutable RID_Owner<LightmapCapture> lightmap_capture_data_owner;
+
virtual RID lightmap_capture_create();
virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds);
virtual AABB lightmap_capture_get_bounds(RID p_capture) const;
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 1c87b3ffb5..082c520480 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -27,11 +27,13 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#include "shader_compiler_gles2.h"
-#include "os/os.h"
-#include "string_buffer.h"
-#include "string_builder.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
+#include "core/string_buffer.h"
+#include "core/string_builder.h"
#define SL ShaderLanguage
@@ -641,11 +643,11 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
case SL::OP_MOD: {
- code += "mod(";
+ code += "mod(float(";
code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- code += ", ";
+ code += "), float(";
code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- code += ")";
+ code += "))";
} break;
default: {
@@ -829,6 +831,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
// gl_InstanceID is not available in OpenGL ES 2.0
actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0";
+ actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
//builtins
@@ -899,16 +902,30 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
- actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
+ bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley");
+
+ if (!force_lambert) {
+ actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
+ }
+
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
- actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
+ bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
+
+ if (!force_blinn) {
+ actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
+ } else {
+ actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n";
+ }
+
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
/* PARTICLES SHADER */
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 804ead2172..5e9e295204 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -27,16 +27,16 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#ifndef SHADERCOMPILERGLES2_H
#define SHADERCOMPILERGLES2_H
-#include "pair.h"
+#include "core/pair.h"
+#include "core/string_builder.h"
#include "servers/visual/shader_language.h"
#include "servers/visual/shader_types.h"
#include "servers/visual_server.h"
-#include "string_builder.h"
-
class ShaderCompilerGLES2 {
public:
struct IdentifierActions {
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index 3b2a29d3ee..628a57c06d 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -27,12 +27,12 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "shader_gles2.h"
-#include "memory.h"
-#include "print_string.h"
-#include "string_builder.h"
+#include "shader_gles2.h"
+#include "core/os/memory.h"
+#include "core/print_string.h"
+#include "core/string_builder.h"
#include "rasterizer_gles2.h"
#include "rasterizer_storage_gles2.h"
@@ -57,7 +57,7 @@
ShaderGLES2 *ShaderGLES2::active = NULL;
-// #define DEBUG_SHADER
+//#define DEBUG_SHADER
#ifdef DEBUG_SHADER
@@ -132,6 +132,11 @@ bool ShaderGLES2::bind() {
ERR_FAIL_COND_V(!version, false);
+ if (!version->ok) { //broken, unable to bind (do not throw error, you saw it before already when it failed compilation).
+ glUseProgram(0);
+ return false;
+ }
+
glUseProgram(version->id);
// find out uniform names and locations
@@ -171,72 +176,24 @@ void ShaderGLES2::unbind() {
active = NULL;
}
-static String _fix_error_code_line(const String &p_error, int p_code_start, int p_offset) {
-
- int last_find_pos = -1;
- // NVIDIA
- String error = p_error;
- while ((last_find_pos = p_error.find("(", last_find_pos + 1)) != -1) {
-
- int end_pos = last_find_pos + 1;
-
- while (true) {
+static void _display_error_with_code(const String &p_error, const Vector<const char *> &p_code) {
- if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') {
-
- end_pos++;
- continue;
- } else if (p_error[end_pos] == ')') {
- break;
- } else {
-
- end_pos = -1;
- break;
- }
- }
-
- if (end_pos == -1)
- continue;
+ int line = 1;
+ String total_code;
- String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1);
- String begin = error.substr(0, last_find_pos + 1);
- String end = error.substr(end_pos, error.length());
- int num = numstr.to_int() + p_code_start - p_offset;
- error = begin + itos(num) + end;
+ for (int i = 0; i < p_code.size(); i++) {
+ total_code += String(p_code[i]);
}
- // ATI
- last_find_pos = -1;
- while ((last_find_pos = p_error.find("ERROR: ", last_find_pos + 1)) != -1) {
+ Vector<String> lines = String(total_code).split("\n");
- last_find_pos += 6;
- int end_pos = last_find_pos + 1;
+ for (int j = 0; j < lines.size(); j++) {
- while (true) {
-
- if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') {
-
- end_pos++;
- continue;
- } else if (p_error[end_pos] == ':') {
- break;
- } else {
-
- end_pos = -1;
- break;
- }
- }
- continue;
- if (end_pos == -1)
- continue;
-
- String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1);
- String begin = error.substr(0, last_find_pos + 1);
- String end = error.substr(end_pos, error.length());
- int num = numstr.to_int() + p_code_start - p_offset;
- error = begin + itos(num) + end;
+ print_line(itos(line) + ": " + lines[j]);
+ line++;
}
- return error;
+
+ ERR_PRINTS(p_error);
}
ShaderGLES2::Version *ShaderGLES2::get_current_version() {
@@ -293,7 +250,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
}
}
- // keep them around during the functino
+ // keep them around during the function
CharString code_string;
CharString code_string2;
CharString code_globals;
@@ -316,7 +273,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
if (cc) {
for (int i = 0; i < cc->custom_defines.size(); i++) {
strings.push_back(cc->custom_defines.write[i]);
- DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i]));
+ DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i].get_data()));
}
}
@@ -375,9 +332,8 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
String err_string = get_shader_name() + ": Vertex shader compilation failed:\n";
err_string += ilogmem;
- err_string = _fix_error_code_line(err_string, vertex_code_start, define_line_ofs);
- ERR_PRINTS(err_string);
+ _display_error_with_code(err_string, strings);
Memory::free_static(ilogmem);
glDeleteShader(v.vert_id);
@@ -451,9 +407,8 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
String err_string = get_shader_name() + ": Fragment shader compilation failed:\n";
err_string += ilogmem;
- err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs);
- ERR_PRINTS(err_string);
+ _display_error_with_code(err_string, strings);
Memory::free_static(ilogmem);
glDeleteShader(v.frag_id);
@@ -503,9 +458,8 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
String err_string = get_shader_name() + ": Program linking failed:\n";
err_string += ilogmem;
- err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs);
- ERR_PRINTS(err_string);
+ _display_error_with_code(err_string, strings);
Memory::free_static(ilogmem);
glDeleteShader(v.frag_id);
@@ -736,11 +690,6 @@ void ShaderGLES2::use_material(void *p_material) {
Version *v = version_map.getptr(conditional_version);
- CustomCode *cc = NULL;
- if (v) {
- cc = custom_code_map.getptr(v->code_version);
- }
-
// bind uniforms
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) {
@@ -1028,7 +977,7 @@ void ShaderGLES2::use_material(void *p_material) {
value.second.resize(default_arg_size);
- for (int i = 0; i < default_arg_size; i++) {
+ for (size_t i = 0; i < default_arg_size; i++) {
if (is_float) {
value.second.write[i].real = 0.0;
} else {
@@ -1038,8 +987,6 @@ void ShaderGLES2::use_material(void *p_material) {
}
}
- // GLint location = get_uniform_location(E->key());
-
GLint location;
if (v->custom_uniform_locations.has(E->key())) {
location = v->custom_uniform_locations[E->key()];
@@ -1059,8 +1006,6 @@ void ShaderGLES2::use_material(void *p_material) {
int tc = material->textures.size();
Pair<StringName, RID> *textures = material->textures.ptrw();
- ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = material->shader->texture_hints.ptrw();
-
for (int i = 0; i < tc; i++) {
Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value;
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index cb515c199c..9160a7c265 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -27,11 +27,11 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+
#ifndef SHADER_GLES2_H
#define SHADER_GLES2_H
-#include <stdio.h>
-
+// This must come first to avoid windows.h mess
#include "platform_config.h"
#ifndef GLES2_INCLUDE_H
#include <GLES2/gl2.h>
@@ -39,14 +39,15 @@
#include GLES2_INCLUDE_H
#endif
-#include "camera_matrix.h"
-#include "hash_map.h"
-#include "map.h"
-#include "variant.h"
-
+#include "core/hash_map.h"
+#include "core/map.h"
+#include "core/math/camera_matrix.h"
#include "core/pair.h"
+#include "core/variant.h"
#include "servers/visual/shader_language.h"
+#include <stdio.h>
+
class RasterizerStorageGLES2;
class ShaderGLES2 {
@@ -334,6 +335,19 @@ public:
case ShaderLanguage::TYPE_SAMPLERCUBE: {
} break;
+
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER3D:
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D: {
+ // Not implemented in GLES2
+ } break;
+
+ case ShaderLanguage::TYPE_VOID: {
+ // Nothing to do?
+ } break;
}
}
@@ -467,7 +481,8 @@ public:
// like forward declared nested classes.
void use_material(void *p_material);
- uint32_t get_version() const { return new_conditional_version.version; }
+ _FORCE_INLINE_ uint32_t get_version() const { return new_conditional_version.version; }
+ _FORCE_INLINE_ bool is_version_valid() const { return version && version->ok; }
void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) {
diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl
index 2a1ad8d8f2..b1553c7cd5 100644
--- a/drivers/gles2/shaders/cubemap_filter.glsl
+++ b/drivers/gles2/shaders/cubemap_filter.glsl
@@ -167,18 +167,21 @@ void main() {
vec3 H = ImportanceSampleGGX(xi, roughness, N);
vec3 V = N;
- vec3 L = normalize(2.0 * dot(V, H) * H - V);
+ vec3 L = (2.0 * dot(V, H) * H - V);
float NdotL = clamp(dot(N, L), 0.0, 1.0);
if (NdotL > 0.0) {
#ifdef USE_SOURCE_PANORAMA
- sum.rgb += texturePanorama(source_panorama, L).rgb * NdotL;
+ vec3 val = texturePanorama(source_panorama, L).rgb;
#else
- L.y = -L.y;
- sum.rgb += textureCubeLod(source_cube, L, 0.0).rgb * NdotL;
+ vec3 val = textureCubeLod(source_cube, L, 0.0).rgb;
#endif
+ //mix using Linear, to approximate high end back-end
+ val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045))));
+
+ sum.rgb += val * NdotL;
sum.a += NdotL;
}
@@ -186,5 +189,8 @@ void main() {
sum /= sum.a;
+ vec3 a = vec3(0.055);
+ sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308))));
+
gl_FragColor = vec4(sum.rgb, 1.0);
}
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 906c089170..958de94485 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -5,12 +5,17 @@
#define mediump
#define highp
#else
-precision mediump float;
-precision mediump int;
+precision highp float;
+precision highp int;
#endif
#include "stdlib.glsl"
+#define SHADER_IS_SRGB true
+
+#define M_PI 3.14159265359
+
+
//
// attributes
//
@@ -23,15 +28,15 @@ attribute vec3 normal_attrib; // attrib:1
attribute vec4 tangent_attrib; // attrib:2
#endif
-#ifdef ENABLE_COLOR_INTERP
+#if defined(ENABLE_COLOR_INTERP)
attribute vec4 color_attrib; // attrib:3
#endif
-#ifdef ENABLE_UV_INTERP
+#if defined(ENABLE_UV_INTERP)
attribute vec2 uv_attrib; // attrib:4
#endif
-#ifdef ENABLE_UV2_INTERP
+#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
attribute vec2 uv2_attrib; // attrib:5
#endif
@@ -39,9 +44,9 @@ attribute vec2 uv2_attrib; // attrib:5
#ifdef USE_SKELETON_SOFTWARE
-attribute highp vec4 bone_transform_row_0; // attrib:9
-attribute highp vec4 bone_transform_row_1; // attrib:10
-attribute highp vec4 bone_transform_row_2; // attrib:11
+attribute highp vec4 bone_transform_row_0; // attrib:13
+attribute highp vec4 bone_transform_row_1; // attrib:14
+attribute highp vec4 bone_transform_row_2; // attrib:15
#else
@@ -57,12 +62,12 @@ uniform ivec2 skeleton_texture_size;
#ifdef USE_INSTANCING
-attribute highp vec4 instance_xform_row_0; // attrib:12
-attribute highp vec4 instance_xform_row_1; // attrib:13
-attribute highp vec4 instance_xform_row_2; // attrib:14
+attribute highp vec4 instance_xform_row_0; // attrib:8
+attribute highp vec4 instance_xform_row_1; // attrib:9
+attribute highp vec4 instance_xform_row_2; // attrib:10
-attribute highp vec4 instance_color; // attrib:15
-attribute highp vec4 instance_custom_data; // attrib:8
+attribute highp vec4 instance_color; // attrib:11
+attribute highp vec4 instance_custom_data; // attrib:12
#endif
@@ -98,15 +103,15 @@ varying vec3 tangent_interp;
varying vec3 binormal_interp;
#endif
-#ifdef ENABLE_COLOR_INTERP
+#if defined(ENABLE_COLOR_INTERP)
varying vec4 color_interp;
#endif
-#ifdef ENABLE_UV_INTERP
+#if defined(ENABLE_UV_INTERP)
varying vec2 uv_interp;
#endif
-#ifdef ENABLE_UV2_INTERP
+#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
varying vec2 uv2_interp;
#endif
@@ -116,6 +121,171 @@ VERTEX_SHADER_GLOBALS
/* clang-format on */
+#ifdef RENDER_DEPTH_DUAL_PARABOLOID
+
+varying highp float dp_clip;
+uniform highp float shadow_dual_paraboloid_render_zfar;
+uniform highp float shadow_dual_paraboloid_render_side;
+
+#endif
+
+#if defined(USE_SHADOW) && defined(USE_LIGHTING)
+
+uniform highp mat4 light_shadow_matrix;
+varying highp vec4 shadow_coord;
+
+#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4)
+uniform highp mat4 light_shadow_matrix2;
+varying highp vec4 shadow_coord2;
+#endif
+
+#if defined(LIGHT_USE_PSSM4)
+
+uniform highp mat4 light_shadow_matrix3;
+uniform highp mat4 light_shadow_matrix4;
+varying highp vec4 shadow_coord3;
+varying highp vec4 shadow_coord4;
+
+#endif
+
+#endif
+
+#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING)
+
+varying highp vec3 diffuse_interp;
+varying highp vec3 specular_interp;
+
+// general for all lights
+uniform vec4 light_color;
+uniform float light_specular;
+
+// directional
+uniform vec3 light_direction;
+
+// omni
+uniform vec3 light_position;
+
+uniform float light_range;
+uniform float light_attenuation;
+
+// spot
+uniform float light_spot_attenuation;
+uniform float light_spot_range;
+uniform float light_spot_angle;
+
+void light_compute(
+ vec3 N,
+ vec3 L,
+ vec3 V,
+ vec3 light_color,
+ vec3 attenuation,
+ float roughness) {
+
+//this makes lights behave closer to linear, but then addition of lights looks bad
+//better left disabled
+
+//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545);
+/*
+#define SRGB_APPROX(m_var) {\
+ float S1 = sqrt(m_var);\
+ float S2 = sqrt(S1);\
+ float S3 = sqrt(S2);\
+ m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\
+ }
+*/
+#define SRGB_APPROX(m_var)
+
+ float NdotL = dot(N, L);
+ float cNdotL = max(NdotL, 0.0); // clamped NdotL
+ float NdotV = dot(N, V);
+ float cNdotV = max(NdotV, 0.0);
+
+#if defined(DIFFUSE_OREN_NAYAR)
+ vec3 diffuse_brdf_NL;
+#else
+ float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
+#endif
+
+#if defined(DIFFUSE_LAMBERT_WRAP)
+ // energy conserving lambert wrap shader
+ diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
+
+#elif defined(DIFFUSE_OREN_NAYAR)
+
+ {
+ // see http://mimosa-pudica.net/improved-oren-nayar.html
+ float LdotV = dot(L, V);
+
+ float s = LdotV - NdotL * NdotV;
+ float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
+
+ float sigma2 = roughness * roughness; // TODO: this needs checking
+ vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13));
+ float B = 0.45 * sigma2 / (sigma2 + 0.09);
+
+ diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
+ }
+#else
+ // lambert by default for everything else
+ diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
+#endif
+
+ SRGB_APPROX(diffuse_brdf_NL)
+
+ diffuse_interp += light_color * diffuse_brdf_NL * attenuation;
+
+ if (roughness > 0.0) {
+
+ // D
+ float specular_brdf_NL = 0.0;
+
+#if !defined(SPECULAR_DISABLED)
+ //normalized blinn always unless disabled
+ vec3 H = normalize(V + L);
+ float cNdotH = max(dot(N, H), 0.0);
+ float cVdotH = max(dot(V, H), 0.0);
+ float cLdotH = max(dot(L, H), 0.0);
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float blinn = pow(cNdotH, shininess);
+ blinn *= (shininess + 8.0) / (8.0 * 3.141592654);
+ specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
+#endif
+
+ SRGB_APPROX(specular_brdf_NL)
+ specular_interp += specular_brdf_NL * light_color * attenuation;
+ }
+}
+
+#endif
+
+#ifdef USE_VERTEX_LIGHTING
+
+#ifdef USE_REFLECTION_PROBE1
+
+uniform mat4 refprobe1_local_matrix;
+varying mediump vec4 refprobe1_reflection_normal_blend;
+uniform vec3 refprobe1_box_extents;
+
+#ifndef USE_LIGHTMAP
+varying mediump vec3 refprobe1_ambient_normal;
+#endif
+
+#endif //reflection probe1
+
+#ifdef USE_REFLECTION_PROBE2
+
+uniform mat4 refprobe2_local_matrix;
+varying mediump vec4 refprobe2_reflection_normal_blend;
+uniform vec3 refprobe2_box_extents;
+
+#ifndef USE_LIGHTMAP
+varying mediump vec3 refprobe2_ambient_normal;
+#endif
+
+#endif //reflection probe2
+
+#endif //vertex lighting for refprobes
+
void main() {
highp vec4 vertex = vertex_attrib;
@@ -131,6 +301,7 @@ void main() {
vec4(0.0, 0.0, 0.0, 1.0));
world_matrix = world_matrix * transpose(m);
}
+
#endif
vec3 normal = normal_attrib * normal_mult;
@@ -142,18 +313,18 @@ void main() {
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
-#ifdef ENABLE_COLOR_INTERP
+#if defined(ENABLE_COLOR_INTERP)
color_interp = color_attrib;
#ifdef USE_INSTANCING
color_interp *= instance_color;
#endif
#endif
-#ifdef ENABLE_UV_INTERP
+#if defined(ENABLE_UV_INTERP)
uv_interp = uv_attrib;
#endif
-#ifdef ENABLE_UV2_INTERP
+#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib;
#endif
@@ -209,6 +380,7 @@ void main() {
#endif
mat4 modelview = camera_matrix * world_matrix;
+ float roughness = 1.0;
#define world_transform world_matrix
@@ -252,13 +424,166 @@ VERTEX_SHADER_CODE
#ifdef RENDER_DEPTH
+#ifdef RENDER_DEPTH_DUAL_PARABOLOID
+
+ vertex_interp.z *= shadow_dual_paraboloid_render_side;
+ normal_interp.z *= shadow_dual_paraboloid_render_side;
+
+ dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
+
+ //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
+
+ highp vec3 vtx = vertex_interp + normalize(vertex_interp) * light_bias;
+ highp float distance = length(vtx);
+ vtx = normalize(vtx);
+ vtx.xy /= 1.0 - vtx.z;
+ vtx.z = (distance / shadow_dual_paraboloid_render_zfar);
+ vtx.z = vtx.z * 2.0 - 1.0;
+
+ vertex_interp = vtx;
+
+#else
float z_ofs = light_bias;
z_ofs += (1.0 - abs(normal_interp.z)) * light_normal_bias;
vertex_interp.z -= z_ofs;
+#endif //dual parabolloid
+
+#endif //depth
+
+//vertex lighting
+#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING)
+ //vertex shaded version of lighting (more limited)
+ vec3 L;
+ vec3 light_att;
+
+#ifdef LIGHT_MODE_OMNI
+ vec3 light_vec = light_position - vertex_interp;
+ float light_length = length(light_vec);
+
+ float normalized_distance = light_length / light_range;
+
+ if (normalized_distance < 1.0) {
+
+ float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation);
+
+ vec3 attenuation = vec3(omni_attenuation);
+ light_att = vec3(omni_attenuation);
+ } else {
+ light_att = vec3(0.0);
+ }
+
+ L = normalize(light_vec);
+
+#endif
+
+#ifdef LIGHT_MODE_SPOT
+
+ vec3 light_rel_vec = light_position - vertex_interp;
+ float light_length = length(light_rel_vec);
+ float normalized_distance = light_length / light_range;
+
+ if (normalized_distance < 1.0) {
+
+ float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation);
+ vec3 spot_dir = light_direction;
+
+ float spot_cutoff = light_spot_angle;
+
+ float angle = dot(-normalize(light_rel_vec), spot_dir);
+
+ if (angle > spot_cutoff) {
+
+ float scos = max(angle, spot_cutoff);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff));
+
+ spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation);
+
+ light_att = vec3(spot_attenuation);
+ } else {
+ light_att = vec3(0.0);
+ }
+ } else {
+ light_att = vec3(0.0);
+ }
+
+ L = normalize(light_rel_vec);
+
+#endif
+
+#ifdef LIGHT_MODE_DIRECTIONAL
+ vec3 light_vec = -light_direction;
+ light_att = vec3(1.0); //no base attenuation
+ L = normalize(light_vec);
+#endif
+
+ diffuse_interp = vec3(0.0);
+ specular_interp = vec3(0.0);
+ light_compute(normal_interp, L, -normalize(vertex_interp), light_color.rgb, light_att, roughness);
+
+#endif
+
+//shadows (for both vertex and fragment)
+#if defined(USE_SHADOW) && defined(USE_LIGHTING)
+
+ vec4 vi4 = vec4(vertex_interp, 1.0);
+ shadow_coord = light_shadow_matrix * vi4;
+
+#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4)
+ shadow_coord2 = light_shadow_matrix2 * vi4;
+#endif
+
+#if defined(LIGHT_USE_PSSM4)
+ shadow_coord3 = light_shadow_matrix3 * vi4;
+ shadow_coord4 = light_shadow_matrix4 * vi4;
+
+#endif
+
+#endif //use shadow and use lighting
+
+#ifdef USE_VERTEX_LIGHTING
+
+#ifdef USE_REFLECTION_PROBE1
+ {
+ vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp));
+ vec3 local_pos = (refprobe1_local_matrix * vec4(vertex_interp, 1.0)).xyz;
+ vec3 inner_pos = abs(local_pos / refprobe1_box_extents);
+ float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
+
+ {
+ vec3 local_ref_vec = (refprobe1_local_matrix * vec4(ref_normal, 0.0)).xyz;
+ refprobe1_reflection_normal_blend.xyz = local_ref_vec;
+ refprobe1_reflection_normal_blend.a = blend;
+ }
+#ifndef USE_LIGHTMAP
+ refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz;
#endif
+ }
+
+#endif //USE_REFLECTION_PROBE1
+
+#ifdef USE_REFLECTION_PROBE2
+ {
+ vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp));
+ vec3 local_pos = (refprobe2_local_matrix * vec4(vertex_interp, 1.0)).xyz;
+ vec3 inner_pos = abs(local_pos / refprobe2_box_extents);
+ float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
+
+ {
+ vec3 local_ref_vec = (refprobe2_local_matrix * vec4(ref_normal, 0.0)).xyz;
+ refprobe2_reflection_normal_blend.xyz = local_ref_vec;
+ refprobe2_reflection_normal_blend.a = blend;
+ }
+#ifndef USE_LIGHTMAP
+
+ refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz;
+#endif
+ }
+#endif //USE_REFLECTION_PROBE2
+
+#endif //use vertex lighting
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
}
@@ -276,12 +601,13 @@ VERTEX_SHADER_CODE
#define highp
#else
precision mediump float;
-precision mediump int;
+precision highp int;
#endif
#include "stdlib.glsl"
#define M_PI 3.14159265359
+#define SHADER_IS_SRGB true
//
// uniforms
@@ -297,20 +623,179 @@ uniform mat4 world_transform;
uniform highp float time;
-#ifdef SCREEN_UV_USED
+#if defined(SCREEN_UV_USED)
uniform vec2 screen_pixel_size;
#endif
-uniform highp sampler2D depth_buffer; //texunit:-5
+// I think supporting this in GLES2 is difficult
+// uniform highp sampler2D depth_buffer;
#if defined(SCREEN_TEXTURE_USED)
-uniform highp sampler2D screen_texture; //texunit:-6
+uniform highp sampler2D screen_texture; //texunit:-4
#endif
-#ifdef USE_RADIANCE_MAP
+#ifdef USE_REFLECTION_PROBE1
+
+#ifdef USE_VERTEX_LIGHTING
+
+varying mediump vec4 refprobe1_reflection_normal_blend;
+#ifndef USE_LIGHTMAP
+varying mediump vec3 refprobe1_ambient_normal;
+#endif
+
+#else
+
+uniform bool refprobe1_use_box_project;
+uniform vec3 refprobe1_box_extents;
+uniform vec3 refprobe1_box_offset;
+uniform mat4 refprobe1_local_matrix;
+
+#endif //use vertex lighting
+
+uniform bool refprobe1_exterior;
+
+uniform highp samplerCube reflection_probe1; //texunit:-5
+
+uniform float refprobe1_intensity;
+uniform vec4 refprobe1_ambient;
+
+#endif //USE_REFLECTION_PROBE1
+
+#ifdef USE_REFLECTION_PROBE2
+
+#ifdef USE_VERTEX_LIGHTING
+
+varying mediump vec4 refprobe2_reflection_normal_blend;
+#ifndef USE_LIGHTMAP
+varying mediump vec3 refprobe2_ambient_normal;
+#endif
+
+#else
+
+uniform bool refprobe2_use_box_project;
+uniform vec3 refprobe2_box_extents;
+uniform vec3 refprobe2_box_offset;
+uniform mat4 refprobe2_local_matrix;
+
+#endif //use vertex lighting
+
+uniform bool refprobe2_exterior;
+
+uniform highp samplerCube reflection_probe2; //texunit:-6
+
+uniform float refprobe2_intensity;
+uniform vec4 refprobe2_ambient;
+
+#endif //USE_REFLECTION_PROBE2
#define RADIANCE_MAX_LOD 6.0
+#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
+
+void reflection_process(samplerCube reflection_map,
+#ifdef USE_VERTEX_LIGHTING
+ vec3 ref_normal,
+#ifndef USE_LIGHTMAP
+ vec3 amb_normal,
+#endif
+ float ref_blend,
+
+#else //no vertex lighting
+ vec3 normal, vec3 vertex,
+ mat4 local_matrix,
+ bool use_box_project, vec3 box_extents, vec3 box_offset,
+#endif //vertex lighting
+ bool exterior, float intensity, vec4 ref_ambient, float roughness, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) {
+
+ vec4 reflection;
+
+#ifdef USE_VERTEX_LIGHTING
+
+ reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb;
+
+ float blend = ref_blend; //crappier blend formula for vertex
+ blend *= blend;
+ blend = max(0.0, 1.0 - blend);
+
+#else //fragment lighting
+
+ vec3 local_pos = (local_matrix * vec4(vertex, 1.0)).xyz;
+
+ if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
+ return;
+ }
+
+ vec3 inner_pos = abs(local_pos / box_extents);
+ float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
+ blend = mix(length(inner_pos), blend, blend);
+ blend *= blend;
+ blend = max(0.0, 1.0 - blend);
+
+ //reflect and make local
+ vec3 ref_normal = normalize(reflect(vertex, normal));
+ ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz;
+
+ if (use_box_project) { //box project
+
+ vec3 nrdir = normalize(ref_normal);
+ vec3 rbmax = (box_extents - local_pos) / nrdir;
+ vec3 rbmin = (-box_extents - local_pos) / nrdir;
+
+ vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0))));
+
+ float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
+ vec3 posonbox = local_pos + nrdir * fa;
+ ref_normal = posonbox - box_offset.xyz;
+ }
+
+ reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb;
+#endif
+
+ if (exterior) {
+ reflection.rgb = mix(skybox, reflection.rgb, blend);
+ }
+ reflection.rgb *= intensity;
+ reflection.a = blend;
+ reflection.rgb *= blend;
+
+ reflection_accum += reflection;
+
+#ifndef USE_LIGHTMAP
+
+ vec4 ambient_out;
+#ifndef USE_VERTEX_LIGHTING
+
+ vec3 amb_normal = (local_matrix * vec4(normal, 0.0)).xyz;
+#endif
+
+ ambient_out.rgb = textureCubeLod(reflection_map, amb_normal, RADIANCE_MAX_LOD).rgb;
+ ambient_out.rgb = mix(ref_ambient.rgb, ambient_out.rgb, ref_ambient.a);
+ if (exterior) {
+ ambient_out.rgb = mix(ambient, ambient_out.rgb, blend);
+ }
+
+ ambient_out.a = blend;
+ ambient_out.rgb *= blend;
+ ambient_accum += ambient_out;
+
+#endif
+}
+
+#endif //use refprobe 1 or 2
+
+#ifdef USE_LIGHTMAP
+uniform mediump sampler2D lightmap; //texunit:-4
+uniform mediump float lightmap_energy;
+#endif
+
+#ifdef USE_LIGHTMAP_CAPTURE
+uniform mediump vec4[12] lightmap_captures;
+uniform bool lightmap_capture_sky;
+
+#endif
+
+#ifdef USE_RADIANCE_MAP
+
uniform samplerCube radiance_map; // texunit:-2
uniform mat4 radiance_inverse_xform;
@@ -323,49 +808,68 @@ uniform float ambient_sky_contribution;
uniform vec4 ambient_color;
uniform float ambient_energy;
-#ifdef LIGHT_PASS
+#ifdef USE_LIGHTING
-#define LIGHT_TYPE_DIRECTIONAL 0
-#define LIGHT_TYPE_OMNI 1
-#define LIGHT_TYPE_SPOT 2
+#ifdef USE_VERTEX_LIGHTING
-// general for all lights
-uniform int light_type;
+//get from vertex
+varying highp vec3 diffuse_interp;
+varying highp vec3 specular_interp;
-uniform float light_energy;
+#else
+//done in fragment
+// general for all lights
uniform vec4 light_color;
uniform float light_specular;
// directional
uniform vec3 light_direction;
-
// omni
uniform vec3 light_position;
-uniform float light_range;
-uniform vec4 light_attenuation;
+uniform float light_attenuation;
// spot
uniform float light_spot_attenuation;
uniform float light_spot_range;
uniform float light_spot_angle;
+#endif
-// shadows
-uniform highp sampler2D light_shadow_atlas; //texunit:-4
-uniform float light_has_shadow;
+//this is needed outside above if because dual paraboloid wants it
+uniform float light_range;
+
+#ifdef USE_SHADOW
+
+uniform highp vec2 shadow_pixel_size;
+
+#if defined(LIGHT_MODE_OMNI) || defined(LIGHT_MODE_SPOT)
+uniform highp sampler2D light_shadow_atlas; //texunit:-3
+#endif
+
+#ifdef LIGHT_MODE_DIRECTIONAL
+uniform highp sampler2D light_directional_shadow; // texunit:-3
+uniform highp vec4 light_split_offsets;
+#endif
+
+varying highp vec4 shadow_coord;
+
+#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4)
+varying highp vec4 shadow_coord2;
+#endif
+
+#if defined(LIGHT_USE_PSSM4)
+
+varying highp vec4 shadow_coord3;
+varying highp vec4 shadow_coord4;
+
+#endif
-uniform mat4 light_shadow_matrix;
uniform vec4 light_clamp;
-// directional shadow
+#endif // light shadow
-uniform highp sampler2D light_directional_shadow; // texunit:-4
-uniform vec4 light_split_offsets;
+// directional shadow
-uniform mat4 light_shadow_matrix1;
-uniform mat4 light_shadow_matrix2;
-uniform mat4 light_shadow_matrix3;
-uniform mat4 light_shadow_matrix4;
#endif
//
@@ -380,15 +884,15 @@ varying vec3 tangent_interp;
varying vec3 binormal_interp;
#endif
-#ifdef ENABLE_COLOR_INTERP
+#if defined(ENABLE_COLOR_INTERP)
varying vec4 color_interp;
#endif
-#ifdef ENABLE_UV_INTERP
+#if defined(ENABLE_UV_INTERP)
varying vec2 uv_interp;
#endif
-#ifdef ENABLE_UV2_INTERP
+#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
varying vec2 uv2_interp;
#endif
@@ -406,7 +910,79 @@ FRAGMENT_SHADER_GLOBALS
/* clang-format on */
-#ifdef LIGHT_PASS
+#ifdef RENDER_DEPTH_DUAL_PARABOLOID
+
+varying highp float dp_clip;
+
+#endif
+
+#ifdef USE_LIGHTING
+
+// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
+// We're dividing this factor off because the overall term we'll end up looks like
+// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
+//
+// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V)
+//
+// We're basically regouping this as
+//
+// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)]
+//
+// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V.
+//
+// The contents of the D and G (G1) functions (GGX) are taken from
+// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014).
+// Eqns 71-72 and 85-86 (see also Eqns 43 and 80).
+
+float G_GGX_2cos(float cos_theta_m, float alpha) {
+ // Schlick's approximation
+ // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994)
+ // Eq. (19), although see Heitz (2014) the about the problems with his derivation.
+ // It nevertheless approximates GGX well with k = alpha/2.
+ float k = 0.5 * alpha;
+ return 0.5 / (cos_theta_m * (1.0 - k) + k);
+
+ // float cos2 = cos_theta_m * cos_theta_m;
+ // float sin2 = (1.0 - cos2);
+ // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2));
+}
+
+float D_GGX(float cos_theta_m, float alpha) {
+ float alpha2 = alpha * alpha;
+ float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m;
+ return alpha2 / (M_PI * d * d);
+}
+
+float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
+ float cos2 = cos_theta_m * cos_theta_m;
+ float sin2 = (1.0 - cos2);
+ float s_x = alpha_x * cos_phi;
+ float s_y = alpha_y * sin_phi;
+ return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001);
+}
+
+float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
+ float cos2 = cos_theta_m * cos_theta_m;
+ float sin2 = (1.0 - cos2);
+ float r_x = cos_phi / alpha_x;
+ float r_y = sin_phi / alpha_y;
+ float d = cos2 + sin2 * (r_x * r_x + r_y * r_y);
+ return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001);
+}
+
+float SchlickFresnel(float u) {
+ float m = 1.0 - u;
+ float m2 = m * m;
+ return m2 * m2 * m; // pow(m,5)
+}
+
+float GTR1(float NdotH, float a) {
+ if (a >= 1.0) return 1.0 / M_PI;
+ float a2 = a * a;
+ float t = 1.0 + (a2 - 1.0) * NdotH * NdotH;
+ return (a2 - 1.0) / (M_PI * log(a2) * t);
+}
+
void light_compute(
vec3 N,
vec3 L,
@@ -428,52 +1004,274 @@ void light_compute(
inout vec3 diffuse_light,
inout vec3 specular_light) {
+//this makes lights behave closer to linear, but then addition of lights looks bad
+//better left disabled
+
+//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545);
+/*
+#define SRGB_APPROX(m_var) {\
+ float S1 = sqrt(m_var);\
+ float S2 = sqrt(S1);\
+ float S3 = sqrt(S2);\
+ m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\
+ }
+*/
+#define SRGB_APPROX(m_var)
+
+#if defined(USE_LIGHT_SHADER_CODE)
+ // light is written by the light shader
+
+ vec3 normal = N;
+ vec3 albedo = diffuse_color;
+ vec3 light = L;
+ vec3 view = V;
+
+ /* clang-format off */
+
+LIGHT_SHADER_CODE
+
+ /* clang-format on */
+
+#else
float NdotL = dot(N, L);
- float cNdotL = max(NdotL, 0.0);
+ float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0);
- {
- // calculate diffuse reflection
-
- // TODO hardcode Oren Nayar for now
- float diffuse_brdf_NL;
+ if (metallic < 1.0) {
+#if defined(DIFFUSE_OREN_NAYAR)
+ vec3 diffuse_brdf_NL;
+#else
+ float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
+#endif
+#if defined(DIFFUSE_LAMBERT_WRAP)
+ // energy conserving lambert wrap shader
diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
- // diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
+
+#elif defined(DIFFUSE_OREN_NAYAR)
+
+ {
+ // see http://mimosa-pudica.net/improved-oren-nayar.html
+ float LdotV = dot(L, V);
+
+ float s = LdotV - NdotL * NdotV;
+ float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
+
+ float sigma2 = roughness * roughness; // TODO: this needs checking
+ vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13));
+ float B = 0.45 * sigma2 / (sigma2 + 0.09);
+
+ diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
+ }
+
+#elif defined(DIFFUSE_TOON)
+
+ diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL);
+
+#elif defined(DIFFUSE_BURLEY)
+
+ {
+
+ vec3 H = normalize(V + L);
+ float cLdotH = max(0.0, dot(L, H));
+
+ float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness;
+ float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV);
+ float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL);
+ diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
+ /*
+ float energyBias = mix(roughness, 0.0, 0.5);
+ float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
+ float fd90 = energyBias + 2.0 * VoH * VoH * roughness;
+ float f0 = 1.0;
+ float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0);
+ float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0);
+
+ diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;
+ */
+ }
+#else
+ // lambert
+ diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
+#endif
+
+ SRGB_APPROX(diffuse_brdf_NL)
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
+
+#if defined(TRANSMISSION_USED)
+ diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#endif
+
+#if defined(LIGHT_USE_RIM)
+ float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
+ diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
+#endif
}
- {
- // calculate specular reflection
+ if (roughness > 0.0) {
+
+ // D
+
+ float specular_brdf_NL;
+
+#if defined(SPECULAR_BLINN)
+
+ //normalized blinn
+ vec3 H = normalize(V + L);
+ float cNdotH = max(dot(N, H), 0.0);
+ float cVdotH = max(dot(V, H), 0.0);
+ float cLdotH = max(dot(L, H), 0.0);
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float blinn = pow(cNdotH, shininess);
+ blinn *= (shininess + 8.0) / (8.0 * 3.141592654);
+ specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
+
+#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
- float cRdotV = max(dot(R, V), 0.0);
- float blob_intensity = pow(cRdotV, (1.0 - roughness) * 256.0);
- specular_light += light_color * attenuation * blob_intensity * specular_blob_intensity;
+ float cRdotV = max(0.0, dot(R, V));
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float phong = pow(cRdotV, shininess);
+ phong *= (shininess + 8.0) / (8.0 * 3.141592654);
+ specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
+
+#elif defined(SPECULAR_TOON)
+
+ vec3 R = normalize(-reflect(L, N));
+ float RdotV = dot(R, V);
+ float mid = 1.0 - roughness;
+ mid *= mid;
+ specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
+
+#elif defined(SPECULAR_DISABLED)
+ // none..
+ specular_brdf_NL = 0.0;
+#elif defined(SPECULAR_SCHLICK_GGX)
+ // shlick+ggx as default
+
+ vec3 H = normalize(V + L);
+
+ float cNdotH = max(dot(N, H), 0.0);
+ float cLdotH = max(dot(L, H), 0.0);
+
+#if defined(LIGHT_USE_ANISOTROPY)
+
+ float aspect = sqrt(1.0 - anisotropy * 0.9);
+ float rx = roughness / aspect;
+ float ry = roughness * aspect;
+ float ax = rx * rx;
+ float ay = ry * ry;
+ float XdotH = dot(T, H);
+ float YdotH = dot(B, H);
+ float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
+ float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH);
+
+#else
+ float alpha = roughness * roughness;
+ float D = D_GGX(cNdotH, alpha);
+ float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha);
+#endif
+ // F
+ //float F0 = 1.0;
+ //float cLdotH5 = SchlickFresnel(cLdotH);
+ //float F = mix(cLdotH5, 1.0, F0);
+
+ specular_brdf_NL = cNdotL * D /* F */ * G;
+
+#endif
+
+ SRGB_APPROX(specular_brdf_NL)
+ specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+
+#if defined(LIGHT_USE_CLEARCOAT)
+ if (clearcoat_gloss > 0.0) {
+#if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN)
+ vec3 H = normalize(V + L);
+#endif
+#if !defined(SPECULAR_SCHLICK_GGX)
+ float cNdotH = max(dot(N, H), 0.0);
+ float cLdotH = max(dot(L, H), 0.0);
+ float cLdotH5 = SchlickFresnel(cLdotH);
+#endif
+ float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss));
+ float Fr = mix(.04, 1.0, cLdotH5);
+ float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25);
+
+ float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
+
+ specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ }
+#endif
}
+
+#endif //defined(USE_LIGHT_SHADER_CODE)
}
+#endif
// shadows
+#ifdef USE_SHADOW
+
+#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, texture2D(p_shadow, p_pos).r)
+#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, texture2DProj(p_shadow, p_pos).r)
+
float sample_shadow(
- highp sampler2D shadow,
- vec2 shadow_pixel_size,
- vec2 pos,
- float depth,
- vec4 clamp_rect) {
- // vec4 depth_value = texture2D(shadow, pos);
-
- // return depth_value.z;
- return texture2DProj(shadow, vec4(pos, depth, 1.0)).r;
- // return (depth_value.x + depth_value.y + depth_value.z + depth_value.w) / 4.0;
+ highp sampler2D shadow, highp vec4 spos) {
+
+#ifdef SHADOW_MODE_PCF_13
+
+ spos.xyz /= spos.w;
+ vec2 pos = spos.xy;
+ float depth = spos.z;
+
+ float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth);
+ return avg * (1.0 / 13.0);
+#endif
+
+#ifdef SHADOW_MODE_PCF_5
+
+ spos.xyz /= spos.w;
+ vec2 pos = spos.xy;
+ float depth = spos.z;
+
+ float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth);
+ avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth);
+ return avg * (1.0 / 5.0);
+
+#endif
+
+#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+
+ return SAMPLE_SHADOW_TEXEL_PROJ(shadow, spos);
+#endif
}
#endif
void main() {
+#ifdef RENDER_DEPTH_DUAL_PARABOLOID
+
+ if (dp_clip > 0.0)
+ discard;
+#endif
highp vec3 vertex = vertex_interp;
vec3 albedo = vec3(1.0);
vec3 transmission = vec3(0.0);
@@ -487,6 +1285,7 @@ void main() {
float clearcoat_gloss = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
+ float sss_strength = 0.0; //unused
float alpha = 1.0;
float side = 1.0;
@@ -510,11 +1309,11 @@ void main() {
#endif
float normaldepth = 1.0;
-#ifdef ALPHA_SCISSOR_USED
+#if defined(ALPHA_SCISSOR_USED)
float alpha_scissor = 0.5;
#endif
-#ifdef SCREEN_UV_USED
+#if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
#endif
@@ -530,8 +1329,8 @@ FRAGMENT_SHADER_CODE
normalmap.xy = normalmap.xy * 2.0 - 1.0;
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy)));
- // normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side;
- normal = normalmap;
+ normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side;
+ //normal = normalmap;
#endif
normal = normalize(normal);
@@ -540,300 +1339,512 @@ FRAGMENT_SHADER_CODE
vec3 specular_light = vec3(0.0, 0.0, 0.0);
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
-
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
- vec3 env_reflection_light = vec3(0.0, 0.0, 0.0);
-
vec3 eye_position = -normalize(vertex_interp);
-#ifdef ALPHA_SCISSOR_USED
+#if defined(ALPHA_SCISSOR_USED)
if (alpha < alpha_scissor) {
discard;
}
#endif
+#ifdef BASE_PASS
+ //none
+#ifdef USE_RADIANCE_MAP
+
+ vec3 ref_vec = reflect(-eye_position, N);
+ ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz);
+
+ ref_vec.z *= -1.0;
+
+ specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
+
+ {
+ vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
+ vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).xyz * bg_energy;
+
+ ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
+ }
+
+#else
+
+ ambient_light = ambient_color.rgb;
+
+#endif
+
+ ambient_light *= ambient_energy;
+
+#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
+
+ vec4 ambient_accum = vec4(0.0);
+ vec4 reflection_accum = vec4(0.0);
+
+#ifdef USE_REFLECTION_PROBE1
+
+ reflection_process(reflection_probe1,
+#ifdef USE_VERTEX_LIGHTING
+ refprobe1_reflection_normal_blend.rgb,
+#ifndef USE_LIGHTMAP
+ refprobe1_ambient_normal,
+#endif
+ refprobe1_reflection_normal_blend.a,
+#else
+ normal_interp, vertex_interp, refprobe1_local_matrix,
+ refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset,
+#endif
+ refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness,
+ ambient_light, specular_light, reflection_accum, ambient_accum);
+
+#endif // USE_REFLECTION_PROBE1
+
+#ifdef USE_REFLECTION_PROBE2
+
+ reflection_process(reflection_probe2,
+#ifdef USE_VERTEX_LIGHTING
+ refprobe2_reflection_normal_blend.rgb,
+#ifndef USE_LIGHTMAP
+ refprobe2_ambient_normal,
+#endif
+ refprobe2_reflection_normal_blend.a,
+#else
+ normal_interp, vertex_interp, refprobe2_local_matrix,
+ refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset,
+#endif
+ refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness,
+ ambient_light, specular_light, reflection_accum, ambient_accum);
+
+#endif // USE_REFLECTION_PROBE2
+
+ if (reflection_accum.a > 0.0) {
+ specular_light = reflection_accum.rgb / reflection_accum.a;
+ }
+
+#ifndef USE_LIGHTMAP
+ if (ambient_accum.a > 0.0) {
+ ambient_light = ambient_accum.rgb / ambient_accum.a;
+ }
+#endif
+
+#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
+
+#ifdef USE_LIGHTMAP
+ //ambient light will come entirely from lightmap is lightmap is used
+ ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy;
+#endif
+
+#ifdef USE_LIGHTMAP_CAPTURE
+ {
+ vec3 cone_dirs[12] = vec3[](
+ vec3(0, 0, 1),
+ vec3(0.866025, 0, 0.5),
+ vec3(0.267617, 0.823639, 0.5),
+ vec3(-0.700629, 0.509037, 0.5),
+ vec3(-0.700629, -0.509037, 0.5),
+ vec3(0.267617, -0.823639, 0.5),
+ vec3(0, 0, -1),
+ vec3(0.866025, 0, -0.5),
+ vec3(0.267617, 0.823639, -0.5),
+ vec3(-0.700629, 0.509037, -0.5),
+ vec3(-0.700629, -0.509037, -0.5),
+ vec3(0.267617, -0.823639, -0.5));
+
+ vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz;
+ vec4 captured = vec4(0.0);
+ float sum = 0.0;
+ for (int i = 0; i < 12; i++) {
+ float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect
+ captured += lightmap_captures[i] * amount;
+ sum += amount;
+ }
+
+ captured /= sum;
+
+ if (lightmap_capture_sky) {
+ ambient_light = mix(ambient_light, captured.rgb, captured.a);
+ } else {
+ ambient_light = captured.rgb;
+ }
+ }
+#endif
+
+#endif //BASE PASS
+
//
// Lighting
//
-#ifdef LIGHT_PASS
+#ifdef USE_LIGHTING
+
+#ifndef USE_VERTEX_LIGHTING
+ vec3 L;
+#endif
+ vec3 light_att = vec3(1.0);
- if (light_type == LIGHT_TYPE_OMNI) {
- vec3 light_vec = light_position - vertex;
- float light_length = length(light_vec);
+#ifdef LIGHT_MODE_OMNI
- float normalized_distance = light_length / light_range;
+#ifndef USE_VERTEX_LIGHTING
+ vec3 light_vec = light_position - vertex;
+ float light_length = length(light_vec);
- float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation.w);
+ float normalized_distance = light_length / light_range;
+ if (normalized_distance < 1.0) {
- vec3 attenuation = vec3(omni_attenuation);
+ float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation);
- if (light_has_shadow > 0.5) {
- highp vec3 splane = (light_shadow_matrix * vec4(vertex, 1.0)).xyz;
- float shadow_len = length(splane);
+ light_att = vec3(omni_attenuation);
+ } else {
+ light_att = vec3(0.0);
+ }
+ L = normalize(light_vec);
+
+#endif
- splane = normalize(splane);
+#ifdef USE_SHADOW
+ {
+ highp vec4 splane = shadow_coord;
+ float shadow_len = length(splane.xyz);
- vec4 clamp_rect = light_clamp;
+ splane = normalize(splane.xyz);
- if (splane.z >= 0.0) {
- splane.z += 1.0;
+ vec4 clamp_rect = light_clamp;
- clamp_rect.y += clamp_rect.w;
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
+
+ clamp_rect.y += clamp_rect.w;
+ } else {
+ splane.z = 1.0 - splane.z;
+ }
+
+ splane.xy /= splane.z;
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len / light_range;
+
+ splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ splane.w = 1.0;
+
+ float shadow = sample_shadow(light_shadow_atlas, splane);
+
+ light_att *= shadow;
+ }
+#endif
+
+#endif //type omni
+
+#ifdef LIGHT_MODE_DIRECTIONAL
+
+#ifndef USE_VERTEX_LIGHTING
+ vec3 light_vec = -light_direction;
+ L = normalize(light_vec);
+#endif
+ float depth_z = -vertex.z;
+
+#ifdef USE_SHADOW
+
+#ifdef USE_VERTEX_LIGHTING
+ //compute shadows in a mobile friendly way
+
+#ifdef LIGHT_USE_PSSM4
+ //take advantage of prefetch
+ float shadow1 = sample_shadow(light_directional_shadow, shadow_coord);
+ float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2);
+ float shadow3 = sample_shadow(light_directional_shadow, shadow_coord3);
+ float shadow4 = sample_shadow(light_directional_shadow, shadow_coord4);
+
+ if (depth_z < light_split_offsets.w) {
+ float pssm_fade = 0.0;
+ float shadow_att = 1.0;
+#ifdef LIGHT_USE_PSSM_BLEND
+ float shadow_att2 = 1.0;
+ float pssm_blend = 0.0;
+ bool use_blend = true;
+#endif
+ if (depth_z < light_split_offsets.y) {
+ if (depth_z < light_split_offsets.x) {
+ shadow_att = shadow1;
+
+#ifdef LIGHT_USE_PSSM_BLEND
+ shadow_att2 = shadow2;
+
+ pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z);
+#endif
} else {
- splane.z = 1.0 - splane.z;
- }
+ shadow_att = shadow2;
+
+#ifdef LIGHT_USE_PSSM_BLEND
+ shadow_att2 = shadow3;
- splane.xy /= splane.z;
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len / light_range;
+ pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z);
+#endif
+ }
+ } else {
+ if (depth_z < light_split_offsets.z) {
- splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ shadow_att = shadow3;
- float shadow = sample_shadow(light_shadow_atlas, vec2(0.0), splane.xy, splane.z, clamp_rect);
+#if defined(LIGHT_USE_PSSM_BLEND)
+ shadow_att2 = shadow4;
+ pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z);
+#endif
- if (shadow > splane.z) {
} else {
- attenuation = vec3(0.0);
+
+ shadow_att = shadow4;
+ pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+ use_blend = false;
+#endif
}
}
+#if defined(LIGHT_USE_PSSM_BLEND)
+ if (use_blend) {
+ shadow_att = mix(shadow_att, shadow_att2, pssm_blend);
+ }
+#endif
+ light_att *= shadow_att;
+ }
+
+#endif //LIGHT_USE_PSSM4
+
+#ifdef LIGHT_USE_PSSM2
+
+ //take advantage of prefetch
+ float shadow1 = sample_shadow(light_directional_shadow, shadow_coord);
+ float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2);
- light_compute(
- normal,
- normalize(light_vec),
- eye_position,
- binormal,
- tangent,
- light_color.xyz * light_energy,
- attenuation,
- albedo,
- transmission,
- specular * light_specular,
- roughness,
- metallic,
- rim,
- rim_tint,
- clearcoat,
- clearcoat_gloss,
- anisotropy,
- diffuse_light,
- specular_light);
-
- } else if (light_type == LIGHT_TYPE_DIRECTIONAL) {
-
- vec3 light_vec = -light_direction;
- vec3 attenuation = vec3(1.0, 1.0, 1.0);
-
- float depth_z = -vertex.z;
-
- if (light_has_shadow > 0.5) {
+ if (depth_z < light_split_offsets.y) {
+ float shadow_att = 1.0;
+ float pssm_fade = 0.0;
+#ifdef LIGHT_USE_PSSM_BLEND
+ float shadow_att2 = 1.0;
+ float pssm_blend = 0.0;
+ bool use_blend = true;
+#endif
+ if (depth_z < light_split_offsets.x) {
+ float pssm_fade = 0.0;
+ shadow_att = shadow1;
+
+#ifdef LIGHT_USE_PSSM_BLEND
+ shadow_att2 = shadow2;
+ pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z);
+#endif
+ } else {
+
+ shadow_att = shadow2;
+ pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z);
+#ifdef LIGHT_USE_PSSM_BLEND
+ use_blend = false;
+#endif
+ }
+#ifdef LIGHT_USE_PSSM_BLEND
+ if (use_blend) {
+ shadow_att = mix(shadow_att, shadow_att2, pssm_blend);
+ }
+#endif
+ light_att *= shadow_att;
+ }
+
+#endif //LIGHT_USE_PSSM2
+
+#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
+
+ light_att *= sample_shadow(light_directional_shadow, shadow_coord);
+#endif //orthogonal
+
+#else //fragment version of pssm
+
+ {
#ifdef LIGHT_USE_PSSM4
- if (depth_z < light_split_offsets.w) {
+ if (depth_z < light_split_offsets.w) {
#elif defined(LIGHT_USE_PSSM2)
- if (depth_z < light_split_offsets.y) {
+ if (depth_z < light_split_offsets.y) {
#else
- if (depth_z < light_split_offsets.x) {
-#endif
+ if (depth_z < light_split_offsets.x) {
+#endif //pssm2
- vec3 pssm_coord;
- float pssm_fade = 0.0;
+ highp vec4 pssm_coord;
+ float pssm_fade = 0.0;
#ifdef LIGHT_USE_PSSM_BLEND
- float pssm_blend;
- vec3 pssm_coord2;
- bool use_blend = true;
+ float pssm_blend;
+ highp vec4 pssm_coord2;
+ bool use_blend = true;
#endif
#ifdef LIGHT_USE_PSSM4
- if (depth_z < light_split_offsets.y) {
- if (depth_z < light_split_offsets.x) {
- highp vec4 splane = (light_shadow_matrix1 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
+
+ if (depth_z < light_split_offsets.y) {
+ if (depth_z < light_split_offsets.x) {
+ pssm_coord = shadow_coord;
#ifdef LIGHT_USE_PSSM_BLEND
- splane = (light_shadow_matrix2 * vec4(vertex, 1.0));
- pssm_coord2 = splane.xyz / splane.w;
+ pssm_coord2 = shadow_coord2;
- pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z);
+ pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z);
#endif
- } else {
- highp vec4 splane = (light_shadow_matrix2 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
+ } else {
+ pssm_coord = shadow_coord2;
#ifdef LIGHT_USE_PSSM_BLEND
- splane = (light_shadow_matrix3 * vec4(vertex, 1.0));
- pssm_coord2 = splane.xyz / splane.w;
+ pssm_coord2 = shadow_coord3;
- pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z);
+ pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z);
#endif
- }
- } else {
- if (depth_z < light_split_offsets.z) {
+ }
+ } else {
+ if (depth_z < light_split_offsets.z) {
- highp vec4 splane = (light_shadow_matrix3 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
+ pssm_coord = shadow_coord3;
#if defined(LIGHT_USE_PSSM_BLEND)
- splane = (light_shadow_matrix4 * vec4(vertex, 1.0));
- pssm_coord2 = splane.xyz / splane.w;
- pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z);
+ pssm_coord2 = shadow_coord4;
+ pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z);
#endif
- } else {
+ } else {
- highp vec4 splane = (light_shadow_matrix4 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
- pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z);
+ pssm_coord = shadow_coord4;
+ pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z);
#if defined(LIGHT_USE_PSSM_BLEND)
- use_blend = false;
+ use_blend = false;
#endif
- }
}
+ }
#endif // LIGHT_USE_PSSM4
#ifdef LIGHT_USE_PSSM2
- if (depth_z < light_split_offsets.x) {
+ if (depth_z < light_split_offsets.x) {
- highp vec4 splane = (light_shadow_matrix1 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
+ pssm_coord = shadow_coord;
#ifdef LIGHT_USE_PSSM_BLEND
- splane = (light_shadow_matrix2 * vec4(vertex, 1.0));
- pssm_coord2 = splane.xyz / splane.w;
- pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z);
+ pssm_coord2 = shadow_coord2;
+ pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z);
#endif
- } else {
- highp vec4 splane = (light_shadow_matrix2 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
- pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z);
+ } else {
+
+ pssm_coord = shadow_coord2;
+ pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z);
#ifdef LIGHT_USE_PSSM_BLEND
- use_blend = false;
+ use_blend = false;
#endif
- }
+ }
#endif // LIGHT_USE_PSSM2
#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
- {
- highp vec4 splane = (light_shadow_matrix1 * vec4(vertex, 1.0));
- pssm_coord = splane.xyz / splane.w;
- }
+ {
+ pssm_coord = shadow_coord;
+ }
#endif
- float shadow = sample_shadow(light_shadow_atlas, vec2(0.0), pssm_coord.xy, pssm_coord.z, light_clamp);
+ float shadow = sample_shadow(light_directional_shadow, pssm_coord);
#ifdef LIGHT_USE_PSSM_BLEND
- if (use_blend) {
- shadow = mix(shadow, sample_shadow(light_shadow_atlas, vec2(0.0), pssm_coord2.xy, pssm_coord2.z, light_clamp), pssm_blend);
- }
+ if (use_blend) {
+ shadow = mix(shadow, sample_shadow(light_directional_shadow, pssm_coord2), pssm_blend);
+ }
#endif
- attenuation *= shadow;
- }
+ light_att *= shadow;
}
+ }
+#endif //use vertex lighting
- light_compute(normal,
- normalize(light_vec),
- eye_position,
- binormal,
- tangent,
- light_color.xyz * light_energy,
- attenuation,
- albedo,
- transmission,
- specular * light_specular,
- roughness,
- metallic,
- rim,
- rim_tint,
- clearcoat,
- clearcoat_gloss,
- anisotropy,
- diffuse_light,
- specular_light);
- } else if (light_type == LIGHT_TYPE_SPOT) {
-
- vec3 light_att = vec3(1.0);
-
- if (light_has_shadow > 0.5) {
- highp vec4 splane = (light_shadow_matrix * vec4(vertex, 1.0));
- splane.xyz /= splane.w;
-
- float shadow = sample_shadow(light_shadow_atlas, vec2(0.0), splane.xy, splane.z, light_clamp);
-
- if (shadow > splane.z) {
- } else {
- light_att = vec3(0.0);
- }
- }
+#endif //use shadow
- vec3 light_rel_vec = light_position - vertex;
- float light_length = length(light_rel_vec);
- float normalized_distance = light_length / light_range;
+#endif
- float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation.w);
- vec3 spot_dir = light_direction;
+#ifdef LIGHT_MODE_SPOT
- float spot_cutoff = light_spot_angle;
+ light_att = vec3(1.0);
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_cutoff);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff));
-
- spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation);
-
- light_att *= vec3(spot_attenuation);
-
- light_compute(
- normal,
- normalize(light_rel_vec),
- eye_position,
- binormal,
- tangent,
- light_color.xyz * light_energy,
- light_att,
- albedo,
- transmission,
- specular * light_specular,
- roughness,
- metallic,
- rim,
- rim_tint,
- clearcoat,
- clearcoat_gloss,
- anisotropy,
- diffuse_light,
- specular_light);
- }
+#ifndef USE_VERTEX_LIGHTING
- gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha);
-#else
+ vec3 light_rel_vec = light_position - vertex;
+ float light_length = length(light_rel_vec);
+ float normalized_distance = light_length / light_range;
-#ifdef RENDER_DEPTH
+ if (normalized_distance < 1.0) {
+ float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation);
+ vec3 spot_dir = light_direction;
-#else
+ float spot_cutoff = light_spot_angle;
+ float angle = dot(-normalize(light_rel_vec), spot_dir);
-#ifdef USE_RADIANCE_MAP
+ if (angle > spot_cutoff) {
+ float scos = max(angle, spot_cutoff);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff));
+ spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation);
- vec3 ref_vec = reflect(-eye_position, N);
- ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz);
+ light_att = vec3(spot_attenuation);
+ } else {
+ light_att = vec3(0.0);
+ }
+ } else {
+ light_att = vec3(0.0);
+ }
- ref_vec.z *= -1.0;
+ L = normalize(light_rel_vec);
- env_reflection_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
+#endif
+#ifdef USE_SHADOW
{
- vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
- vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).xyz * bg_energy;
+ highp vec4 splane = shadow_coord;
+ splane.xyz /= splane.w;
- ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
+ float shadow = sample_shadow(light_shadow_atlas, splane.xy, splane.z);
+ light_att *= shadow;
}
+#endif
- ambient_light *= ambient_energy;
+#endif
+
+#ifdef USE_VERTEX_LIGHTING
+ //vertex lighting
+
+ specular_light += specular_interp * specular * light_att;
+ diffuse_light += diffuse_interp * albedo * light_att;
- specular_light += env_reflection_light;
+#else
+ //fragment lighting
+ light_compute(
+ normal,
+ L,
+ eye_position,
+ binormal,
+ tangent,
+ light_color.xyz,
+ light_att,
+ albedo,
+ transmission,
+ specular * light_specular,
+ roughness,
+ metallic,
+ rim,
+ rim_tint,
+ clearcoat,
+ clearcoat_gloss,
+ anisotropy,
+ diffuse_light,
+ specular_light);
+
+#endif //vertex lighting
+
+#endif //USE_LIGHTING
+ //compute and merge
+
+#ifndef RENDER_DEPTH
+
+#ifdef SHADELESS
+
+ gl_FragColor = vec4(albedo, alpha);
+#else
ambient_light *= albedo;
@@ -849,8 +1860,13 @@ FRAGMENT_SHADER_CODE
// environment BRDF approximation
- // TODO shadeless
{
+
+#if defined(DIFFUSE_TOON)
+ //simplify for toon, as
+ specular_light *= specular * metallic * albedo * 2.0;
+#else
+ //TODO: this curve is not really designed for gammaspace, should be adjusted
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
vec4 r = roughness * c0 + c1;
@@ -860,15 +1876,18 @@ FRAGMENT_SHADER_CODE
vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo);
specular_light *= AB.x * specular_color + AB.y;
+#endif
}
gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha);
- // gl_FragColor = vec4(normal, 1.0);
-#else
- gl_FragColor = vec4(albedo, alpha);
+ //add emission if in base pass
+#ifdef BASE_PASS
+ gl_FragColor.rgb += emission;
#endif
-#endif // RENDER_DEPTH
+ // gl_FragColor = vec4(normal, 1.0);
+
+#endif //unshaded
-#endif // lighting
+#endif // not RENDER_DEPTH
}
diff --git a/drivers/gles2/shaders/stdlib.glsl b/drivers/gles2/shaders/stdlib.glsl
index 6bc81a22d8..3674d70c9f 100644
--- a/drivers/gles2/shaders/stdlib.glsl
+++ b/drivers/gles2/shaders/stdlib.glsl
@@ -35,3 +35,13 @@ highp vec4 texel2DFetch(highp sampler2D tex, ivec2 size, ivec2 coord) {
return texture2DLod(tex, vec2(x_coord, y_coord), 0.0);
}
+
+#ifndef USE_GLES_OVER_GL
+highp mat4 transpose(highp mat4 src) {
+ return mat4(
+ vec4(src[0].x, src[1].x, src[2].x, src[3].x),
+ vec4(src[0].y, src[1].y, src[2].y, src[3].y),
+ vec4(src[0].z, src[1].z, src[2].z, src[3].z),
+ vec4(src[0].w, src[1].w, src[2].w, src[3].w));
+}
+#endif
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 643d50797e..856c83e297 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -29,10 +29,12 @@
/*************************************************************************/
#include "rasterizer_canvas_gles3.h"
-#include "os/os.h"
-#include "project_settings.h"
+
+#include "core/os/os.h"
+#include "core/project_settings.h"
#include "rasterizer_scene_gles3.h"
#include "servers/visual/visual_server_raster.h"
+
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
#endif
@@ -832,6 +834,120 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
}
}
} break;
+ case Item::Command::TYPE_MULTIMESH: {
+
+ Item::CommandMultiMesh *mmesh = static_cast<Item::CommandMultiMesh *>(c);
+
+ RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh);
+
+ if (!multi_mesh)
+ break;
+
+ RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh);
+
+ if (!mesh_data)
+ break;
+
+ RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map);
+
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != VS::MULTIMESH_CUSTOM_DATA_NONE);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true);
+ //reset shader and force rebind
+ state.using_texture_rect = true;
+ _set_texture_rect_mode(false);
+
+ if (texture) {
+ Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
+ }
+
+ int amount = MAX(multi_mesh->size, multi_mesh->visible_instances);
+
+ for (int j = 0; j < mesh_data->surfaces.size(); j++) {
+ RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j];
+ // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
+ glBindVertexArray(s->instancing_array_id);
+
+ glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer
+
+ int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4;
+ glEnableVertexAttribArray(8);
+ glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
+ glVertexAttribDivisor(8, 1);
+ glEnableVertexAttribArray(9);
+ glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 4 * 4);
+ glVertexAttribDivisor(9, 1);
+
+ int color_ofs;
+
+ if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) {
+ glEnableVertexAttribArray(10);
+ glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 8 * 4);
+ glVertexAttribDivisor(10, 1);
+ color_ofs = 12 * 4;
+ } else {
+ glDisableVertexAttribArray(10);
+ glVertexAttrib4f(10, 0, 0, 1, 0);
+ color_ofs = 8 * 4;
+ }
+
+ int custom_data_ofs = color_ofs;
+
+ switch (multi_mesh->color_format) {
+
+ case VS::MULTIMESH_COLOR_NONE: {
+ glDisableVertexAttribArray(11);
+ glVertexAttrib4f(11, 1, 1, 1, 1);
+ } break;
+ case VS::MULTIMESH_COLOR_8BIT: {
+ glEnableVertexAttribArray(11);
+ glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + color_ofs);
+ glVertexAttribDivisor(11, 1);
+ custom_data_ofs += 4;
+
+ } break;
+ case VS::MULTIMESH_COLOR_FLOAT: {
+ glEnableVertexAttribArray(11);
+ glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs);
+ glVertexAttribDivisor(11, 1);
+ custom_data_ofs += 4 * 4;
+ } break;
+ }
+
+ switch (multi_mesh->custom_data_format) {
+
+ case VS::MULTIMESH_CUSTOM_DATA_NONE: {
+ glDisableVertexAttribArray(12);
+ glVertexAttrib4f(12, 1, 1, 1, 1);
+ } break;
+ case VS::MULTIMESH_CUSTOM_DATA_8BIT: {
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + custom_data_ofs);
+ glVertexAttribDivisor(12, 1);
+
+ } break;
+ case VS::MULTIMESH_CUSTOM_DATA_FLOAT: {
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + custom_data_ofs);
+ glVertexAttribDivisor(12, 1);
+ } break;
+ }
+
+ if (s->index_array_len) {
+ glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
+ } else {
+ glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
+ }
+
+ glBindVertexArray(0);
+ }
+
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false);
+ state.using_texture_rect = true;
+ _set_texture_rect_mode(false);
+
+ } break;
case Item::Command::TYPE_PARTICLES: {
Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(c);
@@ -1107,8 +1223,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
bool rebind_shader = true;
- Size2 rt_size = Size2(storage->frame.current_rt->width, storage->frame.current_rt->height);
-
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
@@ -1304,7 +1418,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
blend_mode = RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
}
- bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX);
+ bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || (blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX && blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA));
bool reclip = false;
if (last_blend_mode != blend_mode) {
@@ -1477,6 +1591,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (!t) {
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} else {
+ t = t->get_ptr();
glBindTexture(t->target, t->tex_id);
}
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index c7f2e54efb..bc4ea80328 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -33,6 +33,7 @@
#include "rasterizer_storage_gles3.h"
#include "servers/visual/rasterizer.h"
+
#include "shaders/canvas_shadow.glsl.gen.h"
class RasterizerSceneGLES3;
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index e4824695d5..6f13df621f 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -30,11 +30,9 @@
#include "rasterizer_gles3.h"
-#include "gl_context/context_gl.h"
-#include "os/os.h"
-#include "project_settings.h"
-
-#include <string.h>
+#include "core/os/os.h"
+#include "core/project_settings.h"
+#include "drivers/gl_context/context_gl.h"
RasterizerStorage *RasterizerGLES3::get_storage() {
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 0a264caf8f..543011aff3 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -66,6 +66,8 @@ public:
static void make_current();
static void register_config();
+ virtual bool is_low_end() const { return false; }
+
RasterizerGLES3();
~RasterizerGLES3();
};
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 88f14890ef..7160668fe8 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -29,9 +29,10 @@
/*************************************************************************/
#include "rasterizer_scene_gles3.h"
-#include "math_funcs.h"
-#include "os/os.h"
-#include "project_settings.h"
+
+#include "core/math/math_funcs.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
#include "rasterizer_canvas_gles3.h"
#include "servers/visual/visual_server_raster.h"
@@ -50,26 +51,6 @@ static const GLenum _cube_side_enum[6] = {
};
-static _FORCE_INLINE_ void store_transform2d(const Transform2D &p_mtx, float *p_array) {
-
- p_array[0] = p_mtx.elements[0][0];
- p_array[1] = p_mtx.elements[0][1];
- p_array[2] = 0;
- p_array[3] = 0;
- p_array[4] = p_mtx.elements[1][0];
- p_array[5] = p_mtx.elements[1][1];
- p_array[6] = 0;
- p_array[7] = 0;
- p_array[8] = 0;
- p_array[9] = 0;
- p_array[10] = 1;
- p_array[11] = 0;
- p_array[12] = p_mtx.elements[2][0];
- p_array[13] = p_mtx.elements[2][1];
- p_array[14] = 0;
- p_array[15] = 1;
-}
-
static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
p_array[0] = p_mtx.basis.elements[0][0];
p_array[1] = p_mtx.basis.elements[1][0];
@@ -1201,7 +1182,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
glActiveTexture(GL_TEXTURE0 + i);
- GLenum target;
+ GLenum target = GL_TEXTURE_2D;
GLuint tex = 0;
RasterizerStorageGLES3::Texture *t = storage->texture_owner.getptr(textures[i]);
@@ -1281,6 +1262,8 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
// TODO
} break;
+
+ default: {}
}
}
@@ -1508,6 +1491,7 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
}
} break;
+ default: {}
}
}
@@ -1556,8 +1540,11 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast<RasterizerStorageGLES3::MultiMesh *>(e->owner);
RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry);
- int amount = MAX(multi_mesh->size, multi_mesh->visible_instances);
+ int amount = MIN(multi_mesh->size, multi_mesh->visible_instances);
+ if (amount == -1) {
+ amount = multi_mesh->size;
+ }
#ifdef DEBUG_ENABLED
if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
@@ -1826,6 +1813,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
}
} break;
+ default: {}
}
}
@@ -2363,14 +2351,15 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
- if (!p_depth_pass) {
+ if (e->material->last_pass != render_pass) {
+ e->material->last_pass = render_pass;
+ e->material->index = current_material_index++;
+ }
- if (e->material->last_pass != render_pass) {
- e->material->last_pass = render_pass;
- e->material->index = current_material_index++;
- }
+ e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
+ e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT;
- e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
+ if (!p_depth_pass) {
if (e->instance->gi_probe_instances.size()) {
e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
@@ -2385,9 +2374,6 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
}
e->sort_key |= uint64_t(p_material->render_priority + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT;
- } else {
- e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT;
- e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
}
/*
@@ -2737,7 +2723,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
ubo_data.shadow_split_offsets[j] = li->shadow_transform[j].split;
- Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse();
+ Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).affine_inverse();
CameraMatrix bias;
bias.set_light_bias();
@@ -3034,13 +3020,14 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul
reflection_ubo.ambient[3] = rpi->probe_ptr->interior_ambient_probe_contrib;
} else {
Color ambient_linear;
- float contrib = 0;
+ // FIXME: contrib was retrieved but never used, is it meant to be set as ambient[3]? (GH-20361)
+ //float contrib = 0;
if (p_env) {
ambient_linear = p_env->ambient_color.to_linear();
ambient_linear.r *= p_env->ambient_energy;
ambient_linear.g *= p_env->ambient_energy;
ambient_linear.b *= p_env->ambient_energy;
- contrib = p_env->ambient_sky_contribution;
+ //contrib = p_env->ambient_sky_contribution;
}
reflection_ubo.ambient[0] = ambient_linear.r;
@@ -3097,40 +3084,6 @@ void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalida
glBindVertexArray(0);
}
-void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
-
- //copy to front buffer
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
-
- if (!env) {
- //no environment, simply convert from linear to srgb
- storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true);
- } else {
- /* FIXME: Why are both statements equal? */
- storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true);
- }
-
- storage->shaders.copy.bind();
-
- _copy_screen();
-
- //turn off everything used
- storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
-}
-
void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
//copy to front buffer
@@ -3164,7 +3117,6 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
current_material_index = 0;
state.used_sss = false;
state.used_screen_texture = false;
-
//fill list
for (int i = 0; i < p_cull_count; i++) {
@@ -3242,6 +3194,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
}
} break;
+ default: {}
}
}
}
@@ -4328,7 +4281,6 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
if (env) {
switch (env->bg_mode) {
case VS::ENV_BG_COLOR_SKY:
-
case VS::ENV_BG_SKY:
sky = storage->sky_owner.getornull(env->sky);
@@ -4366,6 +4318,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
break;
+ default: {}
}
}
@@ -4534,7 +4487,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light);
ERR_FAIL_COND(!light);
- uint32_t x, y, width, height, vp_height;
+ uint32_t x, y, width, height;
float dp_direction = 0.0;
float zfar = 0;
@@ -4616,7 +4569,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult;
normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult;
fbo = directional_shadow.fbo;
- vp_height = directional_shadow.size;
} else {
//set from shadow atlas
@@ -4626,7 +4578,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
fbo = shadow_atlas->fbo;
- vp_height = shadow_atlas->size;
uint32_t key = shadow_atlas->shadow_owners[p_light];
@@ -5180,13 +5131,13 @@ void RasterizerSceneGLES3::initialize() {
void RasterizerSceneGLES3::iteration() {
- shadow_filter_mode = ShadowFilterMode(int(ProjectSettings::get_singleton()->get("rendering/quality/shadows/filter_mode")));
- subsurface_scatter_follow_surface = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/follow_surface");
- subsurface_scatter_weight_samples = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/weight_samples");
- subsurface_scatter_quality = SubSurfaceScatterQuality(int(ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/quality")));
- subsurface_scatter_size = ProjectSettings::get_singleton()->get("rendering/quality/subsurface_scattering/scale");
+ shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
+ subsurface_scatter_follow_surface = GLOBAL_GET("rendering/quality/subsurface_scattering/follow_surface");
+ subsurface_scatter_weight_samples = GLOBAL_GET("rendering/quality/subsurface_scattering/weight_samples");
+ subsurface_scatter_quality = SubSurfaceScatterQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/quality")));
+ subsurface_scatter_size = GLOBAL_GET("rendering/quality/subsurface_scattering/scale");
- state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH, ProjectSettings::get_singleton()->get("rendering/quality/voxel_cone_tracing/high_quality"));
+ state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH, GLOBAL_GET("rendering/quality/voxel_cone_tracing/high_quality"));
}
void RasterizerSceneGLES3::finalize() {
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index cf387a69bc..b4c4a0558f 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -837,7 +837,6 @@ public:
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env);
void _copy_screen(bool p_invalidate_color = false, bool p_invalidate_depth = false);
- void _copy_to_front_buffer(Environment *env);
void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 0bb0e12b8e..797441c3a1 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "rasterizer_storage_gles3.h"
-#include "engine.h"
-#include "project_settings.h"
+#include "core/engine.h"
+#include "core/project_settings.h"
#include "rasterizer_canvas_gles3.h"
#include "rasterizer_scene_gles3.h"
@@ -1029,7 +1029,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
PoolVector<uint8_t> data;
- int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0);
+ int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
PoolVector<uint8_t>::Write wb = data.write();
@@ -1072,7 +1072,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
uint32_t *ptr = (uint32_t *)wb.ptr();
uint32_t num_pixels = data_size / 4;
- for (int ofs = 0; ofs < num_pixels; ofs++) {
+ for (uint32_t ofs = 0; ofs < num_pixels; ofs++) {
uint32_t px = ptr[ofs];
uint32_t a = px >> 30 & 0xFF;
@@ -1095,7 +1095,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
#else
ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES");
- return Ref<Image>();
+ ERR_FAIL_V(Ref<Image>());
#endif
}
@@ -1905,6 +1905,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
actions = &shaders.actions_particles;
actions->uniforms = &p_shader->uniforms;
} break;
+ case VS::SHADER_MAX: break; // Can't happen, but silences warning
}
Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
@@ -2028,6 +2029,14 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture";
} break;
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
+
+ pi.type = Variant::OBJECT;
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "TextureArray";
+ } break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D: {
@@ -2139,6 +2148,19 @@ Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringN
if (material->params.has(p_param))
return material->params[p_param];
+ return material_get_param_default(p_material, p_param);
+}
+
+Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const StringName &p_param) const {
+ const Material *material = material_owner.get(p_material);
+ ERR_FAIL_COND_V(!material, Variant());
+
+ if (material->shader) {
+ if (material->shader->uniforms.has(p_param)) {
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type);
+ }
+ }
return Variant();
}
@@ -4948,6 +4970,7 @@ void RasterizerStorageGLES3::light_set_param(RID p_light, VS::LightParam p_param
light->version++;
light->instance_change_notify();
} break;
+ default: {}
}
light->param[p_param] = p_value;
@@ -5272,6 +5295,9 @@ void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_
reflection_probe->instance_change_notify();
}
+void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+}
+
AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, AABB());
@@ -7338,7 +7364,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid);
glDeleteTextures(1, &gi_probe_data->tex_id);
- gi_probe_owner.free(p_rid);
+ gi_probe_data_owner.free(p_rid);
memdelete(gi_probe_data);
} else if (lightmap_capture_data_owner.owns(p_rid)) {
@@ -7346,7 +7372,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid);
lightmap_capture->instance_remove_deps();
- gi_probe_owner.free(p_rid);
+ lightmap_capture_data_owner.free(p_rid);
memdelete(lightmap_capture);
} else if (canvas_occluder_owner.owns(p_rid)) {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index b74dd77e26..9a4798ac2a 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -31,11 +31,12 @@
#ifndef RASTERIZERSTORAGEGLES3_H
#define RASTERIZERSTORAGEGLES3_H
-#include "self_list.h"
+#include "core/self_list.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/shader_language.h"
#include "shader_compiler_gles3.h"
#include "shader_gles3.h"
+
#include "shaders/blend_shape.glsl.gen.h"
#include "shaders/canvas.glsl.gen.h"
#include "shaders/copy.glsl.gen.h"
@@ -582,6 +583,7 @@ public:
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
virtual Variant material_get_param(RID p_material, const StringName &p_param) const;
+ virtual Variant material_get_param_default(RID p_material, const StringName &p_param) const;
virtual void material_set_line_width(RID p_material, float p_width);
virtual void material_set_next_pass(RID p_material, RID p_next_material);
@@ -689,7 +691,7 @@ public:
}
};
- class MultiMesh;
+ struct MultiMesh;
struct Mesh : public GeometryOwner {
@@ -1003,6 +1005,7 @@ public:
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution);
virtual AABB reflection_probe_get_aabb(RID p_probe) const;
virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index a78a392cbd..dbc8507951 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -30,7 +30,8 @@
#include "shader_compiler_gles3.h"
-#include "os/os.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
#define SL ShaderLanguage
@@ -78,6 +79,12 @@ static int _get_datatype_size(SL::DataType p_type) {
case SL::TYPE_SAMPLER2D: return 16;
case SL::TYPE_ISAMPLER2D: return 16;
case SL::TYPE_USAMPLER2D: return 16;
+ case SL::TYPE_SAMPLER2DARRAY: return 16;
+ case SL::TYPE_ISAMPLER2DARRAY: return 16;
+ case SL::TYPE_USAMPLER2DARRAY: return 16;
+ case SL::TYPE_SAMPLER3D: return 16;
+ case SL::TYPE_ISAMPLER3D: return 16;
+ case SL::TYPE_USAMPLER3D: return 16;
case SL::TYPE_SAMPLERCUBE: return 16;
}
@@ -111,6 +118,12 @@ static int _get_datatype_alignment(SL::DataType p_type) {
case SL::TYPE_SAMPLER2D: return 16;
case SL::TYPE_ISAMPLER2D: return 16;
case SL::TYPE_USAMPLER2D: return 16;
+ case SL::TYPE_SAMPLER2DARRAY: return 16;
+ case SL::TYPE_ISAMPLER2DARRAY: return 16;
+ case SL::TYPE_USAMPLER2DARRAY: return 16;
+ case SL::TYPE_SAMPLER3D: return 16;
+ case SL::TYPE_ISAMPLER3D: return 16;
+ case SL::TYPE_USAMPLER3D: return 16;
case SL::TYPE_SAMPLERCUBE: return 16;
}
@@ -860,6 +873,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture";
actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer";
actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor";
+ actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
//for light
actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view";
@@ -901,12 +915,24 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
- actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
+ bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley");
+
+ if (!force_lambert) {
+ actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
+ }
+
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
- actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
+ bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
+
+ if (!force_blinn) {
+ actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
+ } else {
+ actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n";
+ }
+
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h
index 7a32057741..1f903b8935 100644
--- a/drivers/gles3/shader_compiler_gles3.h
+++ b/drivers/gles3/shader_compiler_gles3.h
@@ -31,7 +31,7 @@
#ifndef SHADERCOMPILERGLES3_H
#define SHADERCOMPILERGLES3_H
-#include "pair.h"
+#include "core/pair.h"
#include "servers/visual/shader_language.h"
#include "servers/visual/shader_types.h"
#include "servers/visual_server.h"
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 007600bb42..799179e8d4 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -30,7 +30,7 @@
#include "shader_gles3.h"
-#include "print_string.h"
+#include "core/print_string.h"
//#define DEBUG_OPENGL
@@ -122,6 +122,11 @@ bool ShaderGLES3::bind() {
ERR_FAIL_COND_V(!version, false);
+ if (!version->ok) { //broken, unable to bind (do not throw error, you saw it before already when it failed compilation).
+ glUseProgram(0);
+ return false;
+ }
+
glUseProgram(version->id);
DEBUG_TEST_ERROR("Use Program");
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 996655615e..9db4942163 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -31,7 +31,10 @@
#ifndef SHADER_GLES3_H
#define SHADER_GLES3_H
-#include <stdio.h>
+#include "core/hash_map.h"
+#include "core/map.h"
+#include "core/math/camera_matrix.h"
+#include "core/variant.h"
#include "platform_config.h"
#ifndef GLES3_INCLUDE_H
@@ -40,10 +43,7 @@
#include GLES3_INCLUDE_H
#endif
-#include "camera_matrix.h"
-#include "hash_map.h"
-#include "map.h"
-#include "variant.h"
+#include <stdio.h>
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -336,6 +336,7 @@ public:
}
uint32_t get_version() const { return new_conditional_version.version; }
+ _FORCE_INLINE_ bool is_version_valid() const { return version && version->ok; }
void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) {
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 53f563303a..5203f53fa2 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -120,12 +120,12 @@ void main() {
vec4 color = color_attrib;
#ifdef USE_INSTANCING
- mat4 extra_matrix2 = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
+ mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
color *= instance_color;
vec4 instance_custom = instance_custom_data;
#else
- mat4 extra_matrix2 = extra_matrix;
+ mat4 extra_matrix_instance = extra_matrix;
vec4 instance_custom = vec4(0.0);
#endif
@@ -157,7 +157,7 @@ void main() {
#endif
-#define extra_matrix extra_matrix2
+#define extra_matrix extra_matrix_instance
{
/* clang-format off */
@@ -246,8 +246,8 @@ VERTEX_SHADER_CODE
pos = outvec.xy;
#endif
- local_rot.xy = normalize((modelview_matrix * (extra_matrix * vec4(1.0, 0.0, 0.0, 0.0))).xy);
- local_rot.zw = normalize((modelview_matrix * (extra_matrix * vec4(0.0, 1.0, 0.0, 0.0))).xy);
+ local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(1.0, 0.0, 0.0, 0.0))).xy);
+ local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(0.0, 1.0, 0.0, 0.0))).xy);
#ifdef USE_TEXTURE_RECT
local_rot.xy *= sign(src_rect.z);
local_rot.zw *= sign(src_rect.w);
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 12cbe02d0c..bcaf4a57a8 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -3,6 +3,8 @@
#define M_PI 3.14159265359
+#define SHADER_IS_SRGB false
+
/*
from VisualServer:
@@ -514,6 +516,7 @@ VERTEX_SHADER_CODE
/* clang-format off */
[fragment]
+
/* texture unit usage, N is max_texture_unity-N
1-skeleton
@@ -533,6 +536,7 @@ uniform highp mat4 world_transform;
/* clang-format on */
#define M_PI 3.14159265359
+#define SHADER_IS_SRGB false
/* Varyings */
@@ -1020,16 +1024,27 @@ LIGHT_SHADER_CODE
#if defined(SPECULAR_BLINN)
+ //normalized blinn
vec3 H = normalize(V + L);
float cNdotH = max(dot(N, H), 0.0);
- float intensity = pow(cNdotH, (1.0 - roughness) * 256.0);
+ float cVdotH = max(dot(V, H), 0.0);
+ float cLdotH = max(dot(L, H), 0.0);
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float blinn = pow(cNdotH, shininess);
+ blinn *= (shininess + 8.0) / (8.0 * 3.141592654);
+ float intensity = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
+
specular_light += light_color * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
float cRdotV = max(0.0, dot(R, V));
- float intensity = pow(cRdotV, (1.0 - roughness) * 256.0);
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float phong = pow(cRdotV, shininess);
+ phong *= (shininess + 8.0) / (8.0 * 3.141592654);
+ float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
+
specular_light += light_color * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_TOON)
@@ -1070,11 +1085,11 @@ LIGHT_SHADER_CODE
float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha);
#endif
// F
- float F0 = 1.0; // FIXME
- float cLdotH5 = SchlickFresnel(cLdotH);
- float F = mix(cLdotH5, 1.0, F0);
+ //float F0 = 1.0;
+ //float cLdotH5 = SchlickFresnel(cLdotH);
+ //float F = mix(cLdotH5, 1.0, F0);
- float specular_brdf_NL = cNdotL * D * F * G;
+ float specular_brdf_NL = cNdotL * D /* F */ * G;
specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
#endif
@@ -1121,8 +1136,9 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p
avg += textureProj(shadow, vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
return avg * (1.0 / 13.0);
+#endif
-#elif defined(SHADOW_MODE_PCF_5)
+#ifdef SHADOW_MODE_PCF_5
float avg = textureProj(shadow, vec4(pos, depth, 1.0));
avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
@@ -1131,7 +1147,9 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p
avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
return avg * (1.0 / 5.0);
-#else
+#endif
+
+#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
return textureProj(shadow, vec4(pos, depth, 1.0));
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
index e4aa8d5730..dd6d78849b 100644
--- a/drivers/gles3/shaders/tonemap.glsl
+++ b/drivers/gles3/shaders/tonemap.glsl
@@ -173,7 +173,7 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
return tonemap_aces(color, white);
#endif
- return clamp(color, vec3(0.0f), vec3(1.0f)); // no other seleced -> linear
+ return clamp(color, vec3(0.0f), vec3(1.0f)); // no other selected -> linear
}
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
diff --git a/drivers/png/SCsub b/drivers/png/SCsub
index 39480351a6..22fb1817d1 100644
--- a/drivers/png/SCsub
+++ b/drivers/png/SCsub
@@ -26,14 +26,24 @@ if env['builtin_libpng']:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_png.add_source_files(env.drivers_sources, thirdparty_sources)
env_png.Append(CPPPATH=[thirdparty_dir])
+ # Needed for drivers includes and in platform/javascript
+ env.Append(CPPPATH=[thirdparty_dir])
# Currently .ASM filter_neon.S does not compile on NT.
import os
- if ("neon_enabled" in env and env["neon_enabled"]) and os.name != "nt":
+ use_neon = "neon_enabled" in env and env["neon_enabled"] and os.name != "nt"
+ if use_neon:
env_png.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=2"])
- env_neon = env_png.Clone()
+ else:
+ env_png.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=0"])
+
+ env_thirdparty = env_png.Clone()
+ env_thirdparty.disable_warnings()
+ env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources)
+
+ if use_neon:
+ env_neon = env_thirdparty.Clone()
if "S_compiler" in env:
env_neon['CC'] = env['S_compiler']
neon_sources = []
@@ -41,8 +51,6 @@ if env['builtin_libpng']:
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon_intrinsics.c"))
neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon.S"))
env.drivers_sources += neon_sources
- else:
- env_png.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=0"])
# Godot source files
env_png.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp
index b08688892e..04acb9387e 100644
--- a/drivers/png/image_loader_png.cpp
+++ b/drivers/png/image_loader_png.cpp
@@ -30,8 +30,8 @@
#include "image_loader_png.h"
-#include "os/os.h"
-#include "print_string.h"
+#include "core/os/os.h"
+#include "core/print_string.h"
#include <string.h>
diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h
index 48f48e6bea..5dff7e3902 100644
--- a/drivers/png/image_loader_png.h
+++ b/drivers/png/image_loader_png.h
@@ -31,7 +31,7 @@
#ifndef IMAGE_LOADER_PNG_H
#define IMAGE_LOADER_PNG_H
-#include "io/image_loader.h"
+#include "core/io/image_loader.h"
#include <png.h>
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index 270ae36e1e..c5729f70b2 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -31,8 +31,8 @@
#include "resource_saver_png.h"
#include "core/image.h"
-#include "os/file_access.h"
-#include "project_settings.h"
+#include "core/os/file_access.h"
+#include "core/project_settings.h"
#include "scene/resources/texture.h"
#include <png.h>
diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h
index 109b4801da..34950f6723 100644
--- a/drivers/png/resource_saver_png.h
+++ b/drivers/png/resource_saver_png.h
@@ -31,8 +31,8 @@
#ifndef RESOURCE_SAVER_PNG_H
#define RESOURCE_SAVER_PNG_H
-#include "image.h"
-#include "io/resource_saver.h"
+#include "core/image.h"
+#include "core/io/resource_saver.h"
class ResourceSaverPNG : public ResourceFormatSaver {
public:
diff --git a/drivers/pulseaudio/SCsub b/drivers/pulseaudio/SCsub
index ee39fd2631..28b315ae66 100644
--- a/drivers/pulseaudio/SCsub
+++ b/drivers/pulseaudio/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 744b3a35e6..9c02549e39 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -32,10 +32,8 @@
#ifdef PULSEAUDIO_ENABLED
-#include <pulse/pulseaudio.h>
-
-#include "os/os.h"
-#include "project_settings.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
void AudioDriverPulseAudio::pa_state_cb(pa_context *c, void *userdata) {
AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)userdata;
@@ -45,10 +43,13 @@ void AudioDriverPulseAudio::pa_state_cb(pa_context *c, void *userdata) {
case PA_CONTEXT_FAILED:
ad->pa_ready = -1;
break;
-
case PA_CONTEXT_READY:
ad->pa_ready = 1;
break;
+ default:
+ // TODO: Check if we want to handle some of the other
+ // PA context states like PA_CONTEXT_UNCONNECTED.
+ break;
}
}
@@ -342,7 +343,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
unsigned int out_idx = 0;
for (unsigned int i = 0; i < ad->buffer_frames; i++) {
- for (unsigned int j = 0; j < ad->pa_map.channels - 1; j++) {
+ for (int j = 0; j < ad->pa_map.channels - 1; j++) {
ad->samples_out.write[out_idx++] = ad->samples_in[in_idx++] >> 16;
}
uint32_t l = ad->samples_in[in_idx++];
diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp
index c6d36a5749..9f5d9c1abf 100644
--- a/drivers/register_driver_types.cpp
+++ b/drivers/register_driver_types.cpp
@@ -31,11 +31,11 @@
#include "register_driver_types.h"
#include "core/math/geometry.h"
-#include "png/image_loader_png.h"
-#include "png/resource_saver_png.h"
+#include "drivers/png/image_loader_png.h"
+#include "drivers/png/resource_saver_png.h"
#ifdef TOOLS_ENABLED
-#include "convex_decomp/b2d_decompose.h"
+#include "drivers/convex_decomp/b2d_decompose.h"
#endif
#ifdef TOOLS_ENABLED
diff --git a/drivers/rtaudio/SCsub b/drivers/rtaudio/SCsub
index 2b0a602965..285658073c 100644
--- a/drivers/rtaudio/SCsub
+++ b/drivers/rtaudio/SCsub
@@ -11,9 +11,12 @@ thirdparty_sources = [
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-env.add_source_files(env.drivers_sources, thirdparty_sources)
env.Append(CPPPATH=[thirdparty_dir])
+env_thirdparty = env.Clone()
+env_thirdparty.disable_warnings()
+env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources)
+
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index 69830b542b..10ba0663f2 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -30,8 +30,8 @@
#include "audio_driver_rtaudio.h"
-#include "os/os.h"
-#include "project_settings.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
#ifdef RTAUDIO_ENABLED
diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub
index ada8255580..4888f56099 100644
--- a/drivers/unix/SCsub
+++ b/drivers/unix/SCsub
@@ -5,5 +5,3 @@ Import('env')
env.add_source_files(env.drivers_sources, "*.cpp")
env["check_c_headers"] = [ [ "mntent.h", "HAVE_MNTENT" ] ]
-
-Export('env')
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 5a4be6df4f..a5a9258c4a 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -32,18 +32,19 @@
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
-#ifndef ANDROID_ENABLED
-#include <sys/statvfs.h>
-#endif
-
#include "core/list.h"
-#include "os/memory.h"
-#include "print_string.h"
+#include "core/os/memory.h"
+#include "core/print_string.h"
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifndef ANDROID_ENABLED
+#include <sys/statvfs.h>
+#endif
+
#ifdef HAVE_MNTENT
#include <mntent.h>
#endif
@@ -59,7 +60,7 @@ Error DirAccessUnix::list_dir_begin() {
//char real_current_dir_name[2048]; //is this enough?!
//getcwd(real_current_dir_name,2048);
- //chdir(curent_path.utf8().get_data());
+ //chdir(current_path.utf8().get_data());
dir_stream = opendir(current_dir.utf8().get_data());
//chdir(real_current_dir_name);
if (!dir_stream)
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index a55acdbd34..26978930bd 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -33,16 +33,17 @@
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#include "core/os/dir_access.h"
+
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-#include "os/dir_access.h"
-
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
class DirAccessUnix : public DirAccess {
DIR *dir_stream;
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index ca16c6fcae..3b97b95f7c 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -33,7 +33,8 @@
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
#include "core/os/os.h"
-#include "print_string.h"
+#include "core/print_string.h"
+
#include <sys/stat.h>
#include <sys/types.h>
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 88bb39fbd1..d4a4f8230c 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -31,8 +31,9 @@
#ifndef FILE_ACCESS_UNIX_H
#define FILE_ACCESS_UNIX_H
-#include "os/file_access.h"
-#include "os/memory.h"
+#include "core/os/file_access.h"
+#include "core/os/memory.h"
+
#include <stdio.h>
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index d3d1ccfa85..83535045b1 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -31,7 +31,7 @@
#ifndef IP_UNIX_H
#define IP_UNIX_H
-#include "io/ip.h"
+#include "core/io/ip.h"
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
diff --git a/drivers/unix/mutex_posix.cpp b/drivers/unix/mutex_posix.cpp
index 1f13720f1e..e0004c5730 100644
--- a/drivers/unix/mutex_posix.cpp
+++ b/drivers/unix/mutex_posix.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "mutex_posix.h"
-#include "os/memory.h"
+
+#include "core/os/memory.h"
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
diff --git a/drivers/unix/mutex_posix.h b/drivers/unix/mutex_posix.h
index a4de1603f3..80d85eee61 100644
--- a/drivers/unix/mutex_posix.h
+++ b/drivers/unix/mutex_posix.h
@@ -33,7 +33,8 @@
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
-#include "os/mutex.h"
+#include "core/os/mutex.h"
+
#include <pthread.h>
class MutexPosix : public Mutex {
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
new file mode 100644
index 0000000000..3f03175403
--- /dev/null
+++ b/drivers/unix/net_socket_posix.cpp
@@ -0,0 +1,621 @@
+/*************************************************************************/
+/* net_socket_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "net_socket_posix.h"
+
+#if defined(UNIX_ENABLED)
+
+#include <errno.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifndef NO_FCNTL
+#ifdef __HAIKU__
+#include <fcntl.h>
+#else
+#include <sys/fcntl.h>
+#endif
+#else
+#include <sys/ioctl.h>
+#endif
+#include <netinet/in.h>
+
+#include <sys/socket.h>
+#ifdef JAVASCRIPT_ENABLED
+#include <arpa/inet.h>
+#endif
+
+#include <netinet/tcp.h>
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#define MSG_NOSIGNAL SO_NOSIGPIPE
+#endif
+
+// Some custom defines to minimize ifdefs
+#define SOCK_EMPTY -1
+#define SOCK_BUF(x) x
+#define SOCK_CBUF(x) x
+#define SOCK_IOCTL ioctl
+#define SOCK_CLOSE ::close
+
+/* Windows */
+#elif defined(WINDOWS_ENABLED)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#include <mswsock.h>
+// Some custom defines to minimize ifdefs
+#define SOCK_EMPTY INVALID_SOCKET
+#define SOCK_BUF(x) (char *)(x)
+#define SOCK_CBUF(x) (const char *)(x)
+#define SOCK_IOCTL ioctlsocket
+#define SOCK_CLOSE closesocket
+
+// Windows doesn't have this flag
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+// Workaround missing flag in MinGW
+#if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET)
+#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15)
+#endif
+
+#endif
+
+size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type) {
+
+ memset(p_addr, 0, sizeof(struct sockaddr_storage));
+ if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket
+
+ // IPv6 only socket with IPv4 address
+ ERR_FAIL_COND_V(!p_ip.is_wildcard() && p_ip_type == IP::TYPE_IPV6 && p_ip.is_ipv4(), 0);
+
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = htons(p_port);
+ if (p_ip.is_valid()) {
+ copymem(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16);
+ } else {
+ addr6->sin6_addr = in6addr_any;
+ }
+ return sizeof(sockaddr_in6);
+ } else { // IPv4 socket
+
+ // IPv4 socket with IPv6 address
+ ERR_FAIL_COND_V(!p_ip.is_ipv4(), 0);
+
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
+ addr4->sin_family = AF_INET;
+ addr4->sin_port = htons(p_port); // short, network byte order
+
+ if (p_ip.is_valid()) {
+ copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4);
+ } else {
+ addr4->sin_addr.s_addr = INADDR_ANY;
+ }
+
+ copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4);
+ return sizeof(sockaddr_in);
+ }
+}
+
+void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IP_Address &r_ip, uint16_t &r_port) {
+
+ if (p_addr->ss_family == AF_INET) {
+
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
+ r_ip.set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr));
+
+ r_port = ntohs(addr4->sin_port);
+
+ } else if (p_addr->ss_family == AF_INET6) {
+
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
+ r_ip.set_ipv6(addr6->sin6_addr.s6_addr);
+
+ r_port = ntohs(addr6->sin6_port);
+ };
+}
+
+NetSocket *NetSocketPosix::_create_func() {
+ return memnew(NetSocketPosix);
+}
+
+void NetSocketPosix::make_default() {
+#if defined(WINDOWS_ENABLED)
+ if (_create == NULL) {
+ WSADATA data;
+ WSAStartup(MAKEWORD(2, 2), &data);
+ }
+#endif
+ _create = _create_func;
+}
+
+void NetSocketPosix::cleanup() {
+#if defined(WINDOWS_ENABLED)
+ if (_create != NULL) {
+ WSACleanup();
+ }
+ _create = NULL;
+#endif
+}
+
+NetSocketPosix::NetSocketPosix() {
+ _sock = SOCK_EMPTY;
+ _ip_type = IP::TYPE_NONE;
+ _is_stream = false;
+}
+
+NetSocketPosix::~NetSocketPosix() {
+ close();
+}
+
+NetSocketPosix::NetError NetSocketPosix::_get_socket_error() {
+#if defined(WINDOWS_ENABLED)
+ int err = WSAGetLastError();
+
+ if (err == WSAEISCONN)
+ return ERR_NET_IS_CONNECTED;
+ if (err == WSAEINPROGRESS || err == WSAEALREADY)
+ return ERR_NET_IN_PROGRESS;
+ if (err == WSAEWOULDBLOCK)
+ return ERR_NET_WOULD_BLOCK;
+ ERR_PRINTS("Socket error: " + itos(err));
+ return ERR_NET_OTHER;
+#else
+ if (errno == EISCONN)
+ return ERR_NET_IS_CONNECTED;
+ if (errno == EINPROGRESS || errno == EALREADY)
+ return ERR_NET_IN_PROGRESS;
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return ERR_NET_WOULD_BLOCK;
+ ERR_PRINTS("Socket error: " + itos(errno));
+ return ERR_NET_OTHER;
+#endif
+}
+
+bool NetSocketPosix::_can_use_ip(const IP_Address p_ip, const bool p_for_bind) const {
+
+ if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) {
+ return false;
+ } else if (!p_for_bind && !p_ip.is_valid()) {
+ return false;
+ }
+ // Check if socket support this IP type.
+ IP::Type type = p_ip.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
+ if (_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type) {
+ return false;
+ }
+ return true;
+}
+
+void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream) {
+ _sock = p_sock;
+ _ip_type = p_ip_type;
+ _is_stream = p_is_stream;
+}
+
+Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
+ ERR_FAIL_COND_V(is_open(), ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(ip_type > IP::TYPE_ANY || ip_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER);
+
+#if defined(__OpenBSD__)
+ // OpenBSD does not support dual stacking, fallback to IPv4 only.
+ if (ip_type == IP::TYPE_ANY)
+ ip_type = IP::TYPE_IPV4;
+#endif
+
+ int family = ip_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6;
+ int protocol = p_sock_type == TYPE_TCP ? IPPROTO_TCP : IPPROTO_UDP;
+ int type = p_sock_type == TYPE_TCP ? SOCK_STREAM : SOCK_DGRAM;
+ _sock = socket(family, type, protocol);
+
+ if (_sock == SOCK_EMPTY && ip_type == IP::TYPE_ANY) {
+ // Careful here, changing the referenced parameter so the caller knows that we are using an IPv4 socket
+ // in place of a dual stack one, and further calls to _set_sock_addr will work as expected.
+ ip_type = IP::TYPE_IPV4;
+ family = AF_INET;
+ _sock = socket(family, type, protocol);
+ }
+
+ ERR_FAIL_COND_V(_sock == SOCK_EMPTY, FAILED);
+ _ip_type = ip_type;
+
+ if (family == AF_INET6) {
+ // Select IPv4 over IPv6 mapping
+ set_ipv6_only_enabled(ip_type != IP::TYPE_ANY);
+ }
+
+ if (protocol == IPPROTO_UDP && ip_type != IP::TYPE_IPV6) {
+ // Enable broadcasting for UDP sockets if it's not IPv6 only (IPv6 has no broadcast option).
+ set_broadcasting_enabled(true);
+ }
+
+ _is_stream = p_sock_type == TYPE_TCP;
+
+#if defined(WINDOWS_ENABLED)
+ if (!_is_stream) {
+ // Disable windows feature/bug reporting WSAECONNRESET/WSAENETRESET when
+ // recv/recvfrom and an ICMP reply was received from a previous send/sendto.
+ unsigned long disable = 0;
+ if (ioctlsocket(_sock, SIO_UDP_CONNRESET, &disable) == SOCKET_ERROR) {
+ print_verbose("Unable to turn off UDP WSAECONNRESET behaviour on Windows");
+ }
+ if (ioctlsocket(_sock, SIO_UDP_NETRESET, &disable) == SOCKET_ERROR) {
+ // This feature seems not to be supported on wine.
+ print_verbose("Unable to turn off UDP WSAENETRESET behaviour on Windows");
+ }
+ }
+#endif
+ return OK;
+}
+
+void NetSocketPosix::close() {
+
+ if (_sock != SOCK_EMPTY)
+ SOCK_CLOSE(_sock);
+
+ _sock = SOCK_EMPTY;
+ _ip_type = IP::TYPE_NONE;
+ _is_stream = false;
+}
+
+Error NetSocketPosix::bind(IP_Address p_addr, uint16_t p_port) {
+
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(!_can_use_ip(p_addr, true), ERR_INVALID_PARAMETER);
+
+ sockaddr_storage addr;
+ size_t addr_size = _set_addr_storage(&addr, p_addr, p_port, _ip_type);
+
+ if (::bind(_sock, (struct sockaddr *)&addr, addr_size) == SOCK_EMPTY) {
+ close();
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+
+ return OK;
+}
+
+Error NetSocketPosix::listen(int p_max_pending) {
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+
+ if (::listen(_sock, p_max_pending) == SOCK_EMPTY) {
+
+ close();
+ ERR_FAIL_V(FAILED);
+ };
+
+ return OK;
+}
+
+Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) {
+
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(!_can_use_ip(p_host, false), ERR_INVALID_PARAMETER);
+
+ struct sockaddr_storage addr;
+ size_t addr_size = _set_addr_storage(&addr, p_host, p_port, _ip_type);
+
+ if (::connect(_sock, (struct sockaddr *)&addr, addr_size) == SOCK_EMPTY) {
+
+ NetError err = _get_socket_error();
+
+ switch (err) {
+ // We are already connected
+ case ERR_NET_IS_CONNECTED:
+ return OK;
+ // Still waiting to connect, try again in a while
+ case ERR_NET_WOULD_BLOCK:
+ case ERR_NET_IN_PROGRESS:
+ return ERR_BUSY;
+ default:
+ ERR_PRINT("Connection to remote host failed!");
+ close();
+ return FAILED;
+ }
+ }
+
+ return OK;
+}
+
+Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
+
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+
+#if defined(WINDOWS_ENABLED)
+ bool ready = false;
+ fd_set rd, wr, ex;
+ fd_set *rdp = NULL;
+ fd_set *wrp = NULL;
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+ FD_SET(_sock, &ex);
+ struct timeval timeout = { p_timeout, 0 };
+ // For blocking operation, pass NULL timeout pointer to select.
+ struct timeval *tp = NULL;
+ if (p_timeout >= 0) {
+ // If timeout is non-negative, we want to specify the timeout instead.
+ tp = &timeout;
+ }
+
+ switch (p_type) {
+ case POLL_TYPE_IN:
+ FD_SET(_sock, &rd);
+ rdp = &rd;
+ break;
+ case POLL_TYPE_OUT:
+ FD_SET(_sock, &wr);
+ wrp = &wr;
+ break;
+ case POLL_TYPE_IN_OUT:
+ FD_SET(_sock, &rd);
+ FD_SET(_sock, &wr);
+ rdp = &rd;
+ wrp = &wr;
+ }
+ int ret = select(1, rdp, wrp, &ex, tp);
+
+ ERR_FAIL_COND_V(ret == SOCKET_ERROR, FAILED);
+
+ if (ret == 0)
+ return ERR_BUSY;
+
+ ERR_FAIL_COND_V(FD_ISSET(_sock, &ex), FAILED);
+
+ if (rdp && FD_ISSET(_sock, rdp))
+ ready = true;
+ if (wrp && FD_ISSET(_sock, wrp))
+ ready = true;
+
+ return ready ? OK : ERR_BUSY;
+#else
+ struct pollfd pfd;
+ pfd.fd = _sock;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ switch (p_type) {
+ case POLL_TYPE_IN:
+ pfd.events = POLLIN;
+ break;
+ case POLL_TYPE_OUT:
+ pfd.events = POLLOUT;
+ break;
+ case POLL_TYPE_IN_OUT:
+ pfd.events = POLLOUT || POLLIN;
+ }
+
+ int ret = ::poll(&pfd, 1, p_timeout);
+
+ ERR_FAIL_COND_V(ret < 0, FAILED);
+ ERR_FAIL_COND_V(pfd.revents & POLLERR, FAILED);
+
+ if (ret == 0)
+ return ERR_BUSY;
+
+ return OK;
+#endif
+}
+
+Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) {
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+
+ r_read = ::recv(_sock, SOCK_BUF(p_buffer), p_len, 0);
+
+ if (r_read < 0) {
+ NetError err = _get_socket_error();
+ if (err == ERR_NET_WOULD_BLOCK)
+ return ERR_BUSY;
+
+ return FAILED;
+ }
+
+ return OK;
+}
+
+Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+
+ struct sockaddr_storage from;
+ socklen_t len = sizeof(struct sockaddr_storage);
+ memset(&from, 0, len);
+
+ r_read = ::recvfrom(_sock, SOCK_BUF(p_buffer), p_len, 0, (struct sockaddr *)&from, &len);
+
+ if (r_read < 0) {
+ NetError err = _get_socket_error();
+ if (err == ERR_NET_WOULD_BLOCK)
+ return ERR_BUSY;
+
+ return FAILED;
+ }
+
+ if (from.ss_family == AF_INET) {
+ struct sockaddr_in *sin_from = (struct sockaddr_in *)&from;
+ r_ip.set_ipv4((uint8_t *)&sin_from->sin_addr);
+ r_port = ntohs(sin_from->sin_port);
+ } else if (from.ss_family == AF_INET6) {
+ struct sockaddr_in6 *s6_from = (struct sockaddr_in6 *)&from;
+ r_ip.set_ipv6((uint8_t *)&s6_from->sin6_addr);
+ r_port = ntohs(s6_from->sin6_port);
+ } else {
+ // Unsupported socket family, should never happen.
+ ERR_FAIL_V(FAILED);
+ }
+
+ return OK;
+}
+
+Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) {
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+
+ int flags = 0;
+ if (_is_stream)
+ flags = MSG_NOSIGNAL;
+ r_sent = ::send(_sock, SOCK_CBUF(p_buffer), p_len, flags);
+
+ if (r_sent < 0) {
+ NetError err = _get_socket_error();
+ if (err == ERR_NET_WOULD_BLOCK)
+ return ERR_BUSY;
+
+ return FAILED;
+ }
+
+ return OK;
+}
+
+Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
+ ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
+
+ struct sockaddr_storage addr;
+ size_t addr_size = _set_addr_storage(&addr, p_ip, p_port, _ip_type);
+ r_sent = ::sendto(_sock, SOCK_CBUF(p_buffer), p_len, 0, (struct sockaddr *)&addr, addr_size);
+
+ if (r_sent < 0) {
+ NetError err = _get_socket_error();
+ if (err == ERR_NET_WOULD_BLOCK)
+ return ERR_BUSY;
+
+ return FAILED;
+ }
+
+ return OK;
+}
+
+void NetSocketPosix::set_broadcasting_enabled(bool p_enabled) {
+ ERR_FAIL_COND(!is_open());
+ // IPv6 has no broadcast support.
+ ERR_FAIL_COND(_ip_type == IP::TYPE_IPV6);
+
+ int par = p_enabled ? 1 : 0;
+ if (setsockopt(_sock, SOL_SOCKET, SO_BROADCAST, SOCK_CBUF(&par), sizeof(int)) != 0) {
+ WARN_PRINT("Unable to change broadcast setting");
+ }
+}
+
+void NetSocketPosix::set_blocking_enabled(bool p_enabled) {
+ ERR_FAIL_COND(!is_open());
+
+ int ret = 0;
+#if defined(WINDOWS_ENABLED) || defined(NO_FCNTL)
+ unsigned long par = p_enabled ? 0 : 1;
+ ret = SOCK_IOCTL(_sock, FIONBIO, &par);
+#else
+ int opts = fcntl(_sock, F_GETFL);
+ if (p_enabled)
+ ret = fcntl(_sock, F_SETFL, opts & ~O_NONBLOCK);
+ else
+ ret = fcntl(_sock, F_SETFL, opts | O_NONBLOCK);
+#endif
+
+ if (ret != 0)
+ WARN_PRINT("Unable to change non-block mode");
+}
+
+void NetSocketPosix::set_ipv6_only_enabled(bool p_enabled) {
+ ERR_FAIL_COND(!is_open());
+ // This option is only avaiable in IPv6 sockets.
+ ERR_FAIL_COND(_ip_type == IP::TYPE_IPV4);
+
+ int par = p_enabled ? 1 : 0;
+ if (setsockopt(_sock, IPPROTO_IPV6, IPV6_V6ONLY, SOCK_CBUF(&par), sizeof(int)) != 0) {
+ WARN_PRINT("Unable to change IPv4 address mapping over IPv6 option");
+ }
+}
+
+void NetSocketPosix::set_tcp_no_delay_enabled(bool p_enabled) {
+ ERR_FAIL_COND(!is_open());
+ ERR_FAIL_COND(!_is_stream); // Not TCP
+
+ int par = p_enabled ? 1 : 0;
+ if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, SOCK_CBUF(&par), sizeof(int)) < 0) {
+ ERR_PRINT("Unable to set TCP no delay option");
+ }
+}
+
+void NetSocketPosix::set_reuse_address_enabled(bool p_enabled) {
+ ERR_FAIL_COND(!is_open());
+
+ int par = p_enabled ? 1 : 0;
+ if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, SOCK_CBUF(&par), sizeof(int)) < 0) {
+ WARN_PRINT("Unable to set socket REUSEADDR option!");
+ }
+}
+
+void NetSocketPosix::set_reuse_port_enabled(bool p_enabled) {
+// Windows does not have this option, as it is always ON when setting REUSEADDR.
+#ifndef WINDOWS_ENABLED
+ ERR_FAIL_COND(!is_open());
+
+ int par = p_enabled ? 1 : 0;
+ if (setsockopt(_sock, SOL_SOCKET, SO_REUSEPORT, SOCK_CBUF(&par), sizeof(int)) < 0) {
+ WARN_PRINT("Unable to set socket REUSEPORT option!");
+ }
+#endif
+}
+
+bool NetSocketPosix::is_open() const {
+ return _sock != SOCK_EMPTY;
+}
+
+int NetSocketPosix::get_available_bytes() const {
+
+ ERR_FAIL_COND_V(_sock == SOCK_EMPTY, -1);
+
+ unsigned long len;
+ int ret = SOCK_IOCTL(_sock, FIONREAD, &len);
+ ERR_FAIL_COND_V(ret == -1, 0);
+ return len;
+}
+
+Ref<NetSocket> NetSocketPosix::accept(IP_Address &r_ip, uint16_t &r_port) {
+
+ Ref<NetSocket> out;
+ ERR_FAIL_COND_V(!is_open(), out);
+
+ struct sockaddr_storage their_addr;
+ socklen_t size = sizeof(their_addr);
+ SOCKET_TYPE fd = ::accept(_sock, (struct sockaddr *)&their_addr, &size);
+ ERR_FAIL_COND_V(fd == SOCK_EMPTY, out);
+
+ _set_ip_port(&their_addr, r_ip, r_port);
+
+ NetSocketPosix *ns = memnew(NetSocketPosix);
+ ns->_set_socket(fd, _ip_type, _is_stream);
+ ns->set_blocking_enabled(false);
+ return Ref<NetSocket>(ns);
+}
diff --git a/drivers/windows/stream_peer_tcp_winsock.h b/drivers/unix/net_socket_posix.h
index a0177d374e..010f2ea6e0 100644
--- a/drivers/windows/stream_peer_tcp_winsock.h
+++ b/drivers/unix/net_socket_posix.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* stream_peer_tcp_winsock.h */
+/* net_socket_posix.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,65 +28,74 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef WINDOWS_ENABLED
+#ifndef NET_SOCKET_UNIX_H
+#define NET_SOCKET_UNIX_H
-#ifndef STREAM_PEER_TCP_WINSOCK_H
-#define STREAM_PEER_TCP_WINSOCK_H
+#include "core/io/net_socket.h"
-#include "error_list.h"
+#if defined(WINDOWS_ENABLED)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define SOCKET_TYPE SOCKET
-#include "core/io/ip_address.h"
-#include "core/io/stream_peer_tcp.h"
+#else
+#include <sys/socket.h>
+#define SOCKET_TYPE int
-class StreamPeerTCPWinsock : public StreamPeerTCP {
-
-protected:
- mutable Status status;
- IP::Type sock_type;
+#endif
- int sockfd;
+class NetSocketPosix : public NetSocket {
- Error _block(int p_sockfd, bool p_read, bool p_write) const;
+private:
+ SOCKET_TYPE _sock;
+ IP::Type _ip_type;
+ bool _is_stream;
- Error _poll_connection() const;
+ enum NetError {
+ ERR_NET_WOULD_BLOCK,
+ ERR_NET_IS_CONNECTED,
+ ERR_NET_IN_PROGRESS,
+ ERR_NET_OTHER
+ };
- IP_Address peer_host;
- int peer_port;
+ NetError _get_socket_error();
+ void _set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream);
- Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
- Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
+protected:
+ static NetSocket *_create_func();
- static StreamPeerTCP *_create();
+ bool _can_use_ip(const IP_Address p_ip, const bool p_for_bind) const;
public:
- virtual Error connect_to_host(const IP_Address &p_host, uint16_t p_port);
-
- virtual Error put_data(const uint8_t *p_data, int p_bytes);
- virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent);
-
- virtual Error get_data(uint8_t *p_buffer, int p_bytes);
- virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received);
-
- virtual int get_available_bytes() const;
-
- void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type);
-
- virtual IP_Address get_connected_host() const;
- virtual uint16_t get_connected_port() const;
-
- virtual bool is_connected_to_host() const;
- virtual Status get_status() const;
- virtual void disconnect_from_host();
-
static void make_default();
static void cleanup();
+ static void _set_ip_port(struct sockaddr_storage *p_addr, IP_Address &r_ip, uint16_t &r_port);
+ static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type);
+
+ virtual Error open(Type p_sock_type, IP::Type &ip_type);
+ virtual void close();
+ virtual Error bind(IP_Address p_addr, uint16_t p_port);
+ virtual Error listen(int p_max_pending);
+ virtual Error connect_to_host(IP_Address p_addr, uint16_t p_port);
+ virtual Error poll(PollType p_type, int timeout) const;
+ virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read);
+ virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port);
+ virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent);
+ virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port);
+ virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port);
+
+ virtual bool is_open() const;
+ virtual int get_available_bytes() const;
- virtual void set_no_delay(bool p_enabled);
+ virtual void set_broadcasting_enabled(bool p_enabled);
+ virtual void set_blocking_enabled(bool p_enabled);
+ virtual void set_ipv6_only_enabled(bool p_enabled);
+ virtual void set_tcp_no_delay_enabled(bool p_enabled);
+ virtual void set_reuse_address_enabled(bool p_enabled);
+ virtual void set_reuse_port_enabled(bool p_enabled);
- StreamPeerTCPWinsock();
- ~StreamPeerTCPWinsock();
+ NetSocketPosix();
+ ~NetSocketPosix();
};
-#endif // STREAM_PEER_TCP_WINSOCK_H
-
#endif
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 05dfd69f58..6c70934bc6 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -32,30 +32,27 @@
#ifdef UNIX_ENABLED
-#include "servers/visual_server.h"
-
#include "core/os/thread_dummy.h"
-#include "mutex_posix.h"
-#include "rw_lock_posix.h"
-#include "semaphore_posix.h"
-#include "thread_posix.h"
-
-//#include "core/io/file_access_buffered_fa.h"
-#include "dir_access_unix.h"
-#include "file_access_unix.h"
-#include "packet_peer_udp_posix.h"
-#include "stream_peer_tcp_posix.h"
-#include "tcp_server_posix.h"
+#include "core/project_settings.h"
+#include "drivers/unix/dir_access_unix.h"
+#include "drivers/unix/file_access_unix.h"
+#include "drivers/unix/mutex_posix.h"
+#include "drivers/unix/net_socket_posix.h"
+#include "drivers/unix/rw_lock_posix.h"
+#include "drivers/unix/semaphore_posix.h"
+#include "drivers/unix/thread_posix.h"
+#include "servers/visual_server.h"
#ifdef __APPLE__
#include <mach-o/dyld.h>
+#include <mach/mach_time.h>
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
-#include "project_settings.h"
+
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
@@ -68,6 +65,32 @@
#include <sys/wait.h>
#include <unistd.h>
+/// Clock Setup function (used by get_ticks_usec)
+static uint64_t _clock_start = 0;
+#if defined(__APPLE__)
+static double _clock_scale = 0;
+static void _setup_clock() {
+ mach_timebase_info_data_t info;
+ kern_return_t ret = mach_timebase_info(&info);
+ ERR_EXPLAIN("OS CLOCK IS NOT WORKING!");
+ ERR_FAIL_COND(ret != 0);
+ _clock_scale = ((double)info.numer / (double)info.denom) / 1000.0;
+ _clock_start = mach_absolute_time() * _clock_scale;
+}
+#else
+#if defined(CLOCK_MONOTONIC_RAW) && !defined(JAVASCRIPT_ENABLED) // This is a better clock on Linux.
+#define GODOT_CLOCK CLOCK_MONOTONIC_RAW
+#else
+#define GODOT_CLOCK CLOCK_MONOTONIC
+#endif
+static void _setup_clock() {
+ struct timespec tv_now = { 0, 0 };
+ ERR_EXPLAIN("OS CLOCK IS NOT WORKING!");
+ ERR_FAIL_COND(clock_gettime(GODOT_CLOCK, &tv_now) != 0);
+ _clock_start = ((uint64_t)tv_now.tv_nsec / 1000L) + (uint64_t)tv_now.tv_sec * 1000000L;
+}
+#endif
+
void OS_Unix::debug_break() {
assert(false);
@@ -126,14 +149,11 @@ void OS_Unix::initialize_core() {
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
#ifndef NO_NETWORK
- TCPServerPosix::make_default();
- StreamPeerTCPPosix::make_default();
- PacketPeerUDPPosix::make_default();
+ NetSocketPosix::make_default();
IP_Unix::make_default();
#endif
- ticks_start = 0;
- ticks_start = get_ticks_usec();
+ _setup_clock();
struct sigaction sa;
sa.sa_handler = &handle_sigchld;
@@ -145,6 +165,8 @@ void OS_Unix::initialize_core() {
}
void OS_Unix::finalize_core() {
+
+ NetSocketPosix::cleanup();
}
void OS_Unix::alert(const String &p_alert, const String &p_title) {
@@ -250,11 +272,16 @@ void OS_Unix::delay_usec(uint32_t p_usec) const {
}
uint64_t OS_Unix::get_ticks_usec() const {
- struct timeval tv_now;
- gettimeofday(&tv_now, NULL);
-
- uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec * 1000000L;
- longtime -= ticks_start;
+#if defined(__APPLE__)
+ uint64_t longtime = mach_absolute_time() * _clock_scale;
+#else
+ // Unchecked return. Static analyzers might complain.
+ // If _setup_clock() succeded, we assume clock_gettime() works.
+ struct timespec tv_now = { 0, 0 };
+ clock_gettime(GODOT_CLOCK, &tv_now);
+ uint64_t longtime = ((uint64_t)tv_now.tv_nsec / 1000L) + (uint64_t)tv_now.tv_sec * 1000000L;
+#endif
+ longtime -= _clock_start;
return longtime;
}
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 95b74d23ff..b702454603 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -37,13 +37,11 @@
#ifdef UNIX_ENABLED
+#include "core/os/os.h"
#include "drivers/unix/ip_unix.h"
-#include "os/os.h"
class OS_Unix : public OS {
- uint64_t ticks_start;
-
protected:
// UNIX only handles the core functions.
// inheriting platforms under unix (eg. X11) should handle the rest
diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp
deleted file mode 100644
index 1380c1d88b..0000000000
--- a/drivers/unix/packet_peer_udp_posix.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-/*************************************************************************/
-/* packet_peer_udp_posix.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "packet_peer_udp_posix.h"
-
-#ifdef UNIX_ENABLED
-
-#include <errno.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <netinet/in.h>
-#include <stdio.h>
-
-#ifndef NO_FCNTL
-#ifdef __HAIKU__
-#include <fcntl.h>
-#else
-#include <sys/fcntl.h>
-#endif
-#else
-#include <sys/ioctl.h>
-#endif
-
-#ifdef JAVASCRIPT_ENABLED
-#include <arpa/inet.h>
-#endif
-
-#include "drivers/unix/socket_helpers.h"
-
-int PacketPeerUDPPosix::get_available_packet_count() const {
-
- Error err = const_cast<PacketPeerUDPPosix *>(this)->_poll(false);
- if (err != OK)
- return 0;
-
- return queue_count;
-}
-
-Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
-
- Error err = const_cast<PacketPeerUDPPosix *>(this)->_poll(false);
- if (err != OK)
- return err;
- if (queue_count == 0)
- return ERR_UNAVAILABLE;
-
- uint32_t size = 0;
- uint8_t type = IP::TYPE_NONE;
- rb.read(&type, 1, true);
- if (type == IP::TYPE_IPV4) {
- uint8_t ip[4];
- rb.read(ip, 4, true);
- packet_ip.set_ipv4(ip);
- } else {
- uint8_t ipv6[16];
- rb.read(ipv6, 16, true);
- packet_ip.set_ipv6(ipv6);
- };
- rb.read((uint8_t *)&packet_port, 4, true);
- rb.read((uint8_t *)&size, 4, true);
- rb.read(packet_buffer, size, true);
- --queue_count;
- *r_buffer = packet_buffer;
- r_buffer_size = size;
- return OK;
-}
-Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
-
- ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED);
-
- if (sock_type == IP::TYPE_NONE)
- sock_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
-
- int sock = _get_socket();
- ERR_FAIL_COND_V(sock == -1, FAILED);
- struct sockaddr_storage addr;
- size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
-
- errno = 0;
- int err;
-
- _set_sock_blocking(blocking);
-
- while ((err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr *)&addr, addr_size)) != p_buffer_size) {
-
- if (errno != EAGAIN) {
- return FAILED;
- } else if (!blocking) {
- return ERR_UNAVAILABLE;
- }
- }
-
- return OK;
-}
-
-int PacketPeerUDPPosix::get_max_packet_size() const {
-
- return 512; // uhm maybe not
-}
-
-Error PacketPeerUDPPosix::listen(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) {
-
- ERR_FAIL_COND_V(sockfd != -1, ERR_ALREADY_IN_USE);
- ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
-
-#ifdef __OpenBSD__
- sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only.
-#else
- sock_type = IP::TYPE_ANY;
-#endif
-
- if (p_bind_address.is_valid())
- sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
-
- int sock = _get_socket();
-
- if (sock == -1)
- return ERR_CANT_CREATE;
-
- sockaddr_storage addr = { 0 };
- size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address());
-
- if (bind(sock, (struct sockaddr *)&addr, addr_size) == -1) {
- close();
- return ERR_UNAVAILABLE;
- }
- rb.resize(nearest_shift(p_recv_buffer_size));
- return OK;
-}
-
-void PacketPeerUDPPosix::close() {
-
- if (sockfd != -1)
- ::close(sockfd);
- sockfd = -1;
- sock_type = IP::TYPE_NONE;
- rb.resize(16);
- queue_count = 0;
-}
-
-Error PacketPeerUDPPosix::wait() {
-
- return _poll(true);
-}
-
-Error PacketPeerUDPPosix::_poll(bool p_block) {
-
- if (sockfd == -1) {
- return FAILED;
- }
-
- _set_sock_blocking(p_block);
-
- struct sockaddr_storage from = { 0 };
- socklen_t len = sizeof(struct sockaddr_storage);
- int ret;
- while ((ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer), MAX(rb.space_left() - 24, 0)), 0, (struct sockaddr *)&from, &len)) > 0) {
-
- uint32_t port = 0;
-
- if (from.ss_family == AF_INET) {
- uint8_t type = (uint8_t)IP::TYPE_IPV4;
- rb.write(&type, 1);
- struct sockaddr_in *sin_from = (struct sockaddr_in *)&from;
- rb.write((uint8_t *)&sin_from->sin_addr, 4);
- port = ntohs(sin_from->sin_port);
-
- } else if (from.ss_family == AF_INET6) {
-
- uint8_t type = (uint8_t)IP::TYPE_IPV6;
- rb.write(&type, 1);
-
- struct sockaddr_in6 *s6_from = (struct sockaddr_in6 *)&from;
- rb.write((uint8_t *)&s6_from->sin6_addr, 16);
-
- port = ntohs(s6_from->sin6_port);
-
- } else {
- // WARN_PRINT("Ignoring packet with unknown address family");
- uint8_t type = (uint8_t)IP::TYPE_NONE;
- rb.write(&type, 1);
- };
-
- rb.write((uint8_t *)&port, 4);
- rb.write((uint8_t *)&ret, 4);
- rb.write(recv_buffer, ret);
-
- len = sizeof(struct sockaddr_storage);
- ++queue_count;
- if (p_block)
- break;
- };
-
- // TODO: Should ECONNRESET be handled here?
- if (ret == 0 || (ret == -1 && errno != EAGAIN)) {
- close();
- return FAILED;
- };
-
- return OK;
-}
-bool PacketPeerUDPPosix::is_listening() const {
-
- return sockfd != -1;
-}
-
-IP_Address PacketPeerUDPPosix::get_packet_address() const {
-
- return packet_ip;
-}
-
-int PacketPeerUDPPosix::get_packet_port() const {
-
- return packet_port;
-}
-
-int PacketPeerUDPPosix::_get_socket() {
-
- ERR_FAIL_COND_V(sock_type == IP::TYPE_NONE, -1);
-
- if (sockfd != -1)
- return sockfd;
-
- sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
-
- if (sockfd != -1)
- _set_sock_blocking(false);
-
- return sockfd;
-}
-
-void PacketPeerUDPPosix::_set_sock_blocking(bool p_blocking) {
-
- if (sock_blocking == p_blocking)
- return;
-
- sock_blocking = p_blocking;
-
-#ifndef NO_FCNTL
- int opts = fcntl(sockfd, F_GETFL);
- int ret = 0;
- if (sock_blocking)
- ret = fcntl(sockfd, F_SETFL, opts & ~O_NONBLOCK);
- else
- ret = fcntl(sockfd, F_SETFL, opts | O_NONBLOCK);
- if (ret == -1)
- perror("setting non-block mode");
-#else
- int bval = sock_blocking ? 0 : 1;
- if (ioctl(sockfd, FIONBIO, &bval) == -1)
- perror("setting non-block mode");
-#endif
-}
-
-void PacketPeerUDPPosix::set_dest_address(const IP_Address &p_address, int p_port) {
-
- peer_addr = p_address;
- peer_port = p_port;
-}
-
-PacketPeerUDP *PacketPeerUDPPosix::_create() {
-
- return memnew(PacketPeerUDPPosix);
-};
-
-void PacketPeerUDPPosix::make_default() {
-
- PacketPeerUDP::_create = PacketPeerUDPPosix::_create;
-};
-
-PacketPeerUDPPosix::PacketPeerUDPPosix() {
-
- blocking = true;
- sock_blocking = true;
- sockfd = -1;
- packet_port = 0;
- queue_count = 0;
- peer_port = 0;
- sock_type = IP::TYPE_NONE;
- rb.resize(16);
-}
-
-PacketPeerUDPPosix::~PacketPeerUDPPosix() {
-
- close();
-}
-#endif
diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h
deleted file mode 100644
index 7f72a9bfc9..0000000000
--- a/drivers/unix/packet_peer_udp_posix.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*************************************************************************/
-/* packet_peer_udp_posix.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef PACKET_PEER_UDP_POSIX_H
-#define PACKET_PEER_UDP_POSIX_H
-
-#ifdef UNIX_ENABLED
-
-#include "io/packet_peer_udp.h"
-#include "ring_buffer.h"
-
-class PacketPeerUDPPosix : public PacketPeerUDP {
-
- enum {
- PACKET_BUFFER_SIZE = 65536
- };
-
- RingBuffer<uint8_t> rb;
- uint8_t recv_buffer[PACKET_BUFFER_SIZE];
- uint8_t packet_buffer[PACKET_BUFFER_SIZE];
- IP_Address packet_ip;
- int packet_port;
- int queue_count;
- int sockfd;
- bool sock_blocking;
- IP::Type sock_type;
-
- IP_Address peer_addr;
- int peer_port;
-
- _FORCE_INLINE_ int _get_socket();
-
- static PacketPeerUDP *_create();
- void _set_sock_blocking(bool p_blocking);
- virtual Error _poll(bool p_block);
-
-public:
- virtual int get_available_packet_count() const;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
- virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
-
- virtual int get_max_packet_size() const;
-
- virtual Error listen(int p_port, const IP_Address &p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536);
- virtual void close();
- virtual Error wait();
- virtual bool is_listening() const;
-
- virtual IP_Address get_packet_address() const;
- virtual int get_packet_port() const;
-
- virtual void set_dest_address(const IP_Address &p_address, int p_port);
-
- static void make_default();
-
- PacketPeerUDPPosix();
- ~PacketPeerUDPPosix();
-};
-
-#endif // PACKET_PEER_UDP_POSIX_H
-#endif
diff --git a/drivers/unix/rw_lock_posix.cpp b/drivers/unix/rw_lock_posix.cpp
index 4df965cabb..27b19c30d5 100644
--- a/drivers/unix/rw_lock_posix.cpp
+++ b/drivers/unix/rw_lock_posix.cpp
@@ -32,8 +32,8 @@
#include "rw_lock_posix.h"
-#include "error_macros.h"
-#include "os/memory.h"
+#include "core/error_macros.h"
+#include "core/os/memory.h"
#include <stdio.h>
void RWLockPosix::read_lock() {
diff --git a/drivers/unix/rw_lock_posix.h b/drivers/unix/rw_lock_posix.h
index 617b9705da..897b617f98 100644
--- a/drivers/unix/rw_lock_posix.h
+++ b/drivers/unix/rw_lock_posix.h
@@ -33,7 +33,7 @@
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
-#include "os/rw_lock.h"
+#include "core/os/rw_lock.h"
#include <pthread.h>
class RWLockPosix : public RWLock {
diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp
index 5cabfe4937..26c2aeab28 100644
--- a/drivers/unix/semaphore_posix.cpp
+++ b/drivers/unix/semaphore_posix.cpp
@@ -32,7 +32,7 @@
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
-#include "os/memory.h"
+#include "core/os/memory.h"
#include <errno.h>
#include <stdio.h>
diff --git a/drivers/unix/semaphore_posix.h b/drivers/unix/semaphore_posix.h
index 283174bb2e..025b87c0d7 100644
--- a/drivers/unix/semaphore_posix.h
+++ b/drivers/unix/semaphore_posix.h
@@ -31,7 +31,7 @@
#ifndef SEMAPHORE_POSIX_H
#define SEMAPHORE_POSIX_H
-#include "os/semaphore.h"
+#include "core/os/semaphore.h"
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h
deleted file mode 100644
index 5b42c13eae..0000000000
--- a/drivers/unix/socket_helpers.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*************************************************************************/
-/* socket_helpers.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef SOCKET_HELPERS_H
-#define SOCKET_HELPERS_H
-
-#include <string.h>
-
-#if defined(__MINGW32__) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4)
-// Workaround for mingw-w64 < 4.0
-#ifndef IPV6_V6ONLY
-#define IPV6_V6ONLY 27
-#endif
-#endif
-
-// helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this
-
-static size_t _set_sockaddr(struct sockaddr_storage *p_addr, const IP_Address &p_ip, int p_port, IP::Type p_sock_type = IP::TYPE_ANY) {
-
- memset(p_addr, 0, sizeof(struct sockaddr_storage));
-
- ERR_FAIL_COND_V(!p_ip.is_valid(), 0);
-
- // IPv6 socket
- if (p_sock_type == IP::TYPE_IPV6 || p_sock_type == IP::TYPE_ANY) {
-
- // IPv6 only socket with IPv4 address
- ERR_FAIL_COND_V(p_sock_type == IP::TYPE_IPV6 && p_ip.is_ipv4(), 0);
-
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = htons(p_port);
- copymem(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16);
- return sizeof(sockaddr_in6);
-
- } else { // IPv4 socket
-
- // IPv4 socket with IPv6 address
- ERR_FAIL_COND_V(!p_ip.is_ipv4(), 0);
-
- struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
- addr4->sin_family = AF_INET;
- addr4->sin_port = htons(p_port); // short, network byte order
- copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 16);
- return sizeof(sockaddr_in);
- };
-};
-
-static size_t _set_listen_sockaddr(struct sockaddr_storage *p_addr, int p_port, IP::Type p_sock_type, const IP_Address p_bind_address) {
-
- memset(p_addr, 0, sizeof(struct sockaddr_storage));
- if (p_sock_type == IP::TYPE_IPV4) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
- addr4->sin_family = AF_INET;
- addr4->sin_port = htons(p_port);
- if (p_bind_address.is_valid()) {
- copymem(&addr4->sin_addr.s_addr, p_bind_address.get_ipv4(), 4);
- } else {
- addr4->sin_addr.s_addr = INADDR_ANY;
- }
- return sizeof(sockaddr_in);
- } else {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
-
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = htons(p_port);
- if (p_bind_address.is_valid()) {
- copymem(&addr6->sin6_addr.s6_addr, p_bind_address.get_ipv6(), 16);
- } else {
- addr6->sin6_addr = in6addr_any;
- }
- return sizeof(sockaddr_in6);
- };
-};
-
-static int _socket_create(IP::Type &p_type, int type, int protocol) {
-
- ERR_FAIL_COND_V(p_type > IP::TYPE_ANY || p_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER);
-
- int family = p_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6;
- int sockfd = socket(family, type, protocol);
-
- if (sockfd == -1 && p_type == IP::TYPE_ANY) {
- // Careful here, changing the referenced parameter so the caller knows that we are using an IPv4 socket
- // in place of a dual stack one, and further calls to _set_sock_addr will work as expected.
- p_type = IP::TYPE_IPV4;
- family = AF_INET;
- sockfd = socket(family, type, protocol);
- }
-
- ERR_FAIL_COND_V(sockfd == -1, -1);
-
- if (family == AF_INET6) {
- // Select IPv4 over IPv6 mapping
- int opt = p_type != IP::TYPE_ANY;
- if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&opt, sizeof(opt)) != 0) {
- WARN_PRINT("Unable to set/unset IPv4 address mapping over IPv6");
- }
- }
- if (protocol == IPPROTO_UDP && p_type != IP::TYPE_IPV6) {
- // Enable broadcasting for UDP sockets if it's not IPv6 only (IPv6 has no broadcast option).
- int broadcast = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)) != 0) {
- WARN_PRINT("Error when enabling broadcasting");
- }
- }
-
- return sockfd;
-}
-
-static void _set_ip_addr_port(IP_Address &r_ip, int &r_port, struct sockaddr_storage *p_addr) {
-
- if (p_addr->ss_family == AF_INET) {
-
- struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
- r_ip.set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr));
-
- r_port = ntohs(addr4->sin_port);
-
- } else if (p_addr->ss_family == AF_INET6) {
-
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
- r_ip.set_ipv6(addr6->sin6_addr.s6_addr);
-
- r_port = ntohs(addr6->sin6_port);
- };
-};
-
-#endif
diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp
deleted file mode 100644
index 44b9ef1d7c..0000000000
--- a/drivers/unix/stream_peer_tcp_posix.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*************************************************************************/
-/* stream_peer_tcp_posix.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef UNIX_ENABLED
-
-#include "stream_peer_tcp_posix.h"
-
-#include <errno.h>
-#include <netdb.h>
-#include <poll.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#ifndef NO_FCNTL
-#ifdef __HAIKU__
-#include <fcntl.h>
-#else
-#include <sys/fcntl.h>
-#endif
-#else
-#include <sys/ioctl.h>
-#endif
-#include <netinet/in.h>
-
-#include <sys/socket.h>
-#ifdef JAVASCRIPT_ENABLED
-#include <arpa/inet.h>
-#endif
-
-#include <netinet/tcp.h>
-
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
-#define MSG_NOSIGNAL SO_NOSIGPIPE
-#endif
-
-#include "drivers/unix/socket_helpers.h"
-
-StreamPeerTCP *StreamPeerTCPPosix::_create() {
-
- return memnew(StreamPeerTCPPosix);
-};
-
-void StreamPeerTCPPosix::make_default() {
-
- StreamPeerTCP::_create = StreamPeerTCPPosix::_create;
-};
-
-Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const {
-
- struct pollfd pfd;
- pfd.fd = p_sockfd;
- pfd.events = 0;
- if (p_read)
- pfd.events |= POLLIN;
- if (p_write)
- pfd.events |= POLLOUT;
- pfd.revents = 0;
-
- int ret = poll(&pfd, 1, -1);
- return ret < 0 ? FAILED : OK;
-};
-
-Error StreamPeerTCPPosix::_poll_connection() const {
-
- ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED);
-
- struct sockaddr_storage their_addr;
- size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type);
-
- if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == -1) {
-
- if (errno == EISCONN) {
- status = STATUS_CONNECTED;
- return OK;
- };
-
- if (errno == EINPROGRESS || errno == EALREADY) {
- return OK;
- }
-
- status = STATUS_ERROR;
- return ERR_CONNECTION_ERROR;
- } else {
-
- status = STATUS_CONNECTED;
- return OK;
- };
-
- return OK;
-};
-
-void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) {
-
- sock_type = p_sock_type;
- sockfd = p_sockfd;
-#ifndef NO_FCNTL
- if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#else
- int bval = 1;
- if (ioctl(sockfd, FIONBIO, &bval) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#endif
- status = STATUS_CONNECTING;
-
- peer_host = p_host;
- peer_port = p_port;
-};
-
-Error StreamPeerTCPPosix::connect_to_host(const IP_Address &p_host, uint16_t p_port) {
-
- ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);
-
- sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
- sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
- if (sockfd == -1) {
- ERR_PRINT("Socket creation failed!");
- disconnect_from_host();
- //perror("socket");
- return FAILED;
- };
-
-#ifndef NO_FCNTL
- if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#else
- int bval = 1;
- if (ioctl(sockfd, FIONBIO, &bval) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#endif
-
- struct sockaddr_storage their_addr;
- size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type);
-
- errno = 0;
- if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == -1 && errno != EINPROGRESS) {
-
- ERR_PRINT("Connection to remote host failed!");
- disconnect_from_host();
- return FAILED;
- };
-
- if (errno == EINPROGRESS) {
- status = STATUS_CONNECTING;
- } else {
- status = STATUS_CONNECTED;
- };
-
- peer_host = p_host;
- peer_port = p_port;
-
- return OK;
-};
-
-Error StreamPeerTCPPosix::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
-
- if (status == STATUS_NONE || status == STATUS_ERROR) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
-
- if (_poll_connection() != OK) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
- r_sent = 0;
- return OK;
- };
- };
-
- int data_to_send = p_bytes;
- const uint8_t *offset = p_data;
- if (sockfd == -1) return FAILED;
- errno = 0;
- int total_sent = 0;
-
- while (data_to_send) {
-
- int sent_amount = send(sockfd, offset, data_to_send, MSG_NOSIGNAL);
- //printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno);
-
- if (sent_amount == -1) {
-
- if (errno != EAGAIN) {
-
- perror("Nothing sent");
- disconnect_from_host();
- ERR_PRINT("Server disconnected!\n");
- return FAILED;
- };
-
- if (!p_block) {
- r_sent = total_sent;
- return OK;
- };
-
- _block(sockfd, false, true);
- } else {
-
- data_to_send -= sent_amount;
- offset += sent_amount;
- total_sent += sent_amount;
- };
- }
-
- r_sent = total_sent;
-
- return OK;
-};
-
-Error StreamPeerTCPPosix::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
-
- if (!is_connected_to_host()) {
-
- return FAILED;
- };
-
- if (status == STATUS_CONNECTING) {
-
- if (_poll_connection() != OK) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
- r_received = 0;
- return OK;
- };
- };
-
- int to_read = p_bytes;
- int total_read = 0;
- errno = 0;
-
- while (to_read) {
-
- int read = recv(sockfd, p_buffer + total_read, to_read, 0);
-
- if (read == -1) {
-
- if (errno != EAGAIN) {
-
- perror("Nothing read");
- disconnect_from_host();
- ERR_PRINT("Server disconnected!\n");
- return FAILED;
- };
-
- if (!p_block) {
-
- r_received = total_read;
- return OK;
- };
- _block(sockfd, true, false);
-
- } else if (read == 0) {
-
- sockfd = -1;
- status = STATUS_NONE;
- peer_port = 0;
- peer_host = IP_Address();
- r_received = total_read;
- return ERR_FILE_EOF;
-
- } else {
-
- to_read -= read;
- total_read += read;
- };
- };
-
- r_received = total_read;
-
- return OK;
-};
-
-void StreamPeerTCPPosix::set_no_delay(bool p_enabled) {
-
- ERR_FAIL_COND(!is_connected_to_host());
- int flag = p_enabled ? 1 : 0;
- if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) < 0) {
- ERR_PRINT("Unable to set TCP no delay option");
- }
-}
-
-bool StreamPeerTCPPosix::is_connected_to_host() const {
-
- if (status == STATUS_NONE || status == STATUS_ERROR) {
-
- return false;
- };
- if (status != STATUS_CONNECTED) {
- return true;
- };
-
- return (sockfd != -1);
-};
-
-StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const {
-
- if (status == STATUS_CONNECTING) {
- _poll_connection();
- };
-
- return status;
-};
-
-void StreamPeerTCPPosix::disconnect_from_host() {
-
- if (sockfd != -1)
- close(sockfd);
-
- sock_type = IP::TYPE_NONE;
- sockfd = -1;
-
- status = STATUS_NONE;
- peer_port = 0;
- peer_host = IP_Address();
-};
-
-Error StreamPeerTCPPosix::put_data(const uint8_t *p_data, int p_bytes) {
-
- int total;
- return write(p_data, p_bytes, total, true);
-};
-
-Error StreamPeerTCPPosix::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
-
- return write(p_data, p_bytes, r_sent, false);
-};
-
-Error StreamPeerTCPPosix::get_data(uint8_t *p_buffer, int p_bytes) {
-
- int total;
- return read(p_buffer, p_bytes, total, true);
-};
-
-Error StreamPeerTCPPosix::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
-
- return read(p_buffer, p_bytes, r_received, false);
-};
-
-int StreamPeerTCPPosix::get_available_bytes() const {
-
- unsigned long len;
- int ret = ioctl(sockfd, FIONREAD, &len);
- ERR_FAIL_COND_V(ret == -1, 0)
- return len;
-}
-IP_Address StreamPeerTCPPosix::get_connected_host() const {
-
- return peer_host;
-};
-
-uint16_t StreamPeerTCPPosix::get_connected_port() const {
-
- return peer_port;
-};
-
-StreamPeerTCPPosix::StreamPeerTCPPosix() {
-
- sock_type = IP::TYPE_NONE;
- sockfd = -1;
- status = STATUS_NONE;
- peer_port = 0;
-};
-
-StreamPeerTCPPosix::~StreamPeerTCPPosix() {
-
- disconnect_from_host();
-};
-
-#endif
diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h
deleted file mode 100644
index bcebe57771..0000000000
--- a/drivers/unix/stream_peer_tcp_posix.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************************************/
-/* stream_peer_tcp_posix.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef UNIX_ENABLED
-
-#ifndef STREAM_PEER_TCP_POSIX_H
-#define STREAM_PEER_TCP_POSIX_H
-
-#include "core/io/ip_address.h"
-#include "core/io/stream_peer_tcp.h"
-#include "error_list.h"
-
-class StreamPeerTCPPosix : public StreamPeerTCP {
-
-protected:
- mutable Status status;
-
- IP::Type sock_type;
- int sockfd;
-
- Error _block(int p_sockfd, bool p_read, bool p_write) const;
-
- Error _poll_connection() const;
-
- IP_Address peer_host;
- int peer_port;
-
- Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
- Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
-
- static StreamPeerTCP *_create();
-
-public:
- virtual Error connect_to_host(const IP_Address &p_host, uint16_t p_port);
-
- virtual Error put_data(const uint8_t *p_data, int p_bytes);
- virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent);
-
- virtual Error get_data(uint8_t *p_buffer, int p_bytes);
- virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received);
-
- virtual int get_available_bytes() const;
-
- void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type);
-
- virtual IP_Address get_connected_host() const;
- virtual uint16_t get_connected_port() const;
-
- virtual bool is_connected_to_host() const;
- virtual Status get_status() const;
- virtual void disconnect_from_host();
-
- virtual void set_no_delay(bool p_enabled);
-
- static void make_default();
-
- StreamPeerTCPPosix();
- ~StreamPeerTCPPosix();
-};
-
-#endif // TCP_CLIENT_POSIX_H
-
-#endif
diff --git a/drivers/unix/syslog_logger.cpp b/drivers/unix/syslog_logger.cpp
index 727672458c..c7b4daf4ad 100644
--- a/drivers/unix/syslog_logger.cpp
+++ b/drivers/unix/syslog_logger.cpp
@@ -31,7 +31,7 @@
#ifdef UNIX_ENABLED
#include "syslog_logger.h"
-#include "print_string.h"
+#include "core/print_string.h"
#include <syslog.h>
void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h
index 40bf26cee1..745264ab6f 100644
--- a/drivers/unix/syslog_logger.h
+++ b/drivers/unix/syslog_logger.h
@@ -33,7 +33,7 @@
#ifdef UNIX_ENABLED
-#include "io/logger.h"
+#include "core/io/logger.h"
class SyslogLogger : public Logger {
public:
@@ -45,4 +45,4 @@ public:
#endif
-#endif \ No newline at end of file
+#endif
diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp
deleted file mode 100644
index 67ab981f46..0000000000
--- a/drivers/unix/tcp_server_posix.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*************************************************************************/
-/* tcp_server_posix.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "tcp_server_posix.h"
-#include "stream_peer_tcp_posix.h"
-
-#ifdef UNIX_ENABLED
-
-#include <poll.h>
-
-#include <errno.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#ifndef NO_FCNTL
-#ifdef __HAIKU__
-#include <fcntl.h>
-#else
-#include <sys/fcntl.h>
-#endif
-#else
-#include <sys/ioctl.h>
-#endif
-#ifdef JAVASCRIPT_ENABLED
-#include <arpa/inet.h>
-#endif
-#include <assert.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include "drivers/unix/socket_helpers.h"
-
-TCP_Server *TCPServerPosix::_create() {
-
- return memnew(TCPServerPosix);
-};
-
-void TCPServerPosix::make_default() {
-
- TCP_Server::_create = TCPServerPosix::_create;
-};
-
-Error TCPServerPosix::listen(uint16_t p_port, const IP_Address &p_bind_address) {
-
- ERR_FAIL_COND_V(listen_sockfd != -1, ERR_ALREADY_IN_USE);
- ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
-
- int sockfd;
-#ifdef __OpenBSD__
- sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only.
-#else
- sock_type = IP::TYPE_ANY;
-#endif
-
- // If the bind address is valid use its type as the socket type
- if (p_bind_address.is_valid())
- sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
-
- sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
-
- ERR_FAIL_COND_V(sockfd == -1, FAILED);
-
-#ifndef NO_FCNTL
- if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#else
- int bval = 1;
- if (ioctl(sockfd, FIONBIO, &bval) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#endif
-
- int reuse = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
- WARN_PRINT("REUSEADDR failed!")
- }
-
- struct sockaddr_storage addr;
- size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, p_bind_address);
-
- if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) {
-
- if (::listen(sockfd, 1) == -1) {
-
- close(sockfd);
- ERR_FAIL_V(FAILED);
- };
- } else {
- close(sockfd);
- return ERR_ALREADY_IN_USE;
- };
-
- if (listen_sockfd != -1) {
- stop();
- };
-
- listen_sockfd = sockfd;
-
- return OK;
-};
-
-bool TCPServerPosix::is_connection_available() const {
-
- if (listen_sockfd == -1) {
- return false;
- };
-
- struct pollfd pfd;
- pfd.fd = listen_sockfd;
- pfd.events = POLLIN;
- pfd.revents = 0;
-
- int ret = poll(&pfd, 1, 0);
- ERR_FAIL_COND_V(ret < 0, FAILED);
-
- if (ret && (pfd.revents & POLLIN)) {
- return true;
- };
-
- return false;
-};
-
-Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
-
- if (!is_connection_available()) {
- return Ref<StreamPeerTCP>();
- };
-
- struct sockaddr_storage their_addr;
- socklen_t size = sizeof(their_addr);
- int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &size);
- ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>());
-#ifndef NO_FCNTL
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#else
- int bval = 1;
- if (ioctl(fd, FIONBIO, &bval) < 0) {
- WARN_PRINT("Error setting socket as non blocking");
- }
-#endif
-
- Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix);
- IP_Address ip;
-
- int port = 0;
- _set_ip_addr_port(ip, port, &their_addr);
-
- conn->set_socket(fd, ip, port, sock_type);
-
- return conn;
-};
-
-void TCPServerPosix::stop() {
-
- if (listen_sockfd != -1) {
- int ret = close(listen_sockfd);
- ERR_FAIL_COND(ret != 0);
- };
-
- listen_sockfd = -1;
- sock_type = IP::TYPE_NONE;
-};
-
-TCPServerPosix::TCPServerPosix() {
-
- listen_sockfd = -1;
- sock_type = IP::TYPE_NONE;
-};
-
-TCPServerPosix::~TCPServerPosix() {
-
- stop();
-};
-#endif
diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h
deleted file mode 100644
index c749314fb3..0000000000
--- a/drivers/unix/tcp_server_posix.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*************************************************************************/
-/* tcp_server_posix.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef TCP_SERVER_POSIX_H
-#define TCP_SERVER_POSIX_H
-
-#ifdef UNIX_ENABLED
-#include "core/io/tcp_server.h"
-
-class TCPServerPosix : public TCP_Server {
-
- int listen_sockfd;
- IP::Type sock_type;
-
- static TCP_Server *_create();
-
-public:
- virtual Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*"));
- virtual bool is_connection_available() const;
- virtual Ref<StreamPeerTCP> take_connection();
-
- virtual void stop();
-
- static void make_default();
-
- TCPServerPosix();
- ~TCPServerPosix();
-};
-
-#endif // TCP_SERVER_POSIX_H
-#endif
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index a73b40a6f2..fcefe0a3b3 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "thread_posix.h"
-#include "script_language.h"
+#include "core/script_language.h"
#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
@@ -37,8 +37,8 @@
#include <pthread_np.h>
#endif
+#include "core/os/memory.h"
#include "core/safe_refcount.h"
-#include "os/memory.h"
static pthread_key_t _create_thread_id_key() {
pthread_key_t key;
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index ea2de61bd5..20d103232e 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -37,7 +37,7 @@
#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
-#include "os/thread.h"
+#include "core/os/thread.h"
#include <pthread.h>
#include <sys/types.h>
diff --git a/drivers/wasapi/SCsub b/drivers/wasapi/SCsub
index 233593b0f9..4c24925192 100644
--- a/drivers/wasapi/SCsub
+++ b/drivers/wasapi/SCsub
@@ -4,5 +4,3 @@ Import('env')
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 11abe3256e..3d4979175b 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -32,8 +32,8 @@
#include "audio_driver_wasapi.h"
-#include "os/os.h"
-#include "project_settings.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
#include <functiondiscoverykeys.h>
@@ -65,7 +65,6 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
#define CAPTURE_BUFFER_CHANNELS 2
-static StringName capture_device_id;
static bool default_render_device_changed = false;
static bool default_capture_device_changed = false;
@@ -128,7 +127,6 @@ public:
default_render_device_changed = true;
} else if (flow == eCapture) {
default_capture_device_changed = true;
- capture_device_id = String(pwstrDeviceId);
}
}
@@ -659,6 +657,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
if (err == OK) {
ad->start();
}
+
+ avail_frames = 0;
+ write_ofs = 0;
}
if (ad->audio_input.active) {
diff --git a/drivers/windows/SCsub b/drivers/windows/SCsub
index ee39fd2631..28b315ae66 100644
--- a/drivers/windows/SCsub
+++ b/drivers/windows/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index cf4d82fb07..589e9e0870 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -32,9 +32,9 @@
#include "dir_access_windows.h"
-#include "os/memory.h"
+#include "core/os/memory.h"
+#include "core/print_string.h"
-#include "print_string.h"
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index b18c8f5b5d..9f5d0b6d93 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -33,7 +33,7 @@
#ifdef WINDOWS_ENABLED
-#include "os/dir_access.h"
+#include "core/os/dir_access.h"
/**
@author Juan Linietsky <reduz@gmail.com>
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 0462c1e942..6f985e68b4 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -33,13 +33,15 @@
#ifdef WINDOWS_ENABLED
-#include "os/file_access.h"
-#include "os/memory.h"
+#include "core/os/file_access.h"
+#include "core/os/memory.h"
+
#include <stdio.h>
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
class FileAccessWindows : public FileAccess {
FILE *f;
diff --git a/drivers/windows/mutex_windows.cpp b/drivers/windows/mutex_windows.cpp
index 359a79209c..9fc6485be3 100644
--- a/drivers/windows/mutex_windows.cpp
+++ b/drivers/windows/mutex_windows.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "mutex_windows.h"
-#include "os/memory.h"
+
+#include "core/os/memory.h"
#ifdef WINDOWS_ENABLED
diff --git a/drivers/windows/mutex_windows.h b/drivers/windows/mutex_windows.h
index 4dff2c2456..5c3a8eb331 100644
--- a/drivers/windows/mutex_windows.h
+++ b/drivers/windows/mutex_windows.h
@@ -33,11 +33,14 @@
#ifdef WINDOWS_ENABLED
-#include "os/mutex.h"
+#include "core/os/mutex.h"
+
#include <windows.h>
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
class MutexWindows : public Mutex {
#ifdef WINDOWS_USE_MUTEX
diff --git a/drivers/windows/packet_peer_udp_winsock.cpp b/drivers/windows/packet_peer_udp_winsock.cpp
deleted file mode 100644
index 609096d02e..0000000000
--- a/drivers/windows/packet_peer_udp_winsock.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/*************************************************************************/
-/* packet_peer_udp_winsock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef WINDOWS_ENABLED
-
-#include "packet_peer_udp_winsock.h"
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include "drivers/unix/socket_helpers.h"
-
-int PacketPeerUDPWinsock::get_available_packet_count() const {
-
- Error err = const_cast<PacketPeerUDPWinsock *>(this)->_poll(false);
- if (err != OK)
- return 0;
-
- return queue_count;
-}
-
-Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
-
- Error err = const_cast<PacketPeerUDPWinsock *>(this)->_poll(false);
- if (err != OK)
- return err;
- if (queue_count == 0)
- return ERR_UNAVAILABLE;
-
- uint32_t size;
- uint8_t type;
- rb.read(&type, 1, true);
- if (type == IP::TYPE_IPV4) {
- uint8_t ip[4];
- rb.read(ip, 4, true);
- packet_ip.set_ipv4(ip);
- } else {
- uint8_t ip[16];
- rb.read(ip, 16, true);
- packet_ip.set_ipv6(ip);
- };
- rb.read((uint8_t *)&packet_port, 4, true);
- rb.read((uint8_t *)&size, 4, true);
- rb.read(packet_buffer, size, true);
- --queue_count;
- *r_buffer = packet_buffer;
- r_buffer_size = size;
- return OK;
-}
-Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
-
- ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED);
-
- if (sock_type == IP::TYPE_NONE)
- sock_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
-
- int sock = _get_socket();
- ERR_FAIL_COND_V(sock == -1, FAILED);
- struct sockaddr_storage addr;
- size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
-
- _set_sock_blocking(blocking);
-
- errno = 0;
- int err;
- while ((err = sendto(sock, (const char *)p_buffer, p_buffer_size, 0, (struct sockaddr *)&addr, addr_size)) != p_buffer_size) {
-
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- return FAILED;
- } else if (!blocking) {
- return ERR_UNAVAILABLE;
- }
- }
-
- return OK;
-}
-
-int PacketPeerUDPWinsock::get_max_packet_size() const {
-
- return 512; // uhm maybe not
-}
-
-void PacketPeerUDPWinsock::_set_sock_blocking(bool p_blocking) {
-
- if (sock_blocking == p_blocking)
- return;
-
- sock_blocking = p_blocking;
- unsigned long par = sock_blocking ? 0 : 1;
- if (ioctlsocket(sockfd, FIONBIO, &par)) {
- perror("setting non-block mode");
- //close();
- //return -1;
- };
-}
-
-Error PacketPeerUDPWinsock::listen(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) {
-
- ERR_FAIL_COND_V(sockfd != -1, ERR_ALREADY_IN_USE);
- ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
-
- sock_type = IP::TYPE_ANY;
-
- if (p_bind_address.is_valid())
- sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
-
- int sock = _get_socket();
- if (sock == -1)
- return ERR_CANT_CREATE;
-
- struct sockaddr_storage addr = { 0 };
- size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address());
-
- if (bind(sock, (struct sockaddr *)&addr, addr_size) == -1) {
- close();
- return ERR_UNAVAILABLE;
- }
-
- printf("UDP Connection listening on port %i\n", p_port);
- rb.resize(nearest_shift(p_recv_buffer_size));
- return OK;
-}
-
-void PacketPeerUDPWinsock::close() {
-
- if (sockfd != -1)
- ::closesocket(sockfd);
- sockfd = -1;
- sock_type = IP::TYPE_NONE;
- rb.resize(16);
- queue_count = 0;
-}
-
-Error PacketPeerUDPWinsock::wait() {
-
- return _poll(true);
-}
-Error PacketPeerUDPWinsock::_poll(bool p_wait) {
-
- if (sockfd == -1) {
- return FAILED;
- }
-
- _set_sock_blocking(p_wait);
-
- struct sockaddr_storage from = { 0 };
- int len = sizeof(struct sockaddr_storage);
- int ret;
- while ((ret = recvfrom(sockfd, (char *)recv_buffer, MIN((int)sizeof(recv_buffer), MAX(rb.space_left() - 24, 0)), 0, (struct sockaddr *)&from, &len)) > 0) {
-
- uint32_t port = 0;
-
- if (from.ss_family == AF_INET) {
- uint8_t type = (uint8_t)IP::TYPE_IPV4;
- rb.write(&type, 1);
- struct sockaddr_in *sin_from = (struct sockaddr_in *)&from;
- rb.write((uint8_t *)&sin_from->sin_addr, 4);
- port = ntohs(sin_from->sin_port);
-
- } else if (from.ss_family == AF_INET6) {
-
- uint8_t type = (uint8_t)IP::TYPE_IPV6;
- rb.write(&type, 1);
-
- struct sockaddr_in6 *s6_from = (struct sockaddr_in6 *)&from;
- rb.write((uint8_t *)&s6_from->sin6_addr, 16);
-
- port = ntohs(s6_from->sin6_port);
-
- } else {
- // WARN_PRINT("Ignoring packet with unknown address family");
- uint8_t type = (uint8_t)IP::TYPE_NONE;
- rb.write(&type, 1);
- };
-
- rb.write((uint8_t *)&port, 4);
- rb.write((uint8_t *)&ret, 4);
- rb.write(recv_buffer, ret);
-
- len = sizeof(struct sockaddr_storage);
- ++queue_count;
- if (p_wait)
- break;
- };
-
- if (ret == SOCKET_ERROR) {
- int error = WSAGetLastError();
-
- if (error == WSAEWOULDBLOCK) {
- // Expected when doing non-blocking sockets, retry later.
- } else if (error == WSAECONNRESET) {
- // If the remote target does not accept messages, this error may occur, but is harmless.
- // Once the remote target gets available, this message will disappear for new messages.
- } else {
- close();
- return FAILED;
- }
- }
-
- if (ret == 0) {
- close();
- return FAILED;
- };
-
- return OK;
-}
-
-bool PacketPeerUDPWinsock::is_listening() const {
-
- return sockfd != -1;
-}
-
-IP_Address PacketPeerUDPWinsock::get_packet_address() const {
-
- return packet_ip;
-}
-
-int PacketPeerUDPWinsock::get_packet_port() const {
-
- return packet_port;
-}
-
-int PacketPeerUDPWinsock::_get_socket() {
-
- ERR_FAIL_COND_V(sock_type == IP::TYPE_NONE, -1);
-
- if (sockfd != -1)
- return sockfd;
-
- sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
-
- if (sockfd != -1)
- _set_sock_blocking(false);
-
- return sockfd;
-}
-
-void PacketPeerUDPWinsock::set_dest_address(const IP_Address &p_address, int p_port) {
-
- peer_addr = p_address;
- peer_port = p_port;
-}
-
-void PacketPeerUDPWinsock::make_default() {
-
- PacketPeerUDP::_create = PacketPeerUDPWinsock::_create;
-};
-
-PacketPeerUDP *PacketPeerUDPWinsock::_create() {
-
- return memnew(PacketPeerUDPWinsock);
-};
-
-PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
-
- blocking = true;
- sock_blocking = true;
- sockfd = -1;
- packet_port = 0;
- queue_count = 0;
- peer_port = 0;
- sock_type = IP::TYPE_NONE;
- rb.resize(16);
-}
-
-PacketPeerUDPWinsock::~PacketPeerUDPWinsock() {
-
- close();
-}
-
-#endif
diff --git a/drivers/windows/packet_peer_udp_winsock.h b/drivers/windows/packet_peer_udp_winsock.h
deleted file mode 100644
index 8d575c2033..0000000000
--- a/drivers/windows/packet_peer_udp_winsock.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*************************************************************************/
-/* packet_peer_udp_winsock.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef WINDOWS_ENABLED
-
-#ifndef PACKET_PEER_UDP_WINSOCK_H
-#define PACKET_PEER_UDP_WINSOCK_H
-
-#include "io/packet_peer_udp.h"
-#include "ring_buffer.h"
-
-class PacketPeerUDPWinsock : public PacketPeerUDP {
-
- enum {
- PACKET_BUFFER_SIZE = 65536
- };
-
- RingBuffer<uint8_t> rb;
- uint8_t recv_buffer[PACKET_BUFFER_SIZE];
- uint8_t packet_buffer[PACKET_BUFFER_SIZE];
- IP_Address packet_ip;
- int packet_port;
- int queue_count;
- int sockfd;
- bool sock_blocking;
- IP::Type sock_type;
-
- IP_Address peer_addr;
- int peer_port;
-
- _FORCE_INLINE_ int _get_socket();
-
- static PacketPeerUDP *_create();
-
- void _set_sock_blocking(bool p_blocking);
-
- Error _poll(bool p_wait);
-
-public:
- virtual int get_available_packet_count() const;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
- virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
-
- virtual int get_max_packet_size() const;
-
- virtual Error listen(int p_port, const IP_Address &p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536);
- virtual void close();
- virtual Error wait();
- virtual bool is_listening() const;
-
- virtual IP_Address get_packet_address() const;
- virtual int get_packet_port() const;
-
- virtual void set_dest_address(const IP_Address &p_address, int p_port);
-
- static void make_default();
- PacketPeerUDPWinsock();
- ~PacketPeerUDPWinsock();
-};
-#endif // PACKET_PEER_UDP_WINSOCK_H
-
-#endif
diff --git a/drivers/windows/rw_lock_windows.cpp b/drivers/windows/rw_lock_windows.cpp
index 29c24d3d02..ef00141928 100644
--- a/drivers/windows/rw_lock_windows.cpp
+++ b/drivers/windows/rw_lock_windows.cpp
@@ -32,8 +32,9 @@
#include "rw_lock_windows.h"
-#include "error_macros.h"
-#include "os/memory.h"
+#include "core/error_macros.h"
+#include "core/os/memory.h"
+
#include <stdio.h>
void RWLockWindows::read_lock() {
diff --git a/drivers/windows/rw_lock_windows.h b/drivers/windows/rw_lock_windows.h
index fdce28574a..742a0930d4 100644
--- a/drivers/windows/rw_lock_windows.h
+++ b/drivers/windows/rw_lock_windows.h
@@ -33,7 +33,8 @@
#if defined(WINDOWS_ENABLED)
-#include "os/rw_lock.h"
+#include "core/os/rw_lock.h"
+
#include <windows.h>
class RWLockWindows : public RWLock {
diff --git a/drivers/windows/semaphore_windows.cpp b/drivers/windows/semaphore_windows.cpp
index 25fced93ce..34dd387705 100644
--- a/drivers/windows/semaphore_windows.cpp
+++ b/drivers/windows/semaphore_windows.cpp
@@ -32,7 +32,7 @@
#if defined(WINDOWS_ENABLED)
-#include "os/memory.h"
+#include "core/os/memory.h"
Error SemaphoreWindows::wait() {
diff --git a/drivers/windows/semaphore_windows.h b/drivers/windows/semaphore_windows.h
index e099ee437a..1e2f9c152e 100644
--- a/drivers/windows/semaphore_windows.h
+++ b/drivers/windows/semaphore_windows.h
@@ -31,14 +31,16 @@
#ifndef SEMAPHORE_WINDOWS_H
#define SEMAPHORE_WINDOWS_H
-#include "os/semaphore.h"
+#include "core/os/semaphore.h"
#ifdef WINDOWS_ENABLED
#include <windows.h>
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
class SemaphoreWindows : public Semaphore {
mutable HANDLE semaphore;
diff --git a/drivers/windows/shell_windows.h b/drivers/windows/shell_windows.h
index 41cc6b72a2..98972a9bb1 100644
--- a/drivers/windows/shell_windows.h
+++ b/drivers/windows/shell_windows.h
@@ -31,12 +31,14 @@
#ifndef SHELL_WINDOWS_H
#define SHELL_WINDOWS_H
-#include "os/shell.h"
+#include "core/os/shell.h"
#ifdef WINDOWS_ENABLED
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
class ShellWindows : public Shell {
public:
virtual void execute(String p_path);
diff --git a/drivers/windows/stream_peer_tcp_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp
deleted file mode 100644
index 19c937170b..0000000000
--- a/drivers/windows/stream_peer_tcp_winsock.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-/*************************************************************************/
-/* stream_peer_tcp_winsock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef WINDOWS_ENABLED
-
-#include "stream_peer_tcp_winsock.h"
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include "drivers/unix/socket_helpers.h"
-
-int winsock_refcount = 0;
-
-StreamPeerTCP *StreamPeerTCPWinsock::_create() {
-
- return memnew(StreamPeerTCPWinsock);
-};
-
-void StreamPeerTCPWinsock::make_default() {
-
- StreamPeerTCP::_create = StreamPeerTCPWinsock::_create;
-
- if (winsock_refcount == 0) {
- WSADATA data;
- WSAStartup(MAKEWORD(2, 2), &data);
- };
- ++winsock_refcount;
-};
-
-void StreamPeerTCPWinsock::cleanup() {
-
- --winsock_refcount;
- if (winsock_refcount == 0) {
-
- WSACleanup();
- };
-};
-
-Error StreamPeerTCPWinsock::_block(int p_sockfd, bool p_read, bool p_write) const {
-
- fd_set read, write;
- FD_ZERO(&read);
- FD_ZERO(&write);
-
- if (p_read)
- FD_SET(p_sockfd, &read);
- if (p_write)
- FD_SET(p_sockfd, &write);
-
- int ret = select(p_sockfd + 1, &read, &write, NULL, NULL); // block forever
- return ret < 0 ? FAILED : OK;
-};
-
-Error StreamPeerTCPWinsock::_poll_connection() const {
-
- ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == INVALID_SOCKET, FAILED);
-
- struct sockaddr_storage their_addr;
- size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type);
-
- if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) {
-
- int err = WSAGetLastError();
- if (err == WSAEISCONN) {
- status = STATUS_CONNECTED;
- return OK;
- };
-
- if (err == WSAEINPROGRESS || err == WSAEALREADY) {
- return OK;
- }
-
- status = STATUS_ERROR;
- return ERR_CONNECTION_ERROR;
- } else {
-
- status = STATUS_CONNECTED;
- return OK;
- };
-
- return OK;
-};
-
-Error StreamPeerTCPWinsock::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
-
- if (status == STATUS_NONE || status == STATUS_ERROR) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
-
- if (_poll_connection() != OK) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
- r_sent = 0;
- return OK;
- };
- };
-
- int data_to_send = p_bytes;
- const uint8_t *offset = p_data;
- if (sockfd == -1) return FAILED;
- int total_sent = 0;
-
- while (data_to_send) {
-
- int sent_amount = send(sockfd, (const char *)offset, data_to_send, 0);
-
- if (sent_amount == -1) {
-
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
-
- perror("Nothing sent");
- disconnect_from_host();
- ERR_PRINT("Server disconnected!\n");
- return FAILED;
- };
-
- if (!p_block) {
- r_sent = total_sent;
- return OK;
- };
-
- _block(sockfd, false, true);
- } else {
-
- data_to_send -= sent_amount;
- offset += sent_amount;
- total_sent += sent_amount;
- };
- }
-
- r_sent = total_sent;
-
- return OK;
-};
-
-Error StreamPeerTCPWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
-
- if (!is_connected_to_host()) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
-
- if (_poll_connection() != OK) {
-
- return FAILED;
- };
-
- if (status != STATUS_CONNECTED) {
- r_received = 0;
- return OK;
- };
- };
-
- int to_read = p_bytes;
- int total_read = 0;
-
- while (to_read) {
-
- int read = recv(sockfd, (char *)p_buffer + total_read, to_read, 0);
-
- if (read == -1) {
-
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
-
- perror("Nothing read");
- disconnect_from_host();
- ERR_PRINT("Server disconnected!\n");
- return FAILED;
- };
-
- if (!p_block) {
-
- r_received = total_read;
- return OK;
- };
- _block(sockfd, true, false);
- } else if (read == 0) {
- disconnect_from_host();
- r_received = total_read;
- return ERR_FILE_EOF;
- } else {
-
- to_read -= read;
- total_read += read;
- };
- };
-
- r_received = total_read;
-
- return OK;
-};
-
-Error StreamPeerTCPWinsock::put_data(const uint8_t *p_data, int p_bytes) {
-
- int total;
- return write(p_data, p_bytes, total, true);
-};
-
-Error StreamPeerTCPWinsock::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
-
- return write(p_data, p_bytes, r_sent, false);
-};
-
-Error StreamPeerTCPWinsock::get_data(uint8_t *p_buffer, int p_bytes) {
-
- int total;
- return read(p_buffer, p_bytes, total, true);
-};
-
-Error StreamPeerTCPWinsock::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
-
- return read(p_buffer, p_bytes, r_received, false);
-};
-
-StreamPeerTCP::Status StreamPeerTCPWinsock::get_status() const {
-
- if (status == STATUS_CONNECTING) {
- _poll_connection();
- };
-
- return status;
-};
-
-bool StreamPeerTCPWinsock::is_connected_to_host() const {
-
- if (status == STATUS_NONE || status == STATUS_ERROR) {
-
- return false;
- };
- if (status != STATUS_CONNECTED) {
- return true;
- };
-
- return (sockfd != INVALID_SOCKET);
-};
-
-void StreamPeerTCPWinsock::disconnect_from_host() {
-
- if (sockfd != INVALID_SOCKET)
- closesocket(sockfd);
- sockfd = INVALID_SOCKET;
- sock_type = IP::TYPE_NONE;
-
- status = STATUS_NONE;
-
- peer_host = IP_Address();
- peer_port = 0;
-};
-
-void StreamPeerTCPWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) {
-
- sockfd = p_sockfd;
- sock_type = p_sock_type;
- status = STATUS_CONNECTING;
- peer_host = p_host;
- peer_port = p_port;
-};
-
-Error StreamPeerTCPWinsock::connect_to_host(const IP_Address &p_host, uint16_t p_port) {
-
- ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);
-
- sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
- sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
- if (sockfd == INVALID_SOCKET) {
- ERR_PRINT("Socket creation failed!");
- disconnect_from_host();
- //perror("socket");
- return FAILED;
- };
-
- unsigned long par = 1;
- if (ioctlsocket(sockfd, FIONBIO, &par)) {
- perror("setting non-block mode");
- disconnect_from_host();
- return FAILED;
- };
-
- struct sockaddr_storage their_addr;
- size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type);
-
- if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) {
-
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- ERR_PRINT("Connection to remote host failed!");
- disconnect_from_host();
- return FAILED;
- };
- status = STATUS_CONNECTING;
- } else {
- status = STATUS_CONNECTED;
- };
-
- peer_host = p_host;
- peer_port = p_port;
-
- return OK;
-};
-
-void StreamPeerTCPWinsock::set_no_delay(bool p_enabled) {
- ERR_FAIL_COND(!is_connected_to_host());
- int flag = p_enabled ? 1 : 0;
- if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) != 0) {
- ERR_PRINT("Unable to set TCP no delay option");
- }
-}
-
-int StreamPeerTCPWinsock::get_available_bytes() const {
-
- unsigned long len;
- int ret = ioctlsocket(sockfd, FIONREAD, &len);
- ERR_FAIL_COND_V(ret == -1, 0)
- return len;
-}
-
-IP_Address StreamPeerTCPWinsock::get_connected_host() const {
-
- return peer_host;
-};
-
-uint16_t StreamPeerTCPWinsock::get_connected_port() const {
-
- return peer_port;
-};
-
-StreamPeerTCPWinsock::StreamPeerTCPWinsock() {
-
- sock_type = IP::TYPE_NONE;
- sockfd = INVALID_SOCKET;
- status = STATUS_NONE;
- peer_port = 0;
-};
-
-StreamPeerTCPWinsock::~StreamPeerTCPWinsock() {
-
- disconnect_from_host();
-};
-
-#endif
diff --git a/drivers/windows/tcp_server_winsock.cpp b/drivers/windows/tcp_server_winsock.cpp
deleted file mode 100644
index ddb955549f..0000000000
--- a/drivers/windows/tcp_server_winsock.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*************************************************************************/
-/* tcp_server_winsock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef WINDOWS_ENABLED
-
-#include "tcp_server_winsock.h"
-
-#include "stream_peer_tcp_winsock.h"
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include "drivers/unix/socket_helpers.h"
-
-extern int winsock_refcount;
-
-TCP_Server *TCPServerWinsock::_create() {
-
- return memnew(TCPServerWinsock);
-};
-
-void TCPServerWinsock::make_default() {
-
- TCP_Server::_create = TCPServerWinsock::_create;
-
- if (winsock_refcount == 0) {
- WSADATA data;
- WSAStartup(MAKEWORD(2, 2), &data);
- };
- ++winsock_refcount;
-};
-
-void TCPServerWinsock::cleanup() {
-
- --winsock_refcount;
- if (winsock_refcount == 0) {
-
- WSACleanup();
- };
-};
-
-Error TCPServerWinsock::listen(uint16_t p_port, const IP_Address &p_bind_address) {
-
- ERR_FAIL_COND_V(listen_sockfd != -1, ERR_ALREADY_IN_USE);
- ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
-
- int sockfd;
- sock_type = IP::TYPE_ANY;
-
- // If the bind address is valid use its type as the socket type
- if (p_bind_address.is_valid())
- sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
-
- sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
- ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED);
-
- unsigned long par = 1;
- if (ioctlsocket(sockfd, FIONBIO, &par)) {
- perror("setting non-block mode");
- stop();
- return FAILED;
- };
-
- struct sockaddr_storage my_addr;
- size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, sock_type, p_bind_address);
-
- int reuse = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
-
- printf("REUSEADDR failed!");
- }
-
- if (bind(sockfd, (struct sockaddr *)&my_addr, addr_size) != SOCKET_ERROR) {
-
- if (::listen(sockfd, SOMAXCONN) == SOCKET_ERROR) {
-
- closesocket(sockfd);
- ERR_FAIL_V(FAILED);
- };
- } else {
- closesocket(sockfd);
- return ERR_ALREADY_IN_USE;
- };
-
- if (listen_sockfd != INVALID_SOCKET) {
-
- stop();
- };
-
- listen_sockfd = sockfd;
-
- return OK;
-};
-
-bool TCPServerWinsock::is_connection_available() const {
-
- if (listen_sockfd == -1) {
- return false;
- };
-
- timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
-
- fd_set pfd;
- FD_ZERO(&pfd);
- FD_SET(listen_sockfd, &pfd);
-
- int ret = select(listen_sockfd + 1, &pfd, NULL, NULL, &timeout);
- ERR_FAIL_COND_V(ret < 0, 0);
-
- if (ret && (FD_ISSET(listen_sockfd, &pfd))) {
-
- return true;
- };
-
- return false;
-};
-
-Ref<StreamPeerTCP> TCPServerWinsock::take_connection() {
-
- if (!is_connection_available()) {
- return NULL;
- };
-
- struct sockaddr_storage their_addr;
- int sin_size = sizeof(their_addr);
- int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size);
- ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL);
-
- Ref<StreamPeerTCPWinsock> conn = memnew(StreamPeerTCPWinsock);
- IP_Address ip;
- int port;
- _set_ip_addr_port(ip, port, &their_addr);
-
- conn->set_socket(fd, ip, port, sock_type);
-
- return conn;
-};
-
-void TCPServerWinsock::stop() {
-
- if (listen_sockfd != INVALID_SOCKET) {
- closesocket(listen_sockfd);
- };
-
- listen_sockfd = -1;
- sock_type = IP::TYPE_NONE;
-};
-
-TCPServerWinsock::TCPServerWinsock() {
-
- listen_sockfd = INVALID_SOCKET;
- sock_type = IP::TYPE_NONE;
-};
-
-TCPServerWinsock::~TCPServerWinsock() {
-
- stop();
-};
-
-#endif
diff --git a/drivers/windows/tcp_server_winsock.h b/drivers/windows/tcp_server_winsock.h
deleted file mode 100644
index a6979db42d..0000000000
--- a/drivers/windows/tcp_server_winsock.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*************************************************************************/
-/* tcp_server_winsock.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef WINDOWS_ENABLED
-
-#ifndef TCP_SERVER_WINSOCK_H
-#define TCP_SERVER_WINSOCK_H
-
-#include "core/io/tcp_server.h"
-
-class TCPServerWinsock : public TCP_Server {
-
- int listen_sockfd;
- IP::Type sock_type;
-
- static TCP_Server *_create();
-
-public:
- virtual Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*"));
- virtual bool is_connection_available() const;
- virtual Ref<StreamPeerTCP> take_connection();
-
- virtual void stop(); //stop listening
-
- static void make_default();
- static void cleanup();
-
- TCPServerWinsock();
- ~TCPServerWinsock();
-};
-
-#endif
-
-#endif
diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp
index 5e0b017a5c..52dcfacdf8 100644
--- a/drivers/windows/thread_windows.cpp
+++ b/drivers/windows/thread_windows.cpp
@@ -32,7 +32,7 @@
#if defined(WINDOWS_ENABLED) && !defined(UWP_ENABLED)
-#include "os/memory.h"
+#include "core/os/memory.h"
Thread::ID ThreadWindows::get_id() const {
diff --git a/drivers/windows/thread_windows.h b/drivers/windows/thread_windows.h
index d7a8389d9e..5d2838e54f 100644
--- a/drivers/windows/thread_windows.h
+++ b/drivers/windows/thread_windows.h
@@ -31,16 +31,17 @@
#ifndef THREAD_WINDOWS_H
#define THREAD_WINDOWS_H
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
#ifdef WINDOWS_ENABLED
-#include "os/thread.h"
-#include "script_language.h"
+#include "core/os/thread.h"
+#include "core/script_language.h"
+
#include <windows.h>
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
class ThreadWindows : public Thread {
ThreadCreateCallback callback;
diff --git a/drivers/winmidi/SCsub b/drivers/winmidi/SCsub
index 233593b0f9..4c24925192 100644
--- a/drivers/winmidi/SCsub
+++ b/drivers/winmidi/SCsub
@@ -4,5 +4,3 @@ Import('env')
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
-
-Export('env')
diff --git a/drivers/winmidi/win_midi.cpp b/drivers/winmidi/win_midi.cpp
index 63f7f13685..1d4bf1a1e2 100644
--- a/drivers/winmidi/win_midi.cpp
+++ b/drivers/winmidi/win_midi.cpp
@@ -31,7 +31,8 @@
#ifdef WINMIDI_ENABLED
#include "win_midi.h"
-#include "print_string.h"
+
+#include "core/print_string.h"
void MIDIDriverWinMidi::read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
diff --git a/drivers/winmidi/win_midi.h b/drivers/winmidi/win_midi.h
index 1cf9b19b5d..87a349d5d1 100644
--- a/drivers/winmidi/win_midi.h
+++ b/drivers/winmidi/win_midi.h
@@ -33,14 +33,14 @@
#ifndef WIN_MIDI_H
#define WIN_MIDI_H
+#include "core/os/midi_driver.h"
+#include "core/vector.h"
+
#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>
-#include "core/vector.h"
-#include "os/midi_driver.h"
-
class MIDIDriverWinMidi : public MIDIDriver {
Vector<HMIDIIN> connected_sources;
diff --git a/drivers/xaudio2/SCsub b/drivers/xaudio2/SCsub
index cb780a893b..3dca95b429 100644
--- a/drivers/xaudio2/SCsub
+++ b/drivers/xaudio2/SCsub
@@ -5,5 +5,3 @@ Import('env')
env.add_source_files(env.drivers_sources, "*.cpp")
env.Append(CXXFLAGS=['-DXAUDIO2_ENABLED'])
env.Append(LINKFLAGS=['xaudio2_8.lib'])
-
-Export('env')
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index a1002ef4f9..452a1105ca 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -30,8 +30,8 @@
#include "audio_driver_xaudio2.h"
-#include "os/os.h"
-#include "project_settings.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
const char *AudioDriverXAudio2::get_name() const {
return "XAudio2";
diff --git a/drivers/zlib/SCsub b/drivers/zlib/SCsub
deleted file mode 100644
index 407deb5f6e..0000000000
--- a/drivers/zlib/SCsub
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python
-
-Import('env')
-
-# Not cloning the env, the includes need to be accessible for core/
-
-# Thirdparty source files
-# No check here as already done in drivers/SCsub
-thirdparty_dir = "#thirdparty/zlib/"
-thirdparty_sources = [
- "adler32.c",
- "compress.c",
- "crc32.c",
- "deflate.c",
- "infback.c",
- "inffast.c",
- "inflate.c",
- "inftrees.c",
- "trees.c",
- "uncompr.c",
- "zutil.c",
-]
-thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-
-env.add_source_files(env.drivers_sources, thirdparty_sources)
-env.Append(CPPPATH=[thirdparty_dir])