summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_stream.cpp22
-rw-r--r--servers/audio_server.cpp16
-rw-r--r--servers/audio_server.h6
-rw-r--r--servers/camera/camera_feed.cpp105
-rw-r--r--servers/camera/camera_feed.h4
-rw-r--r--servers/physics_2d/body_2d_sw.h6
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp40
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h4
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h4
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp65
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp72
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h2
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp28
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h6
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h12
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp70
-rw-r--r--servers/physics_2d/shape_2d_sw.h45
-rw-r--r--servers/physics_2d/space_2d_sw.cpp235
-rw-r--r--servers/physics_2d/space_2d_sw.h3
-rw-r--r--servers/physics_3d/area_3d_sw.cpp8
-rw-r--r--servers/physics_3d/area_3d_sw.h34
-rw-r--r--servers/physics_3d/area_pair_3d_sw.cpp82
-rw-r--r--servers/physics_3d/area_pair_3d_sw.h18
-rw-r--r--servers/physics_3d/body_3d_sw.h14
-rw-r--r--servers/physics_3d/body_pair_3d_sw.cpp156
-rw-r--r--servers/physics_3d/body_pair_3d_sw.h9
-rw-r--r--servers/physics_3d/collision_object_3d_sw.h4
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp49
-rw-r--r--servers/physics_3d/collision_solver_3d_sw.cpp51
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp21
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h4
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h10
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp135
-rw-r--r--servers/physics_3d/shape_3d_sw.h38
-rw-r--r--servers/physics_3d/soft_body_3d_sw.cpp41
-rw-r--r--servers/physics_3d/soft_body_3d_sw.h26
-rw-r--r--servers/physics_3d/space_3d_sw.cpp212
-rw-r--r--servers/physics_3d/space_3d_sw.h3
-rw-r--r--servers/physics_server_2d.cpp40
-rw-r--r--servers/physics_server_2d.h24
-rw-r--r--servers/physics_server_3d.cpp30
-rw-r--r--servers/physics_server_3d.h30
-rw-r--r--servers/rendering/rasterizer_dummy.h26
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp8
-rw-r--r--servers/rendering/renderer_compositor.h2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp604
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h141
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp27
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp3
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp445
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h21
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp3
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp10
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp320
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h33
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp377
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h10
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp70
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h62
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster.glsl98
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/bokeh_dof.glsl38
-rw-r--r--servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl37
-rw-r--r--servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl253
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl48
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl48
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl163
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl256
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl95
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl94
-rw-r--r--servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl63
-rw-r--r--servers/rendering/renderer_rd/shaders/light_data_inc.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl37
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl41
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl16
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl32
-rw-r--r--servers/rendering/renderer_scene_cull.cpp79
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h2
-rw-r--r--servers/rendering/renderer_storage.h22
-rw-r--r--servers/rendering/rendering_device.cpp8
-rw-r--r--servers/rendering/rendering_device.h3
-rw-r--r--servers/rendering/rendering_server_default.cpp12
-rw-r--r--servers/rendering/rendering_server_default.h22
-rw-r--r--servers/rendering/shader_language.cpp1431
-rw-r--r--servers/rendering/shader_language.h3
-rw-r--r--servers/rendering/shader_types.cpp22
-rw-r--r--servers/rendering/shader_types.h8
-rw-r--r--servers/rendering_server.cpp97
-rw-r--r--servers/rendering_server.h26
-rw-r--r--servers/text_server.cpp92
-rw-r--r--servers/text_server.h28
95 files changed, 4360 insertions, 2812 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index aec6932326..f3fa857682 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -48,27 +48,27 @@ void AudioStreamPlaybackResampled::_begin_resample() {
void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
float target_rate = AudioServer::get_singleton()->get_mix_rate();
- float global_rate_scale = AudioServer::get_singleton()->get_global_rate_scale();
+ float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale();
- uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale) / double(target_rate * global_rate_scale)) * double(FP_LEN));
+ uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale * playback_speed_scale) / double(target_rate)) * double(FP_LEN));
for (int i = 0; i < p_frames; i++) {
uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
- // 4 point, 4th order optimal resampling algorithm from: http://yehar.com/blog/wp-content/uploads/2009/08/deip.pdf
+ //standard cubic interpolation (great quality/performance ratio)
+ //this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory.
float mu = (mix_offset & FP_MASK) / float(FP_LEN);
AudioFrame y0 = internal_buffer[idx - 3];
AudioFrame y1 = internal_buffer[idx - 2];
AudioFrame y2 = internal_buffer[idx - 1];
AudioFrame y3 = internal_buffer[idx - 0];
- AudioFrame even1 = y2 + y1, odd1 = y2 - y1;
- AudioFrame even2 = y3 + y0, odd2 = y3 - y0;
- AudioFrame c0 = even1 * 0.46835497211269561 + even2 * 0.03164502784253309;
- AudioFrame c1 = odd1 * 0.56001293337091440 + odd2 * 0.14666238593949288;
- AudioFrame c2 = even1 * -0.250038759826233691 + even2 * 0.25003876124297131;
- AudioFrame c3 = odd1 * -0.49949850957839148 + odd2 * 0.16649935475113800;
- AudioFrame c4 = even1 * 0.00016095224137360 + even2 * -0.00016095810460478;
- p_buffer[i] = (((c4 * mu + c3) * mu + c2) * mu + c1) * mu + c0;
+ float mu2 = mu * mu;
+ AudioFrame a0 = 3 * y1 - 3 * y2 + y3 - y0;
+ AudioFrame a1 = 2 * y0 - 5 * y1 + 4 * y2 - y3;
+ AudioFrame a2 = y2 - y0;
+ AudioFrame a3 = 2 * y1;
+
+ p_buffer[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3) / 2;
mix_offset += mix_increment;
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 076cbb58af..4c54188cb2 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -913,14 +913,14 @@ bool AudioServer::is_bus_channel_active(int p_bus, int p_channel) const {
return buses[p_bus]->channels[p_channel].active;
}
-void AudioServer::set_global_rate_scale(float p_scale) {
+void AudioServer::set_playback_speed_scale(float p_scale) {
ERR_FAIL_COND(p_scale <= 0);
- global_rate_scale = p_scale;
+ playback_speed_scale = p_scale;
}
-float AudioServer::get_global_rate_scale() const {
- return global_rate_scale;
+float AudioServer::get_playback_speed_scale() const {
+ return playback_speed_scale;
}
void AudioServer::init_channels_and_buffers() {
@@ -1277,8 +1277,8 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bus_peak_volume_left_db", "bus_idx", "channel"), &AudioServer::get_bus_peak_volume_left_db);
ClassDB::bind_method(D_METHOD("get_bus_peak_volume_right_db", "bus_idx", "channel"), &AudioServer::get_bus_peak_volume_right_db);
- ClassDB::bind_method(D_METHOD("set_global_rate_scale", "scale"), &AudioServer::set_global_rate_scale);
- ClassDB::bind_method(D_METHOD("get_global_rate_scale"), &AudioServer::get_global_rate_scale);
+ ClassDB::bind_method(D_METHOD("set_playback_speed_scale", "scale"), &AudioServer::set_playback_speed_scale);
+ ClassDB::bind_method(D_METHOD("get_playback_speed_scale"), &AudioServer::get_playback_speed_scale);
ClassDB::bind_method(D_METHOD("lock"), &AudioServer::lock);
ClassDB::bind_method(D_METHOD("unlock"), &AudioServer::unlock);
@@ -1302,7 +1302,7 @@ void AudioServer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rate_scale"), "set_global_rate_scale", "get_global_rate_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed_scale"), "set_playback_speed_scale", "get_playback_speed_scale");
ADD_SIGNAL(MethodInfo("bus_layout_changed"));
@@ -1322,7 +1322,7 @@ AudioServer::AudioServer() {
#endif
mix_time = 0;
mix_size = 0;
- global_rate_scale = 1;
+ playback_speed_scale = 1;
}
AudioServer::~AudioServer() {
diff --git a/servers/audio_server.h b/servers/audio_server.h
index a1a373e1ca..7974c4a2ad 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -177,7 +177,7 @@ private:
int channel_count;
int to_mix;
- float global_rate_scale;
+ float playback_speed_scale;
struct Bus {
StringName name;
@@ -316,8 +316,8 @@ public:
bool is_bus_channel_active(int p_bus, int p_channel) const;
- void set_global_rate_scale(float p_scale);
- float get_global_rate_scale() const;
+ void set_playback_speed_scale(float p_scale);
+ float get_playback_speed_scale() const;
virtual void init();
virtual void finish();
diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp
index eab4c61591..9f8e8a8106 100644
--- a/servers/camera/camera_feed.cpp
+++ b/servers/camera/camera_feed.cpp
@@ -33,18 +33,17 @@
#include "servers/rendering_server.h"
void CameraFeed::_bind_methods() {
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
// The setters prefixed with _ are only exposed so we can have feeds through GDNative!
// They should not be called by the end user.
ClassDB::bind_method(D_METHOD("get_id"), &CameraFeed::get_id);
- ClassDB::bind_method(D_METHOD("get_name"), &CameraFeed::get_name);
- ClassDB::bind_method(D_METHOD("_set_name", "name"), &CameraFeed::set_name);
ClassDB::bind_method(D_METHOD("is_active"), &CameraFeed::is_active);
ClassDB::bind_method(D_METHOD("set_active", "active"), &CameraFeed::set_active);
+ ClassDB::bind_method(D_METHOD("get_name"), &CameraFeed::get_name);
+ ClassDB::bind_method(D_METHOD("_set_name", "name"), &CameraFeed::set_name);
+
ClassDB::bind_method(D_METHOD("get_position"), &CameraFeed::get_position);
ClassDB::bind_method(D_METHOD("_set_position", "position"), &CameraFeed::set_position);
@@ -54,7 +53,8 @@ void CameraFeed::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_RGB_img", "rgb_img"), &CameraFeed::set_RGB_img);
ClassDB::bind_method(D_METHOD("_set_YCbCr_img", "ycbcr_img"), &CameraFeed::set_YCbCr_img);
- ClassDB::bind_method(D_METHOD("_allocate_texture", "width", "height", "format", "texture_type", "data_type"), &CameraFeed::allocate_texture);
+
+ ClassDB::bind_method(D_METHOD("get_datatype"), &CameraFeed::get_datatype);
ADD_GROUP("Feed", "feed_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feed_is_active"), "set_active", "is_active");
@@ -68,7 +68,6 @@ void CameraFeed::_bind_methods() {
BIND_ENUM_CONSTANT(FEED_UNSPECIFIED);
BIND_ENUM_CONSTANT(FEED_FRONT);
BIND_ENUM_CONSTANT(FEED_BACK);
-#endif
}
int CameraFeed::get_id() const {
@@ -139,19 +138,15 @@ RID CameraFeed::get_texture(CameraServer::FeedImage p_which) {
CameraFeed::CameraFeed() {
// initialize our feed
id = CameraServer::get_singleton()->get_free_id();
+ base_width = 0;
+ base_height = 0;
name = "???";
active = false;
datatype = CameraFeed::FEED_RGB;
position = CameraFeed::FEED_UNSPECIFIED;
transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0);
-
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- // create a texture object
- RenderingServer *vs = RenderingServer::get_singleton();
- texture[CameraServer::FEED_Y_IMAGE] = vs->texture_create(); // also used for RGBA
- texture[CameraServer::FEED_CBCR_IMAGE] = vs->texture_create();
-#endif
+ texture[CameraServer::FEED_Y_IMAGE] = RenderingServer::get_singleton()->texture_2d_placeholder_create();
+ texture[CameraServer::FEED_CBCR_IMAGE] = RenderingServer::get_singleton()->texture_2d_placeholder_create();
}
CameraFeed::CameraFeed(String p_name, FeedPosition p_position) {
@@ -164,33 +159,19 @@ CameraFeed::CameraFeed(String p_name, FeedPosition p_position) {
datatype = CameraFeed::FEED_NOIMAGE;
position = p_position;
transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0);
-
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- // create a texture object
- RenderingServer *vs = RenderingServer::get_singleton();
- texture[CameraServer::FEED_Y_IMAGE] = vs->texture_create(); // also used for RGBA
- texture[CameraServer::FEED_CBCR_IMAGE] = vs->texture_create();
-#endif
+ texture[CameraServer::FEED_Y_IMAGE] = RenderingServer::get_singleton()->texture_2d_placeholder_create();
+ texture[CameraServer::FEED_CBCR_IMAGE] = RenderingServer::get_singleton()->texture_2d_placeholder_create();
}
CameraFeed::~CameraFeed() {
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
// Free our textures
- RenderingServer *vs = RenderingServer::get_singleton();
- vs->free(texture[CameraServer::FEED_Y_IMAGE]);
- vs->free(texture[CameraServer::FEED_CBCR_IMAGE]);
-#endif
+ RenderingServer::get_singleton()->free(texture[CameraServer::FEED_Y_IMAGE]);
+ RenderingServer::get_singleton()->free(texture[CameraServer::FEED_CBCR_IMAGE]);
}
void CameraFeed::set_RGB_img(const Ref<Image> &p_rgb_img) {
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
ERR_FAIL_COND(p_rgb_img.is_null());
if (active) {
- RenderingServer *vs = RenderingServer::get_singleton();
-
int new_width = p_rgb_img->get_width();
int new_height = p_rgb_img->get_height();
@@ -199,22 +180,19 @@ void CameraFeed::set_RGB_img(const Ref<Image> &p_rgb_img) {
base_width = new_width;
base_height = new_height;
- vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAGS_DEFAULT);
+ RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_rgb_img);
+ RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_RGBA_IMAGE], new_texture);
+ } else {
+ RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_RGBA_IMAGE], p_rgb_img);
}
- vs->texture_set_data(texture[CameraServer::FEED_RGBA_IMAGE], p_rgb_img);
datatype = CameraFeed::FEED_RGB;
}
-#endif
}
void CameraFeed::set_YCbCr_img(const Ref<Image> &p_ycbcr_img) {
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
ERR_FAIL_COND(p_ycbcr_img.is_null());
if (active) {
- RenderingServer *vs = RenderingServer::get_singleton();
-
int new_width = p_ycbcr_img->get_width();
int new_height = p_ycbcr_img->get_height();
@@ -223,66 +201,47 @@ void CameraFeed::set_YCbCr_img(const Ref<Image> &p_ycbcr_img) {
base_width = new_width;
base_height = new_height;
- vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAGS_DEFAULT);
+ RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_ycbcr_img);
+ RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_RGBA_IMAGE], new_texture);
+ } else {
+ RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_RGBA_IMAGE], p_ycbcr_img);
}
- vs->texture_set_data(texture[CameraServer::FEED_RGBA_IMAGE], p_ycbcr_img);
datatype = CameraFeed::FEED_YCBCR;
}
-#endif
}
void CameraFeed::set_YCbCr_imgs(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img) {
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
ERR_FAIL_COND(p_y_img.is_null());
ERR_FAIL_COND(p_cbcr_img.is_null());
if (active) {
- RenderingServer *vs = RenderingServer::get_singleton();
-
///@TODO investigate whether we can use thirdparty/misc/yuv2rgb.h here to convert our YUV data to RGB, our shader approach is potentially faster though..
// Wondering about including that into multiple projects, may cause issues.
// That said, if we convert to RGB, we could enable using texture resources again...
int new_y_width = p_y_img->get_width();
int new_y_height = p_y_img->get_height();
- int new_cbcr_width = p_cbcr_img->get_width();
- int new_cbcr_height = p_cbcr_img->get_height();
if ((base_width != new_y_width) || (base_height != new_y_height)) {
// We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
base_width = new_y_width;
base_height = new_y_height;
-
- vs->texture_allocate(texture[CameraServer::FEED_Y_IMAGE], new_y_width, new_y_height, 0, Image::FORMAT_R8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAG_USED_FOR_STREAMING);
-
- ///@TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion
- vs->texture_allocate(texture[CameraServer::FEED_CBCR_IMAGE], new_cbcr_width, new_cbcr_height, 0, Image::FORMAT_RG8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAG_USED_FOR_STREAMING);
+ {
+ RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_y_img);
+ RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_Y_IMAGE], new_texture);
+ }
+ {
+ RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_cbcr_img);
+ RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_CBCR_IMAGE], new_texture);
+ }
+ } else {
+ RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_Y_IMAGE], p_y_img);
+ RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_CBCR_IMAGE], p_cbcr_img);
}
- vs->texture_set_data(texture[CameraServer::FEED_Y_IMAGE], p_y_img);
- vs->texture_set_data(texture[CameraServer::FEED_CBCR_IMAGE], p_cbcr_img);
datatype = CameraFeed::FEED_YCBCR_SEP;
}
-#endif
-}
-
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
-void CameraFeed::allocate_texture(int p_width, int p_height, Image::Format p_format, RenderingServer::TextureType p_texture_type, FeedDataType p_data_type) {
- RenderingServer *vs = RenderingServer::get_singleton();
-
- if ((base_width != p_width) || (base_height != p_height)) {
- // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
- base_width = p_width;
- base_height = p_height;
-
- vs->texture_allocate(texture[0], p_width, p_height, 0, p_format, p_texture_type, RS::TEXTURE_FLAGS_DEFAULT);
- }
-
- datatype = p_data_type;
}
-#endif
bool CameraFeed::activate_feed() {
// nothing to do here
diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h
index fac7ae1b2d..1f80d15e30 100644
--- a/servers/camera/camera_feed.h
+++ b/servers/camera/camera_feed.h
@@ -103,10 +103,6 @@ public:
void set_RGB_img(const Ref<Image> &p_rgb_img);
void set_YCbCr_img(const Ref<Image> &p_ycbcr_img);
void set_YCbCr_imgs(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img);
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
- void allocate_texture(int p_width, int p_height, Image::Format p_format, RenderingServer::TextureType p_texture_type, FeedDataType p_data_type);
-#endif
virtual bool activate_feed();
virtual void deactivate_feed();
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index b4a95651cb..74bef433dc 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -266,6 +266,10 @@ public:
void integrate_forces(real_t p_step);
void integrate_velocities(real_t p_step);
+ _FORCE_INLINE_ Vector2 get_velocity_in_local_point(const Vector2 &rel_pos) const {
+ return linear_velocity + Vector2(-angular_velocity * rel_pos.y, angular_velocity * rel_pos.x);
+ }
+
_FORCE_INLINE_ Vector2 get_motion() const {
if (mode > PhysicsServer2D::BODY_MODE_KINEMATIC) {
return new_transform.get_origin() - get_transform().get_origin();
@@ -352,6 +356,8 @@ public:
virtual void set_transform(const Transform2D &p_transform) override { body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform); }
virtual Transform2D get_transform() const override { return body->get_transform(); }
+ virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const override { return body->get_velocity_in_local_point(p_position); }
+
virtual void add_central_force(const Vector2 &p_force) override { body->add_central_force(p_force); }
virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override { body->add_force(p_force, p_position); }
virtual void add_torque(real_t p_torque) override { body->add_torque(p_torque); }
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index 71d985a6c5..91d747b492 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -226,16 +226,16 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) {
}
bool BodyPair2DSW::setup(real_t p_step) {
- dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
- dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
-
if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
}
+ collide_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) && A->collides_with(B);
+ collide_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) && B->collides_with(A);
+
report_contacts_only = false;
- if (!dynamic_A && !dynamic_B) {
+ if (!collide_A && !collide_B) {
if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) {
report_contacts_only = true;
} else {
@@ -275,13 +275,13 @@ bool BodyPair2DSW::setup(real_t p_step) {
if (!collided) {
//test ccd (currently just a raycast)
- if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && dynamic_A) {
+ if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_A) {
if (_test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B)) {
collided = true;
}
}
- if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && dynamic_B) {
+ if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_B) {
if (_test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A, true)) {
collided = true;
}
@@ -374,6 +374,12 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
const Transform2D &transform_A = A->get_transform();
const Transform2D &transform_B = B->get_transform();
+ real_t inv_inertia_A = collide_A ? A->get_inv_inertia() : 0.0;
+ real_t inv_inertia_B = collide_B ? B->get_inv_inertia() : 0.0;
+
+ real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0;
+ real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0;
+
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
c.active = false;
@@ -384,7 +390,7 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
Vector2 axis = global_A - global_B;
real_t depth = axis.dot(c.normal);
- if (depth <= 0 || !c.reused) {
+ if (depth <= 0.0 || !c.reused) {
continue;
}
@@ -416,15 +422,15 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
// Precompute normal mass, tangent mass, and bias.
real_t rnA = c.rA.dot(c.normal);
real_t rnB = c.rB.dot(c.normal);
- real_t kNormal = A->get_inv_mass() + B->get_inv_mass();
- kNormal += A->get_inv_inertia() * (c.rA.dot(c.rA) - rnA * rnA) + B->get_inv_inertia() * (c.rB.dot(c.rB) - rnB * rnB);
+ real_t kNormal = inv_mass_A + inv_mass_B;
+ kNormal += inv_inertia_A * (c.rA.dot(c.rA) - rnA * rnA) + inv_inertia_B * (c.rB.dot(c.rB) - rnB * rnB);
c.mass_normal = 1.0f / kNormal;
Vector2 tangent = c.normal.orthogonal();
real_t rtA = c.rA.dot(tangent);
real_t rtB = c.rB.dot(tangent);
- real_t kTangent = A->get_inv_mass() + B->get_inv_mass();
- kTangent += A->get_inv_inertia() * (c.rA.dot(c.rA) - rtA * rtA) + B->get_inv_inertia() * (c.rB.dot(c.rB) - rtB * rtB);
+ real_t kTangent = inv_mass_A + inv_mass_B;
+ kTangent += inv_inertia_A * (c.rA.dot(c.rA) - rtA * rtA) + inv_inertia_B * (c.rB.dot(c.rB) - rtB * rtB);
c.mass_tangent = 1.0f / kTangent;
c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration);
@@ -436,10 +442,10 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
// Apply normal + friction impulse
Vector2 P = c.acc_normal_impulse * c.normal + c.acc_tangent_impulse * tangent;
- if (dynamic_A) {
+ if (collide_A) {
A->apply_impulse(-P, c.rA);
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_impulse(P, c.rB);
}
}
@@ -493,10 +499,10 @@ void BodyPair2DSW::solve(real_t p_step) {
Vector2 jb = c.normal * (c.acc_bias_impulse - jbnOld);
- if (dynamic_A) {
+ if (collide_A) {
A->apply_bias_impulse(-jb, c.rA);
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_bias_impulse(jb, c.rB);
}
@@ -513,10 +519,10 @@ void BodyPair2DSW::solve(real_t p_step) {
Vector2 j = c.normal * (c.acc_normal_impulse - jnOld) + tangent * (c.acc_tangent_impulse - jtOld);
- if (dynamic_A) {
+ if (collide_A) {
A->apply_impulse(-j, c.rA);
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_impulse(j, c.rB);
}
}
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h
index 4b42b44c92..849a7e2430 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/body_pair_2d_sw.h
@@ -50,8 +50,8 @@ class BodyPair2DSW : public Constraint2DSW {
int shape_A = 0;
int shape_B = 0;
- bool dynamic_A = false;
- bool dynamic_B = false;
+ bool collide_A = false;
+ bool collide_B = false;
Space2DSW *space = nullptr;
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index 14adb0bb18..55ffa9b1b8 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -186,8 +186,8 @@ public:
void set_pickable(bool p_pickable) { pickable = p_pickable; }
_FORCE_INLINE_ bool is_pickable() const { return pickable; }
- _FORCE_INLINE_ bool layer_in_mask(CollisionObject2DSW *p_other) const {
- return collision_layer & p_other->collision_mask;
+ _FORCE_INLINE_ bool collides_with(CollisionObject2DSW *p_other) const {
+ return p_other->collision_layer & collision_mask;
}
_FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const {
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp
index 29242a554b..30a99d3d74 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/collision_solver_2d_sat.cpp
@@ -560,16 +560,18 @@ static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D &
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5))) {
+ real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
+
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5))) {
+ if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
return;
}
@@ -715,11 +717,13 @@ static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p
return;
}
+ real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
+
//capsule endpoints
- if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5))) {
+ if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
return;
}
- if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5))) {
+ if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
return;
}
@@ -864,9 +868,11 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
Transform2D boxinv = p_transform_a.affine_inverse();
+ real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
+
for (int i = 0; i < 2; i++) {
{
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
return;
@@ -874,7 +880,7 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
}
if (castA) {
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
capsule_endpoint -= p_motion_a;
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
@@ -883,7 +889,7 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
}
if (castB) {
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
capsule_endpoint += p_motion_b;
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
@@ -892,7 +898,7 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
}
if (castA && castB) {
- Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
capsule_endpoint -= p_motion_a;
capsule_endpoint += p_motion_b;
@@ -900,6 +906,8 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
return;
}
}
+
+ capsule_dir *= -1.0;
}
separator.generate_contacts();
@@ -994,16 +1002,22 @@ static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D &
//capsule endpoints
+ real_t capsule_dir_A = capsule_A->get_height() * 0.5 - capsule_A->get_radius();
for (int i = 0; i < 2; i++) {
- Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_A->get_height() * (i == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_dir_A;
+ real_t capsule_dir_B = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
for (int j = 0; j < 2; j++) {
- Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (j == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir_B;
if (TEST_POINT(capsule_endpoint_A, capsule_endpoint_B)) {
return;
}
+
+ capsule_dir_B *= -1.0;
}
+
+ capsule_dir_A *= -1.0;
}
separator.generate_contacts();
@@ -1034,12 +1048,15 @@ static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transf
for (int i = 0; i < convex_B->get_point_count(); i++) {
Vector2 cpoint = p_transform_b.xform(convex_B->get_point(i));
+ real_t capsule_dir = capsule_A->get_height() * 0.5 - capsule_A->get_radius();
for (int j = 0; j < 2; j++) {
- Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_A->get_height() * (j == 0 ? 0.5 : -0.5);
+ Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_dir;
if (TEST_POINT(capsule_endpoint_A, cpoint)) {
return;
}
+
+ capsule_dir *= -1.0;
}
if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i))) {
@@ -1097,14 +1114,12 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const
bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer2D::ShapeType type_A = p_shape_A->get_type();
- ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_LINE, false);
- //ERR_FAIL_COND_V(type_A==PhysicsServer2D::SHAPE_RAY,false);
+ ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN, false);
ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
PhysicsServer2D::ShapeType type_B = p_shape_B->get_type();
- ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_LINE, false);
- //ERR_FAIL_COND_V(type_B==PhysicsServer2D::SHAPE_RAY,false);
+ ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN, false);
ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
static const CollisionFunc collision_table[5][5] = {
@@ -1367,23 +1382,23 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D
if (p_margin_A || p_margin_B) {
if (*motion_A == Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table_margin[type_A - 2][type_B - 2];
+ collision_func = collision_table_margin[type_A - 1][type_B - 1];
} else if (*motion_A != Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table_castA_margin[type_A - 2][type_B - 2];
+ collision_func = collision_table_castA_margin[type_A - 1][type_B - 1];
} else if (*motion_A == Vector2() && *motion_B != Vector2()) {
- collision_func = collision_table_castB_margin[type_A - 2][type_B - 2];
+ collision_func = collision_table_castB_margin[type_A - 1][type_B - 1];
} else {
- collision_func = collision_table_castA_castB_margin[type_A - 2][type_B - 2];
+ collision_func = collision_table_castA_castB_margin[type_A - 1][type_B - 1];
}
} else {
if (*motion_A == Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table[type_A - 2][type_B - 2];
+ collision_func = collision_table[type_A - 1][type_B - 1];
} else if (*motion_A != Vector2() && *motion_B == Vector2()) {
- collision_func = collision_table_castA[type_A - 2][type_B - 2];
+ collision_func = collision_table_castA[type_A - 1][type_B - 1];
} else if (*motion_A == Vector2() && *motion_B != Vector2()) {
- collision_func = collision_table_castB[type_A - 2][type_B - 2];
+ collision_func = collision_table_castB[type_A - 1][type_B - 1];
} else {
- collision_func = collision_table_castA_castB[type_A - 2][type_B - 2];
+ collision_func = collision_table_castA_castB[type_A - 1][type_B - 1];
}
}
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index 5bd4d498c6..8f8a4a862c 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -34,14 +34,14 @@
#define collision_solver sat_2d_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const LineShape2DSW *line = static_cast<const LineShape2DSW *>(p_shape_A);
- if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_LINE) {
+bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const WorldMarginShape2DSW *world_margin = static_cast<const WorldMarginShape2DSW *>(p_shape_A);
+ if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_MARGIN) {
return false;
}
- Vector2 n = p_transform_A.basis_xform(line->get_normal()).normalized();
- Vector2 p = p_transform_A.xform(line->get_normal() * line->get_d());
+ Vector2 n = p_transform_A.basis_xform(world_margin->get_normal()).normalized();
+ Vector2 p = p_transform_A.xform(world_margin->get_normal() * world_margin->get_d());
real_t d = n.dot(p);
Vector2 supports[2];
@@ -73,49 +73,6 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Tr
return found;
}
-bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) {
- const RayShape2DSW *ray = static_cast<const RayShape2DSW *>(p_shape_A);
- if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_RAY) {
- return false;
- }
-
- Vector2 from = p_transform_A.get_origin();
- Vector2 to = from + p_transform_A[1] * ray->get_length();
- if (p_motion_A != Vector2()) {
- //not the best but should be enough
- Vector2 normal = (to - from).normalized();
- to += normal * MAX(0.0, normal.dot(p_motion_A));
- }
- Vector2 support_A = to;
-
- Transform2D invb = p_transform_B.affine_inverse();
- from = invb.xform(from);
- to = invb.xform(to);
-
- Vector2 p, n;
- if (!p_shape_B->intersect_segment(from, to, p, n)) {
- if (sep_axis) {
- *sep_axis = p_transform_A[1].normalized();
- }
- return false;
- }
-
- Vector2 support_B = p_transform_B.xform(p);
- if (ray->get_slips_on_slope()) {
- Vector2 global_n = invb.basis_xform_inv(n).normalized();
- support_B = support_A + (support_B - support_A).length() * global_n;
- }
-
- if (p_result_callback) {
- if (p_swap_result) {
- p_result_callback(support_B, support_A, p_userdata);
- } else {
- p_result_callback(support_A, support_B, p_userdata);
- }
- }
- return true;
-}
-
struct _ConcaveCollisionInfo2D {
const Transform2D *transform_A;
const Shape2DSW *shape_A;
@@ -209,26 +166,15 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p
swap = true;
}
- if (type_A == PhysicsServer2D::SHAPE_LINE) {
- if (type_B == PhysicsServer2D::SHAPE_LINE || type_B == PhysicsServer2D::SHAPE_RAY) {
+ if (type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN) {
+ if (type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN) {
return false;
}
if (swap) {
- return solve_static_line(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
- } else {
- return solve_static_line(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
- }
-
- } else if (type_A == PhysicsServer2D::SHAPE_RAY) {
- if (type_B == PhysicsServer2D::SHAPE_RAY) {
- return false; //no ray-ray
- }
-
- if (swap) {
- return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis);
+ return solve_static_world_margin(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
} else {
- return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis);
+ return solve_static_world_margin(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
}
} else if (concave_B) {
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index 4f12ca9e88..17c0c2fe70 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -38,7 +38,7 @@ public:
typedef void (*CallbackResult)(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata);
private:
- static bool solve_static_line(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_static_world_margin(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
static bool solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = nullptr);
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index 467c664302..88c097453e 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -42,11 +42,8 @@
RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) {
Shape2DSW *shape = nullptr;
switch (p_shape) {
- case SHAPE_LINE: {
- shape = memnew(LineShape2DSW);
- } break;
- case SHAPE_RAY: {
- shape = memnew(RayShape2DSW);
+ case SHAPE_WORLD_MARGIN: {
+ shape = memnew(WorldMarginShape2DSW);
} break;
case SHAPE_SEGMENT: {
shape = memnew(SegmentShape2DSW);
@@ -78,12 +75,8 @@ RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) {
return id;
}
-RID PhysicsServer2DSW::line_shape_create() {
- return _shape_create(SHAPE_LINE);
-}
-
-RID PhysicsServer2DSW::ray_shape_create() {
- return _shape_create(SHAPE_RAY);
+RID PhysicsServer2DSW::world_margin_shape_create() {
+ return _shape_create(SHAPE_WORLD_MARGIN);
}
RID PhysicsServer2DSW::segment_shape_create() {
@@ -946,7 +939,7 @@ void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) {
body->set_pickable(p_pickable);
}
-bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
+bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result, const Set<RID> &p_exclude) {
Body2DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -954,16 +947,7 @@ bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from,
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes, p_exclude);
-}
-
-int PhysicsServer2DSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
- Body2DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, false);
- ERR_FAIL_COND_V(!body->get_space(), false);
- ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
-
- return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_exclude);
}
PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index f40b5a7c42..3610f43f93 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -87,8 +87,7 @@ public:
Vector2 *ptr;
};
- virtual RID line_shape_create() override;
- virtual RID ray_shape_create() override;
+ virtual RID world_margin_shape_create() override;
virtual RID segment_shape_create() override;
virtual RID circle_shape_create() override;
virtual RID rectangle_shape_create() override;
@@ -247,8 +246,7 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable) override;
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override;
- virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) override;
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index fb7235c031..b93178919d 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -79,8 +79,7 @@ public:
#include "servers/server_wrap_mt_common.h"
//FUNC1RID(shape,ShapeType); todo fix
- FUNCRID(line_shape)
- FUNCRID(ray_shape)
+ FUNCRID(world_margin_shape)
FUNCRID(segment_shape)
FUNCRID(circle_shape)
FUNCRID(rectangle_shape)
@@ -253,14 +252,9 @@ public:
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override {
+ bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes, p_exclude);
- }
-
- int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) override {
- ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
+ return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_exclude);
}
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 6cc086b9b7..b3e4ca84c3 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -88,15 +88,15 @@ Shape2DSW::~Shape2DSW() {
/*********************************************************/
/*********************************************************/
-void LineShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void WorldMarginShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
r_amount = 0;
}
-bool LineShape2DSW::contains_point(const Vector2 &p_point) const {
+bool WorldMarginShape2DSW::contains_point(const Vector2 &p_point) const {
return normal.dot(p_point) < d;
}
-bool LineShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool WorldMarginShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
Vector2 segment = p_begin - p_end;
real_t den = normal.dot(segment);
@@ -118,11 +118,11 @@ bool LineShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_e
return true;
}
-real_t LineShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t WorldMarginShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0;
}
-void LineShape2DSW::set_data(const Variant &p_data) {
+void WorldMarginShape2DSW::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::ARRAY);
Array arr = p_data;
ERR_FAIL_COND(arr.size() != 2);
@@ -131,7 +131,7 @@ void LineShape2DSW::set_data(const Variant &p_data) {
configure(Rect2(Vector2(-1e4, -1e4), Vector2(1e4 * 2, 1e4 * 2)));
}
-Variant LineShape2DSW::get_data() const {
+Variant WorldMarginShape2DSW::get_data() const {
Array arr;
arr.resize(2);
arr[0] = normal;
@@ -143,46 +143,6 @@ Variant LineShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void RayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
- r_amount = 1;
-
- if (p_normal.y > 0) {
- *r_supports = Vector2(0, length);
- } else {
- *r_supports = Vector2();
- }
-}
-
-bool RayShape2DSW::contains_point(const Vector2 &p_point) const {
- return false;
-}
-
-bool RayShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
- return false; //rays can't be intersected
-}
-
-real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
- return 0; //rays are mass-less
-}
-
-void RayShape2DSW::set_data(const Variant &p_data) {
- Dictionary d = p_data;
- length = d["length"];
- slips_on_slope = d["slips_on_slope"];
- configure(Rect2(0, 0, 0.001, length));
-}
-
-Variant RayShape2DSW::get_data() const {
- Dictionary d;
- d["length"] = length;
- d["slips_on_slope"] = slips_on_slope;
- return d;
-}
-
-/*********************************************************/
-/*********************************************************/
-/*********************************************************/
-
void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
if (Math::abs(p_normal.dot(n)) > _SEGMENT_IS_VALID_SUPPORT_THRESHOLD) {
r_supports[0] = a;
@@ -383,15 +343,15 @@ void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports
r_amount = 2;
r_supports[0] = n;
- r_supports[0].y += height * 0.5;
+ r_supports[0].y += height * 0.5 - radius;
r_supports[1] = n;
- r_supports[1].y -= height * 0.5;
+ r_supports[1].y -= height * 0.5 - radius;
} else {
- real_t h = (d > 0) ? height : -height;
+ real_t h = height * 0.5 - radius;
n *= radius;
- n.y += h * 0.5;
+ n.y += (d > 0) ? h : -h;
r_amount = 1;
*r_supports = n;
}
@@ -400,7 +360,7 @@ void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports
bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const {
Vector2 p = p_point;
p.y = Math::abs(p.y);
- p.y -= height * 0.5;
+ p.y -= height * 0.5 - radius;
if (p.y < 0) {
p.y = 0;
}
@@ -417,7 +377,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
for (int i = 0; i < 2; i++) {
Vector2 begin = p_begin;
Vector2 end = p_end;
- real_t ofs = (i == 0) ? -height * 0.5 : height * 0.5;
+ real_t ofs = (i == 0) ? -height * 0.5 + radius : height * 0.5 - radius;
begin.y += ofs;
end.y += ofs;
@@ -454,7 +414,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
}
Vector2 rpos, rnorm;
- if (Rect2(Point2(-radius, -height * 0.5), Size2(radius * 2.0, height)).intersects_segment(p_begin, p_end, &rpos, &rnorm)) {
+ if (Rect2(Point2(-radius, -height * 0.5 + radius), Size2(radius * 2.0, height - radius * 2)).intersects_segment(p_begin, p_end, &rpos, &rnorm)) {
real_t pd = n.dot(rpos);
if (pd < d) {
r_point = rpos;
@@ -469,7 +429,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
}
real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
- Vector2 he2 = Vector2(radius * 2, height + radius * 2) * p_scale;
+ Vector2 he2 = Vector2(radius * 2, height) * p_scale;
return p_mass * he2.dot(he2) / 12.0;
}
@@ -487,7 +447,7 @@ void CapsuleShape2DSW::set_data(const Variant &p_data) {
height = p.y;
}
- Point2 he(radius, height * 0.5 + radius);
+ Point2 he(radius, height * 0.5);
configure(Rect2(-he, he * 2));
}
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index ee2730ebb5..2de0f3cb9f 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -36,7 +36,7 @@
/*
-SHAPE_LINE, ///< plane:"plane"
+SHAPE_WORLD_MARGIN, ///< plane:"plane"
SHAPE_SEGMENT, ///< real_t:"length"
SHAPE_CIRCLE, ///< real_t:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
@@ -152,7 +152,7 @@ public:
r_max = MAX(maxa, maxb); \
}
-class LineShape2DSW : public Shape2DSW {
+class WorldMarginShape2DSW : public Shape2DSW {
Vector2 normal;
real_t d;
@@ -160,7 +160,7 @@ public:
_FORCE_INLINE_ Vector2 get_normal() const { return normal; }
_FORCE_INLINE_ real_t get_d() const { return d; }
- virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_LINE; }
+ virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_WORLD_MARGIN; }
virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); }
virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const;
@@ -189,41 +189,6 @@ public:
}
};
-class RayShape2DSW : public Shape2DSW {
- real_t length;
- bool slips_on_slope;
-
-public:
- _FORCE_INLINE_ real_t get_length() const { return length; }
- _FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; }
-
- virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; }
-
- virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); }
- virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const;
-
- virtual bool contains_point(const Vector2 &p_point) const;
- virtual bool intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const;
-
- virtual void set_data(const Variant &p_data);
- virtual Variant get_data() const;
-
- _FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
- //real large
- r_max = p_normal.dot(p_transform.get_origin());
- r_min = p_normal.dot(p_transform.xform(Vector2(0, length)));
- if (r_max < r_min) {
- SWAP(r_max, r_min);
- }
- }
-
- DEFAULT_PROJECT_RANGE_CAST
-
- _FORCE_INLINE_ RayShape2DSW() {}
- _FORCE_INLINE_ RayShape2DSW(real_t p_length) { length = p_length; }
-};
-
class SegmentShape2DSW : public Shape2DSW {
Vector2 a;
Vector2 b;
@@ -396,10 +361,10 @@ public:
_FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
Vector2 n = p_transform.basis_xform_inv(p_normal).normalized();
- real_t h = (n.y > 0) ? height : -height;
+ real_t h = height * 0.5 - radius;
n *= radius;
- n.y += h * 0.5;
+ n.y += (n.y > 0) ? h : -h;
r_max = p_normal.dot(p_transform.xform(n));
r_min = p_normal.dot(p_transform.xform(-n));
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 43329fed2f..f04f3ab583 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -508,7 +508,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject2DSW::TYPE_AREA) {
keep = false;
- } else if (!p_body->layer_in_mask(static_cast<Body2DSW *>(intersection_query_results[i]))) {
+ } else if (!p_body->collides_with(static_cast<Body2DSW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
@@ -528,188 +528,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
return amount;
}
-int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, PhysicsServer2D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
- Rect2 body_aabb;
-
- bool shapes_found = false;
-
- for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (p_body->is_shape_disabled(i)) {
- continue;
- }
-
- if (p_body->get_shape(i)->get_type() != PhysicsServer2D::SHAPE_RAY) {
- continue;
- }
-
- if (!shapes_found) {
- body_aabb = p_body->get_shape_aabb(i);
- shapes_found = true;
- } else {
- body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
- }
- }
-
- if (!shapes_found) {
- return 0;
- }
-
- // Undo the currently transform the physics server is aware of and apply the provided one
- body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_margin);
-
- Transform2D body_transform = p_transform;
-
- for (int i = 0; i < p_result_max; i++) {
- //reset results
- r_results[i].collision_depth = 0;
- }
-
- int rays_found = 0;
-
- {
- // raycast AND separate
-
- const int max_results = 32;
- int recover_attempts = 4;
- Vector2 sr[max_results * 2];
- PhysicsServer2DSW::CollCbkData cbk;
- cbk.max = max_results;
- PhysicsServer2DSW::CollCbkData *cbkptr = &cbk;
- CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk;
-
- do {
- Vector2 recover_motion;
-
- bool collided = false;
-
- int amount = _cull_aabb_for_body(p_body, body_aabb);
-
- for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_disabled(j)) {
- continue;
- }
-
- Shape2DSW *body_shape = p_body->get_shape(j);
-
- if (body_shape->get_type() != PhysicsServer2D::SHAPE_RAY) {
- continue;
- }
-
- Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
-
- for (int i = 0; i < amount; i++) {
- const CollisionObject2DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
-
- cbk.amount = 0;
- cbk.passed = 0;
- cbk.ptr = sr;
- cbk.invalid_by_dir = 0;
-
- if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
- }
-
- Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
-
- /*
- * There is no point in supporting one way collisions with ray shapes, as they will always collide in the desired
- * direction. Use a short ray shape if you want to achieve a similar effect.
- *
- if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
- cbk.valid_depth = p_margin; //only valid depth is the collision margin
- cbk.invalid_by_dir = 0;
-
- } else {
-*/
-
- cbk.valid_dir = Vector2();
- cbk.valid_depth = 0;
- cbk.invalid_by_dir = 0;
-
- /*
- }
- */
-
- Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_margin)) {
- if (cbk.amount > 0) {
- collided = true;
- }
-
- int ray_index = -1; //reuse shape
- for (int k = 0; k < rays_found; k++) {
- if (r_results[ray_index].collision_local_shape == j) {
- ray_index = k;
- }
- }
-
- if (ray_index == -1 && rays_found < p_result_max) {
- ray_index = rays_found;
- rays_found++;
- }
-
- if (ray_index != -1) {
- PhysicsServer2D::SeparationResult &result = r_results[ray_index];
-
- for (int k = 0; k < cbk.amount; k++) {
- Vector2 a = sr[k * 2 + 0];
- Vector2 b = sr[k * 2 + 1];
-
- recover_motion += (b - a) / cbk.amount;
-
- real_t depth = a.distance_to(b);
- if (depth > result.collision_depth) {
- result.collision_depth = depth;
- result.collision_point = b;
- result.collision_normal = (b - a).normalized();
- result.collision_local_shape = j;
- result.collider_shape = shape_idx;
- result.collider = col_obj->get_self();
- result.collider_id = col_obj->get_instance_id();
- result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
- if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
- Body2DSW *body = (Body2DSW *)col_obj;
-
- Vector2 rel_vec = b - body->get_transform().get_origin();
- result.collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
- }
- }
- }
- }
- }
- }
- }
-
- if (!collided || recover_motion == Vector2()) {
- break;
- }
-
- body_transform.elements[2] += recover_motion;
- body_aabb.position += recover_motion;
-
- recover_attempts--;
- } while (recover_attempts);
- }
-
- //optimize results (remove non colliding)
- for (int i = 0; i < rays_found; i++) {
- if (r_results[i].collision_depth == 0) {
- rays_found--;
- SWAP(r_results[i], r_results[rays_found]);
- }
- }
-
- r_recover_motion = body_transform.elements[2] - p_transform.elements[2];
- return rays_found;
-}
-
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, const Set<RID> &p_exclude) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -730,10 +549,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
continue;
}
- if (p_exclude_raycast_shapes && p_body->get_shape(i)->get_type() == PhysicsServer2D::SHAPE_RAY) {
- continue;
- }
-
if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
shapes_found = true;
@@ -745,7 +560,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (!shapes_found) {
if (r_result) {
*r_result = PhysicsServer2D::MotionResult();
- r_result->motion = p_motion;
+ r_result->travel = p_motion;
}
return false;
}
@@ -794,24 +609,15 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
Shape2DSW *body_shape = p_body->get_shape(j);
- if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer2D::SHAPE_RAY) {
- continue;
- }
-
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
+
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
if (p_exclude.has(col_obj->get_self())) {
continue;
}
- int shape_idx = intersection_query_subindex_results[i];
- if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
- }
+ int shape_idx = intersection_query_subindex_results[i];
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
@@ -920,10 +726,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
Shape2DSW *body_shape = p_body->get_shape(body_shape_idx);
- if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer2D::SHAPE_RAY) {
- continue;
- }
-
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx);
bool stuck = false;
@@ -939,13 +741,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int col_shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
- if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
- }
-
bool excluded = false;
for (int k = 0; k < excluded_shape_pair_count; k++) {
@@ -1082,10 +877,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
- if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer2D::SHAPE_RAY) {
- continue;
- }
-
body_aabb.position += p_motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
@@ -1095,14 +886,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (p_exclude.has(col_obj->get_self())) {
continue;
}
- int shape_idx = intersection_query_subindex_results[i];
- if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
- }
+ int shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
@@ -1169,9 +954,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Vector2 rel_vec = r_result->collision_point - body->get_transform().get_origin();
r_result->collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
- r_result->motion = safe * p_motion;
+ r_result->travel = safe * p_motion;
r_result->remainder = p_motion - safe * p_motion;
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_from.get_origin());
}
collided = true;
@@ -1179,9 +964,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
if (!collided && r_result) {
- r_result->motion = p_motion;
+ r_result->travel = p_motion;
r_result->remainder = Vector2();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_from.get_origin());
}
return collided;
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index f7224e4661..3be36852b0 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -183,8 +183,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>());
- int test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, PhysicsServer2D::SeparationResult *r_results, int p_result_max, real_t p_margin);
+ bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, const Set<RID> &p_exclude = Set<RID>());
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/area_3d_sw.cpp
index a9f5c4aec3..364f63e4ad 100644
--- a/servers/physics_3d/area_3d_sw.cpp
+++ b/servers/physics_3d/area_3d_sw.cpp
@@ -30,8 +30,16 @@
#include "area_3d_sw.h"
#include "body_3d_sw.h"
+#include "soft_body_3d_sw.h"
#include "space_3d_sw.h"
+Area3DSW::BodyKey::BodyKey(SoftBody3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+ rid = p_body->get_self();
+ instance_id = p_body->get_instance_id();
+ body_shape = p_body_shape;
+ area_shape = p_area_shape;
+}
+
Area3DSW::BodyKey::BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
rid = p_body->get_self();
instance_id = p_body->get_instance_id();
diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/area_3d_sw.h
index 12f7545c08..5959ee1e95 100644
--- a/servers/physics_3d/area_3d_sw.h
+++ b/servers/physics_3d/area_3d_sw.h
@@ -38,6 +38,7 @@
class Space3DSW;
class Body3DSW;
+class SoftBody3DSW;
class Constraint3DSW;
class Area3DSW : public CollisionObject3DSW {
@@ -80,6 +81,7 @@ class Area3DSW : public CollisionObject3DSW {
}
_FORCE_INLINE_ BodyKey() {}
+ BodyKey(SoftBody3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
};
@@ -91,6 +93,7 @@ class Area3DSW : public CollisionObject3DSW {
_FORCE_INLINE_ BodyState() { state = 0; }
};
+ Map<BodyKey, BodyState> monitored_soft_bodies;
Map<BodyKey, BodyState> monitored_bodies;
Map<BodyKey, BodyState> monitored_areas;
@@ -115,6 +118,9 @@ public:
_FORCE_INLINE_ void add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
_FORCE_INLINE_ void remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape);
+
_FORCE_INLINE_ void add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
_FORCE_INLINE_ void remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
@@ -166,6 +172,22 @@ public:
~Area3DSW();
};
+void Area3DSW::add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) {
+ BodyKey bk(p_soft_body, p_soft_body_shape, p_area_shape);
+ monitored_soft_bodies[bk].inc();
+ if (!monitor_query_list.in_list()) {
+ _queue_monitor_update();
+ }
+}
+
+void Area3DSW::remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) {
+ BodyKey bk(p_soft_body, p_soft_body_shape, p_area_shape);
+ monitored_soft_bodies[bk].dec();
+ if (!monitor_query_list.in_list()) {
+ _queue_monitor_update();
+ }
+}
+
void Area3DSW::add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_body, p_body_shape, p_area_shape);
monitored_bodies[bk].inc();
@@ -198,4 +220,16 @@ void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, u
}
}
+struct AreaCMP {
+ Area3DSW *area;
+ int refCount;
+ _FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); }
+ _FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); }
+ _FORCE_INLINE_ AreaCMP() {}
+ _FORCE_INLINE_ AreaCMP(Area3DSW *p_area) {
+ area = p_area;
+ refCount = 1;
+ }
+};
+
#endif // AREA__SW_H
diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/area_pair_3d_sw.cpp
index f43c2c965e..e740565da6 100644
--- a/servers/physics_3d/area_pair_3d_sw.cpp
+++ b/servers/physics_3d/area_pair_3d_sw.cpp
@@ -181,3 +181,85 @@ Area2Pair3DSW::~Area2Pair3DSW() {
area_a->remove_constraint(this);
area_b->remove_constraint(this);
}
+
+////////////////////////////////////////////////////
+
+bool AreaSoftBodyPair3DSW::setup(real_t p_step) {
+ bool result = false;
+ if (
+ area->interacts_with(soft_body) &&
+ CollisionSolver3DSW::solve_static(
+ soft_body->get_shape(soft_body_shape),
+ soft_body->get_transform() * soft_body->get_shape_transform(soft_body_shape),
+ area->get_shape(area_shape),
+ area->get_transform() * area->get_shape_transform(area_shape),
+ nullptr,
+ this)) {
+ result = true;
+ }
+
+ process_collision = false;
+ if (result != colliding) {
+ if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ process_collision = true;
+ } else if (area->has_monitor_callback()) {
+ process_collision = true;
+ }
+
+ colliding = result;
+ }
+
+ return process_collision;
+}
+
+bool AreaSoftBodyPair3DSW::pre_solve(real_t p_step) {
+ if (!process_collision) {
+ return false;
+ }
+
+ if (colliding) {
+ if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ soft_body->add_area(area);
+ }
+
+ if (area->has_monitor_callback()) {
+ area->add_soft_body_to_query(soft_body, soft_body_shape, area_shape);
+ }
+ } else {
+ if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ soft_body->remove_area(area);
+ }
+
+ if (area->has_monitor_callback()) {
+ area->remove_soft_body_from_query(soft_body, soft_body_shape, area_shape);
+ }
+ }
+
+ return false; // Never do any post solving.
+}
+
+void AreaSoftBodyPair3DSW::solve(real_t p_step) {
+ // Nothing to do.
+}
+
+AreaSoftBodyPair3DSW::AreaSoftBodyPair3DSW(SoftBody3DSW *p_soft_body, int p_soft_body_shape, Area3DSW *p_area, int p_area_shape) {
+ soft_body = p_soft_body;
+ area = p_area;
+ soft_body_shape = p_soft_body_shape;
+ area_shape = p_area_shape;
+ soft_body->add_constraint(this);
+ area->add_constraint(this);
+}
+
+AreaSoftBodyPair3DSW::~AreaSoftBodyPair3DSW() {
+ if (colliding) {
+ if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ soft_body->remove_area(area);
+ }
+ if (area->has_monitor_callback()) {
+ area->remove_soft_body_from_query(soft_body, soft_body_shape, area_shape);
+ }
+ }
+ soft_body->remove_constraint(this);
+ area->remove_constraint(this);
+}
diff --git a/servers/physics_3d/area_pair_3d_sw.h b/servers/physics_3d/area_pair_3d_sw.h
index 596d893082..8cc9e9ad63 100644
--- a/servers/physics_3d/area_pair_3d_sw.h
+++ b/servers/physics_3d/area_pair_3d_sw.h
@@ -34,6 +34,7 @@
#include "area_3d_sw.h"
#include "body_3d_sw.h"
#include "constraint_3d_sw.h"
+#include "soft_body_3d_sw.h"
class AreaPair3DSW : public Constraint3DSW {
Body3DSW *body;
@@ -69,4 +70,21 @@ public:
~Area2Pair3DSW();
};
+class AreaSoftBodyPair3DSW : public Constraint3DSW {
+ SoftBody3DSW *soft_body;
+ Area3DSW *area;
+ int soft_body_shape;
+ int area_shape;
+ bool colliding = false;
+ bool process_collision = false;
+
+public:
+ virtual bool setup(real_t p_step) override;
+ virtual bool pre_solve(real_t p_step) override;
+ virtual void solve(real_t p_step) override;
+
+ AreaSoftBodyPair3DSW(SoftBody3DSW *p_sof_body, int p_soft_body_shape, Area3DSW *p_area, int p_area_shape);
+ ~AreaSoftBodyPair3DSW();
+};
+
#endif // AREA_PAIR__SW_H
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index 0fa31c5037..efb114a325 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -96,18 +96,6 @@ class Body3DSW : public CollisionObject3DSW {
Map<Constraint3DSW *, int> constraint_map;
- struct AreaCMP {
- Area3DSW *area;
- int refCount;
- _FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); }
- _FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); }
- _FORCE_INLINE_ AreaCMP() {}
- _FORCE_INLINE_ AreaCMP(Area3DSW *p_area) {
- area = p_area;
- refCount = 1;
- }
- };
-
Vector<AreaCMP> areas;
struct Contact {
@@ -389,6 +377,8 @@ public:
virtual void set_transform(const Transform3D &p_transform) override { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); }
virtual Transform3D get_transform() const override { return body->get_transform(); }
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override { return body->get_velocity_in_local_point(p_position); }
+
virtual void add_central_force(const Vector3 &p_force) override { body->add_central_force(p_force); }
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {
body->add_force(p_force, p_position);
diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp
index af680f23db..c27a2ecced 100644
--- a/servers/physics_3d/body_pair_3d_sw.cpp
+++ b/servers/physics_3d/body_pair_3d_sw.cpp
@@ -212,16 +212,16 @@ real_t combine_friction(Body3DSW *A, Body3DSW *B) {
}
bool BodyPair3DSW::setup(real_t p_step) {
- dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
- dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
-
if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
}
+ collide_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) && A->collides_with(B);
+ collide_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) && B->collides_with(A);
+
report_contacts_only = false;
- if (!dynamic_A && !dynamic_B) {
+ if (!collide_A && !collide_B) {
if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) {
report_contacts_only = true;
} else {
@@ -250,11 +250,11 @@ bool BodyPair3DSW::setup(real_t p_step) {
if (!collided) {
//test ccd (currently just a raycast)
- if (A->is_continuous_collision_detection_enabled() && dynamic_A && !dynamic_B) {
+ if (A->is_continuous_collision_detection_enabled() && collide_A) {
_test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B);
}
- if (B->is_continuous_collision_detection_enabled() && dynamic_B && !dynamic_A) {
+ if (B->is_continuous_collision_detection_enabled() && collide_B) {
_test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A);
}
@@ -293,6 +293,15 @@ bool BodyPair3DSW::pre_solve(real_t p_step) {
const Basis &basis_A = A->get_transform().basis;
const Basis &basis_B = B->get_transform().basis;
+ Basis zero_basis;
+ zero_basis.set_zero();
+
+ const Basis &inv_inertia_tensor_A = collide_A ? A->get_inv_inertia_tensor() : zero_basis;
+ const Basis &inv_inertia_tensor_B = collide_B ? B->get_inv_inertia_tensor() : zero_basis;
+
+ real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0;
+ real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0;
+
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
c.active = false;
@@ -303,7 +312,7 @@ bool BodyPair3DSW::pre_solve(real_t p_step) {
Vector3 axis = global_A - global_B;
real_t depth = axis.dot(c.normal);
- if (depth <= 0) {
+ if (depth <= 0.0) {
continue;
}
@@ -339,9 +348,9 @@ bool BodyPair3DSW::pre_solve(real_t p_step) {
do_process = true;
// Precompute normal mass, tangent mass, and bias.
- Vector3 inertia_A = A->get_inv_inertia_tensor().xform(c.rA.cross(c.normal));
- Vector3 inertia_B = B->get_inv_inertia_tensor().xform(c.rB.cross(c.normal));
- real_t kNormal = A->get_inv_mass() + B->get_inv_mass();
+ Vector3 inertia_A = inv_inertia_tensor_A.xform(c.rA.cross(c.normal));
+ Vector3 inertia_B = inv_inertia_tensor_B.xform(c.rB.cross(c.normal));
+ real_t kNormal = inv_mass_A + inv_mass_B;
kNormal += c.normal.dot(inertia_A.cross(c.rA)) + c.normal.dot(inertia_B.cross(c.rB));
c.mass_normal = 1.0f / kNormal;
@@ -349,10 +358,10 @@ bool BodyPair3DSW::pre_solve(real_t p_step) {
c.depth = depth;
Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse;
- if (dynamic_A) {
+ if (collide_A) {
A->apply_impulse(-j_vec, c.rA + A->get_center_of_mass());
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_impulse(j_vec, c.rB + B->get_center_of_mass());
}
c.acc_bias_impulse = 0;
@@ -378,6 +387,15 @@ void BodyPair3DSW::solve(real_t p_step) {
const real_t max_bias_av = MAX_BIAS_ROTATION / p_step;
+ Basis zero_basis;
+ zero_basis.set_zero();
+
+ const Basis &inv_inertia_tensor_A = collide_A ? A->get_inv_inertia_tensor() : zero_basis;
+ const Basis &inv_inertia_tensor_B = collide_B ? B->get_inv_inertia_tensor() : zero_basis;
+
+ real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0;
+ real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0;
+
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
if (!c.active) {
@@ -401,10 +419,10 @@ void BodyPair3DSW::solve(real_t p_step) {
Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld);
- if (dynamic_A) {
+ if (collide_A) {
A->apply_bias_impulse(-jb, c.rA + A->get_center_of_mass(), max_bias_av);
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_bias_impulse(jb, c.rB + B->get_center_of_mass(), max_bias_av);
}
@@ -415,16 +433,16 @@ void BodyPair3DSW::solve(real_t p_step) {
vbn = dbv.dot(c.normal);
if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) {
- real_t jbn_com = (-vbn + c.bias) / (A->get_inv_mass() + B->get_inv_mass());
+ real_t jbn_com = (-vbn + c.bias) / (inv_mass_A + inv_mass_B);
real_t jbnOld_com = c.acc_bias_impulse_center_of_mass;
c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f);
Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com);
- if (dynamic_A) {
+ if (collide_A) {
A->apply_bias_impulse(-jb_com, A->get_center_of_mass(), 0.0f);
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_bias_impulse(jb_com, B->get_center_of_mass(), 0.0f);
}
}
@@ -446,10 +464,10 @@ void BodyPair3DSW::solve(real_t p_step) {
Vector3 j = c.normal * (c.acc_normal_impulse - jnOld);
- if (dynamic_A) {
+ if (collide_A) {
A->apply_impulse(-j, c.rA + A->get_center_of_mass());
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_impulse(j, c.rB + B->get_center_of_mass());
}
@@ -473,11 +491,11 @@ void BodyPair3DSW::solve(real_t p_step) {
if (tvl > MIN_VELOCITY) {
tv /= tvl;
- Vector3 temp1 = A->get_inv_inertia_tensor().xform(c.rA.cross(tv));
- Vector3 temp2 = B->get_inv_inertia_tensor().xform(c.rB.cross(tv));
+ Vector3 temp1 = inv_inertia_tensor_A.xform(c.rA.cross(tv));
+ Vector3 temp2 = inv_inertia_tensor_B.xform(c.rB.cross(tv));
real_t t = -tvl /
- (A->get_inv_mass() + B->get_inv_mass() + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB)));
+ (inv_mass_A + inv_mass_B + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB)));
Vector3 jt = t * tv;
@@ -493,10 +511,10 @@ void BodyPair3DSW::solve(real_t p_step) {
jt = c.acc_tangent_impulse - jtOld;
- if (dynamic_A) {
+ if (collide_A) {
A->apply_impulse(-jt, c.rA + A->get_center_of_mass());
}
- if (dynamic_B) {
+ if (collide_B) {
B->apply_impulse(jt, c.rB + B->get_center_of_mass());
}
@@ -595,13 +613,23 @@ void BodySoftBodyPair3DSW::validate_contacts() {
}
bool BodySoftBodyPair3DSW::setup(real_t p_step) {
- body_dynamic = (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
-
if (!body->interacts_with(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) {
collided = false;
return false;
}
+ body_collides = (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) && body->collides_with(soft_body);
+ soft_body_collides = soft_body->collides_with(body);
+
+ if (!body_collides && !soft_body_collides) {
+ if (body->get_max_contacts_reported() > 0) {
+ report_contacts_only = true;
+ } else {
+ collided = false;
+ return false;
+ }
+ }
+
const Transform3D &xform_Au = body->get_transform();
Transform3D xform_A = xform_Au * body->get_shape_transform(body_shape);
@@ -639,13 +667,20 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
const Transform3D &transform_A = body->get_transform();
+ Basis zero_basis;
+ zero_basis.set_zero();
+
+ const Basis &body_inv_inertia_tensor = body_collides ? body->get_inv_inertia_tensor() : zero_basis;
+
+ real_t body_inv_mass = body_collides ? body->get_inv_mass() : 0.0;
+
uint32_t contact_count = contacts.size();
for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
Contact &c = contacts[contact_index];
c.active = false;
- real_t node_inv_mass = soft_body->get_node_inv_mass(c.index_B);
- if (node_inv_mass == 0.0) {
+ real_t node_inv_mass = soft_body_collides ? soft_body->get_node_inv_mass(c.index_B) : 0.0;
+ if ((node_inv_mass == 0.0) && (body_inv_mass == 0.0)) {
continue;
}
@@ -654,15 +689,11 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
Vector3 axis = global_A - global_B;
real_t depth = axis.dot(c.normal);
- if (depth <= 0) {
+ if (depth <= 0.0) {
continue;
}
- c.active = true;
- do_process = true;
-
#ifdef DEBUG_ENABLED
-
if (space->is_debugging_contacts()) {
space->add_debug_contact(global_A);
space->add_debug_contact(global_B);
@@ -677,13 +708,21 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
body->add_contact(global_A, -c.normal, depth, body_shape, global_B, 0, soft_body->get_instance_id(), soft_body->get_self(), crA);
}
- if (body_dynamic) {
+ if (report_contacts_only) {
+ collided = false;
+ continue;
+ }
+
+ c.active = true;
+ do_process = true;
+
+ if (body_collides) {
body->set_active(true);
}
// Precompute normal mass, tangent mass, and bias.
- Vector3 inertia_A = body->get_inv_inertia_tensor().xform(c.rA.cross(c.normal));
- real_t kNormal = body->get_inv_mass() + node_inv_mass;
+ Vector3 inertia_A = body_inv_inertia_tensor.xform(c.rA.cross(c.normal));
+ real_t kNormal = body_inv_mass + node_inv_mass;
kNormal += c.normal.dot(inertia_A.cross(c.rA));
c.mass_normal = 1.0f / kNormal;
@@ -691,10 +730,12 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
c.depth = depth;
Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse;
- if (body_dynamic) {
+ if (body_collides) {
body->apply_impulse(-j_vec, c.rA + body->get_center_of_mass());
}
- soft_body->apply_node_impulse(c.index_B, j_vec);
+ if (soft_body_collides) {
+ soft_body->apply_node_impulse(c.index_B, j_vec);
+ }
c.acc_bias_impulse = 0;
c.acc_bias_impulse_center_of_mass = 0;
@@ -719,6 +760,13 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
const real_t max_bias_av = MAX_BIAS_ROTATION / p_step;
+ Basis zero_basis;
+ zero_basis.set_zero();
+
+ const Basis &body_inv_inertia_tensor = body_collides ? body->get_inv_inertia_tensor() : zero_basis;
+
+ real_t body_inv_mass = body_collides ? body->get_inv_mass() : 0.0;
+
uint32_t contact_count = contacts.size();
for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
Contact &c = contacts[contact_index];
@@ -728,6 +776,8 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
c.active = false;
+ real_t node_inv_mass = soft_body_collides ? soft_body->get_node_inv_mass(c.index_B) : 0.0;
+
// Bias impulse.
Vector3 crbA = body->get_biased_angular_velocity().cross(c.rA);
Vector3 dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA;
@@ -741,10 +791,12 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld);
- if (body_dynamic) {
+ if (body_collides) {
body->apply_bias_impulse(-jb, c.rA + body->get_center_of_mass(), max_bias_av);
}
- soft_body->apply_node_bias_impulse(c.index_B, jb);
+ if (soft_body_collides) {
+ soft_body->apply_node_bias_impulse(c.index_B, jb);
+ }
crbA = body->get_biased_angular_velocity().cross(c.rA);
dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA;
@@ -752,16 +804,18 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
vbn = dbv.dot(c.normal);
if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) {
- real_t jbn_com = (-vbn + c.bias) / (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B));
+ real_t jbn_com = (-vbn + c.bias) / (body_inv_mass + node_inv_mass);
real_t jbnOld_com = c.acc_bias_impulse_center_of_mass;
c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f);
Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com);
- if (body_dynamic) {
+ if (body_collides) {
body->apply_bias_impulse(-jb_com, body->get_center_of_mass(), 0.0f);
}
- soft_body->apply_node_bias_impulse(c.index_B, jb_com);
+ if (soft_body_collides) {
+ soft_body->apply_node_bias_impulse(c.index_B, jb_com);
+ }
}
c.active = true;
@@ -780,10 +834,12 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
Vector3 j = c.normal * (c.acc_normal_impulse - jnOld);
- if (body_dynamic) {
+ if (body_collides) {
body->apply_impulse(-j, c.rA + body->get_center_of_mass());
}
- soft_body->apply_node_impulse(c.index_B, j);
+ if (soft_body_collides) {
+ soft_body->apply_node_impulse(c.index_B, j);
+ }
c.active = true;
}
@@ -804,10 +860,10 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
if (tvl > MIN_VELOCITY) {
tv /= tvl;
- Vector3 temp1 = body->get_inv_inertia_tensor().xform(c.rA.cross(tv));
+ Vector3 temp1 = body_inv_inertia_tensor.xform(c.rA.cross(tv));
real_t t = -tvl /
- (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B) + tv.dot(temp1.cross(c.rA)));
+ (body_inv_mass + node_inv_mass + tv.dot(temp1.cross(c.rA)));
Vector3 jt = t * tv;
@@ -823,10 +879,12 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
jt = c.acc_tangent_impulse - jtOld;
- if (body_dynamic) {
+ if (body_collides) {
body->apply_impulse(-jt, c.rA + body->get_center_of_mass());
}
- soft_body->apply_node_impulse(c.index_B, jt);
+ if (soft_body_collides) {
+ soft_body->apply_node_impulse(c.index_B, jt);
+ }
c.active = true;
}
diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h
index 976982d1f1..19d6a46880 100644
--- a/servers/physics_3d/body_pair_3d_sw.h
+++ b/servers/physics_3d/body_pair_3d_sw.h
@@ -83,8 +83,8 @@ class BodyPair3DSW : public BodyContact3DSW {
int shape_A = 0;
int shape_B = 0;
- bool dynamic_A = false;
- bool dynamic_B = false;
+ bool collide_A = false;
+ bool collide_B = false;
bool report_contacts_only = false;
@@ -115,7 +115,10 @@ class BodySoftBodyPair3DSW : public BodyContact3DSW {
int body_shape = 0;
- bool body_dynamic = false;
+ bool body_collides = false;
+ bool soft_body_collides = false;
+
+ bool report_contacts_only = false;
LocalVector<Contact> contacts;
diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h
index fb8dca8bb4..6ffab54645 100644
--- a/servers/physics_3d/collision_object_3d_sw.h
+++ b/servers/physics_3d/collision_object_3d_sw.h
@@ -166,8 +166,8 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
- _FORCE_INLINE_ bool layer_in_mask(CollisionObject3DSW *p_other) const {
- return collision_layer & p_other->collision_mask;
+ _FORCE_INLINE_ bool collides_with(CollisionObject3DSW *p_other) const {
+ return p_other->collision_layer & collision_mask;
}
_FORCE_INLINE_ bool interacts_with(CollisionObject3DSW *p_other) const {
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index 6a7f2b73c5..6e6a2cb9e7 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -848,7 +848,7 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p
//capsule sphere 1, sphere
- Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Vector3 capsule_ball_1 = p_transform_b.origin + capsule_axis;
@@ -956,9 +956,12 @@ static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transfo
const Vector3 *vertices = mesh.vertices.ptr();
int vertex_count = mesh.vertices.size();
+ // Precalculating this makes the transforms faster.
+ Basis b_xform_normal = p_transform_b.basis.inverse().transposed();
+
// faces of B
for (int i = 0; i < face_count; i++) {
- Vector3 axis = p_transform_b.xform(faces[i].plane).normal;
+ Vector3 axis = b_xform_normal.xform(faces[i].plane.normal).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1204,7 +1207,7 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_tr
// capsule balls, edges of A
for (int i = 0; i < 2; i++) {
- Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Vector3 sphere_pos = p_transform_b.origin + ((i == 0) ? capsule_axis : -capsule_axis);
@@ -1379,9 +1382,12 @@ static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform3
}
}
+ // Precalculating this makes the transforms faster.
+ Basis b_xform_normal = p_transform_b.basis.inverse().transposed();
+
// faces of B
for (int i = 0; i < face_count; i++) {
- Vector3 axis = p_transform_b.xform(faces[i].plane).normal;
+ Vector3 axis = b_xform_normal.xform(faces[i].plane.normal).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1601,8 +1607,8 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D &
// some values
- Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5);
- Vector3 capsule_B_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5);
+ Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
+ Vector3 capsule_B_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis;
Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis;
@@ -1673,8 +1679,8 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D
Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1);
- Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5);
- Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
+ Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
if (!separator.test_axis((p_transform_b.origin - capsule_A_ball_1).cross(cylinder_B_axis).cross(cylinder_B_axis).normalized())) {
return;
@@ -1733,9 +1739,12 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
int edge_count = mesh.edges.size();
const Vector3 *vertices = mesh.vertices.ptr();
+ // Precalculating this makes the transforms faster.
+ Basis b_xform_normal = p_transform_b.basis.inverse().transposed();
+
// faces of B
for (int i = 0; i < face_count; i++) {
- Vector3 axis = p_transform_b.xform(faces[i].plane).normal;
+ Vector3 axis = b_xform_normal.xform(faces[i].plane.normal).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1759,7 +1768,7 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
for (int i = 0; i < 2; i++) {
// edges of B, capsule cylinder
- Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis);
@@ -1799,7 +1808,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
// edges of B, capsule cylinder
- Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
for (int i = 0; i < 3; i++) {
// edge-cylinder
@@ -2057,20 +2066,24 @@ static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const
const Vector3 *vertices_B = mesh_B.vertices.ptr();
int vertex_count_B = mesh_B.vertices.size();
+ // Precalculating this makes the transforms faster.
+ Basis a_xform_normal = p_transform_b.basis.inverse().transposed();
+
// faces of A
for (int i = 0; i < face_count_A; i++) {
- Vector3 axis = p_transform_a.xform(faces_A[i].plane).normal;
- //Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized();
+ Vector3 axis = a_xform_normal.xform(faces_A[i].plane.normal).normalized();
if (!separator.test_axis(axis)) {
return;
}
}
+ // Precalculating this makes the transforms faster.
+ Basis b_xform_normal = p_transform_b.basis.inverse().transposed();
+
// faces of B
for (int i = 0; i < face_count_B; i++) {
- Vector3 axis = p_transform_b.xform(faces_B[i].plane).normal;
- //Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized();
+ Vector3 axis = b_xform_normal.xform(faces_B[i].plane.normal).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -2260,13 +2273,11 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_
PhysicsServer3D::ShapeType type_A = p_shape_A->get_type();
ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_PLANE, false);
- ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_RAY, false);
ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
PhysicsServer3D::ShapeType type_B = p_shape_B->get_type();
ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_PLANE, false);
- ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_RAY, false);
ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
static const CollisionFunc collision_table[6][6] = {
@@ -2371,10 +2382,10 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_
CollisionFunc collision_func;
if (margin_A != 0.0 || margin_B != 0.0) {
- collision_func = collision_table_margin[type_A - 2][type_B - 2];
+ collision_func = collision_table_margin[type_A - 1][type_B - 1];
} else {
- collision_func = collision_table[type_A - 2][type_B - 2];
+ collision_func = collision_table[type_A - 1][type_B - 1];
}
ERR_FAIL_COND_V(!collision_func, false);
diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp
index 67330d497e..dcecac1c73 100644
--- a/servers/physics_3d/collision_solver_3d_sw.cpp
+++ b/servers/physics_3d/collision_solver_3d_sw.cpp
@@ -89,39 +89,6 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T
return found;
}
-bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const RayShape3DSW *ray = static_cast<const RayShape3DSW *>(p_shape_A);
-
- Vector3 from = p_transform_A.origin;
- Vector3 to = from + p_transform_A.basis.get_axis(2) * ray->get_length();
- Vector3 support_A = to;
-
- Transform3D ai = p_transform_B.affine_inverse();
-
- from = ai.xform(from);
- to = ai.xform(to);
-
- Vector3 p, n;
- if (!p_shape_B->intersect_segment(from, to, p, n)) {
- return false;
- }
-
- Vector3 support_B = p_transform_B.xform(p);
- if (ray->get_slips_on_slope()) {
- Vector3 global_n = ai.basis.xform_inv(n).normalized();
- support_B = support_A + (support_B - support_A).length() * global_n;
- }
-
- if (p_result_callback) {
- if (p_swap_result) {
- p_result_callback(support_B, 0, support_A, 0, p_userdata);
- } else {
- p_result_callback(support_A, 0, support_B, 0, p_userdata);
- }
- }
- return true;
-}
-
struct _SoftBodyContactCollisionInfo {
int node_index = 0;
CollisionSolver3DSW::CallbackResult result_callback = nullptr;
@@ -135,6 +102,10 @@ void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, i
++cinfo.contact_count;
+ if (!cinfo.result_callback) {
+ return;
+ }
+
if (cinfo.swap_result) {
cinfo.result_callback(p_point_B, cinfo.node_index, p_point_A, p_index_A, cinfo.userdata);
} else {
@@ -347,9 +318,6 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
if (type_B == PhysicsServer3D::SHAPE_PLANE) {
return false;
}
- if (type_B == PhysicsServer3D::SHAPE_RAY) {
- return false;
- }
if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
return false;
}
@@ -360,17 +328,6 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
return solve_static_plane(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
}
- } else if (type_A == PhysicsServer3D::SHAPE_RAY) {
- if (type_B == PhysicsServer3D::SHAPE_RAY) {
- return false;
- }
-
- if (swap) {
- return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
- } else {
- return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
- }
-
} else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
if (type_A == PhysicsServer3D::SHAPE_SOFT_BODY) {
// Soft Body / Soft Body not supported.
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index c1a9d6259d..fbb374bd74 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -48,12 +48,6 @@ RID PhysicsServer3DSW::plane_shape_create() {
shape->set_self(rid);
return rid;
}
-RID PhysicsServer3DSW::ray_shape_create() {
- Shape3DSW *shape = memnew(RayShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
RID PhysicsServer3DSW::sphere_shape_create() {
Shape3DSW *shape = memnew(SphereShape3DSW);
RID rid = shape_owner.make_rid(shape);
@@ -854,18 +848,7 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
body->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) {
- Body3DSW *body = body_owner.getornull(p_body);
- ERR_FAIL_COND_V(!body, false);
- ERR_FAIL_COND_V(!body->get_space(), false);
- ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
-
- _update_shapes();
-
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
-}
-
-int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
+bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, MotionResult *r_result, const Set<RID> &p_exclude) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -873,7 +856,7 @@ int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform3D &p
_update_shapes();
- return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_exclude);
}
PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 0ccd15fbb2..6e59a77e89 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -83,7 +83,6 @@ public:
static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
virtual RID plane_shape_create() override;
- virtual RID ray_shape_create() override;
virtual RID sphere_shape_create() override;
virtual RID box_shape_create() override;
virtual RID capsule_shape_create() override;
@@ -242,8 +241,7 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
index 9beec22bcd..75174628bf 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -79,7 +79,6 @@ public:
//FUNC1RID(shape,ShapeType); todo fix
FUNCRID(plane_shape)
- FUNCRID(ray_shape)
FUNCRID(sphere_shape)
FUNCRID(box_shape)
FUNCRID(capsule_shape)
@@ -250,14 +249,9 @@ public:
FUNC2(body_set_ray_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
+ bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
- }
-
- int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
- ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
+ return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_exclude);
}
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index 04a174f9c8..a84405de81 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -164,91 +164,6 @@ Variant PlaneShape3DSW::get_data() const {
PlaneShape3DSW::PlaneShape3DSW() {
}
-//
-
-real_t RayShape3DSW::get_length() const {
- return length;
-}
-
-bool RayShape3DSW::get_slips_on_slope() const {
- return slips_on_slope;
-}
-
-void RayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
- // don't think this will be even used
- r_min = 0;
- r_max = 1;
-}
-
-Vector3 RayShape3DSW::get_support(const Vector3 &p_normal) const {
- if (p_normal.z > 0) {
- return Vector3(0, 0, length);
- } else {
- return Vector3(0, 0, 0);
- }
-}
-
-void RayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
- if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
- r_amount = 2;
- r_type = FEATURE_EDGE;
- r_supports[0] = Vector3(0, 0, 0);
- r_supports[1] = Vector3(0, 0, length);
- } else if (p_normal.z > 0) {
- r_amount = 1;
- r_type = FEATURE_POINT;
- *r_supports = Vector3(0, 0, length);
- } else {
- r_amount = 1;
- r_type = FEATURE_POINT;
- *r_supports = Vector3(0, 0, 0);
- }
-}
-
-bool RayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
- return false; //simply not possible
-}
-
-bool RayShape3DSW::intersect_point(const Vector3 &p_point) const {
- return false; //simply not possible
-}
-
-Vector3 RayShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
- Vector3 s[2] = {
- Vector3(0, 0, 0),
- Vector3(0, 0, length)
- };
-
- return Geometry3D::get_closest_point_to_segment(p_point, s);
-}
-
-Vector3 RayShape3DSW::get_moment_of_inertia(real_t p_mass) const {
- return Vector3();
-}
-
-void RayShape3DSW::_setup(real_t p_length, bool p_slips_on_slope) {
- length = p_length;
- slips_on_slope = p_slips_on_slope;
- configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length)));
-}
-
-void RayShape3DSW::set_data(const Variant &p_data) {
- Dictionary d = p_data;
- _setup(d["length"], d["slips_on_slope"]);
-}
-
-Variant RayShape3DSW::get_data() const {
- Dictionary d;
- d["length"] = length;
- d["slips_on_slope"] = slips_on_slope;
- return d;
-}
-
-RayShape3DSW::RayShape3DSW() {
- length = 1;
- slips_on_slope = false;
-}
-
/********** SPHERE *************/
real_t SphereShape3DSW::get_radius() const {
@@ -509,10 +424,10 @@ BoxShape3DSW::BoxShape3DSW() {
void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 n = p_transform.basis.xform_inv(p_normal).normalized();
- real_t h = (n.y > 0) ? height : -height;
+ real_t h = height * 0.5 - radius;
n *= radius;
- n.y += h * 0.5;
+ n.y += (n.y > 0) ? h : -h;
r_max = p_normal.dot(p_transform.xform(n));
r_min = p_normal.dot(p_transform.xform(-n));
@@ -521,10 +436,10 @@ void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D
Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const {
Vector3 n = p_normal;
- real_t h = (n.y > 0) ? height : -height;
+ real_t h = height * 0.5 - radius;
n *= radius;
- n.y += h * 0.5;
+ n.y += (n.y > 0) ? h : -h;
return n;
}
@@ -542,15 +457,15 @@ void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3
r_amount = 2;
r_type = FEATURE_EDGE;
r_supports[0] = n;
- r_supports[0].y += height * 0.5;
+ r_supports[0].y += height * 0.5 - radius;
r_supports[1] = n;
- r_supports[1].y -= height * 0.5;
+ r_supports[1].y -= height * 0.5 - radius;
} else {
- real_t h = (d > 0) ? height : -height;
+ real_t h = height * 0.5 - radius;
n *= radius;
- n.y += h * 0.5;
+ n.y += (d > 0) ? h : -h;
r_amount = 1;
r_type = FEATURE_POINT;
*r_supports = n;
@@ -569,7 +484,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
// test against cylinder and spheres :-|
- collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn, 1);
+ collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height - radius * 2.0, radius, &auxres, &auxn, 1);
if (collided) {
real_t d = norm.dot(auxres);
@@ -581,7 +496,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
}
}
- collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * 0.5, 0), radius, &auxres, &auxn);
+ collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * 0.5 - radius, 0), radius, &auxres, &auxn);
if (collided) {
real_t d = norm.dot(auxres);
@@ -593,7 +508,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
}
}
- collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * -0.5, 0), radius, &auxres, &auxn);
+ collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * -0.5 + radius, 0), radius, &auxres, &auxn);
if (collided) {
real_t d = norm.dot(auxres);
@@ -614,19 +529,19 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
}
bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const {
- if (Math::abs(p_point.y) < height * 0.5) {
+ if (Math::abs(p_point.y) < height * 0.5 - radius) {
return Vector3(p_point.x, 0, p_point.z).length() < radius;
} else {
Vector3 p = p_point;
- p.y = Math::abs(p.y) - height * 0.5;
+ p.y = Math::abs(p.y) - height * 0.5 + radius;
return p.length() < radius;
}
}
Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
Vector3 s[2] = {
- Vector3(0, -height * 0.5, 0),
- Vector3(0, height * 0.5, 0),
+ Vector3(0, -height * 0.5 + radius, 0),
+ Vector3(0, height * 0.5 - radius, 0),
};
Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, s);
@@ -651,7 +566,7 @@ Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const {
void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) {
height = p_height;
radius = p_radius;
- configure(AABB(Vector3(-radius, -height * 0.5 - radius, -radius), Vector3(radius * 2, height + radius * 2.0, radius * 2)));
+ configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2, height, radius * 2)));
}
void CapsuleShape3DSW::set_data(const Variant &p_data) {
@@ -1635,7 +1550,7 @@ ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() {
/* HEIGHT MAP SHAPE */
-Vector<float> HeightMapShape3DSW::get_heights() const {
+Vector<real_t> HeightMapShape3DSW::get_heights() const {
return heights;
}
@@ -1932,7 +1847,7 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-void HeightMapShape3DSW::_setup(const Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
+void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
heights = p_heights;
width = p_width;
depth = p_depth;
@@ -1966,8 +1881,12 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) {
ERR_FAIL_COND(depth <= 0.0);
Variant heights_variant = d["heights"];
- Vector<float> heights_buffer;
+ Vector<real_t> heights_buffer;
+#ifdef REAL_T_IS_DOUBLE
+ if (heights_variant.get_type() == Variant::PACKED_FLOAT64_ARRAY) {
+#else
if (heights_variant.get_type() == Variant::PACKED_FLOAT32_ARRAY) {
+#endif
// Ready-to-use heights can be passed.
heights_buffer = heights_variant;
} else if (heights_variant.get_type() == Variant::OBJECT) {
@@ -1980,13 +1899,17 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) {
PackedByteArray im_data = image->get_data();
heights_buffer.resize(image->get_width() * image->get_height());
- float *w = heights_buffer.ptrw();
- float *rp = (float *)im_data.ptr();
+ real_t *w = heights_buffer.ptrw();
+ real_t *rp = (real_t *)im_data.ptr();
for (int i = 0; i < heights_buffer.size(); ++i) {
w[i] = rp[i];
}
} else {
+#ifdef REAL_T_IS_DOUBLE
+ ERR_FAIL_MSG("Expected PackedFloat64Array or float Image.");
+#else
ERR_FAIL_MSG("Expected PackedFloat32Array or float Image.");
+#endif
}
// Compute min and max heights or use precomputed values.
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h
index 0d1b7cc3d7..c11c3a08f6 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/shape_3d_sw.h
@@ -145,34 +145,6 @@ public:
PlaneShape3DSW();
};
-class RayShape3DSW : public Shape3DSW {
- real_t length;
- bool slips_on_slope;
-
- void _setup(real_t p_length, bool p_slips_on_slope);
-
-public:
- real_t get_length() const;
- bool get_slips_on_slope() const;
-
- virtual real_t get_area() const { return 0.0; }
- virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; }
- virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
- virtual Vector3 get_support(const Vector3 &p_normal) const;
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const;
-
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
- virtual bool intersect_point(const Vector3 &p_point) const;
- virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
-
- virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
-
- virtual void set_data(const Variant &p_data);
- virtual Variant get_data() const;
-
- RayShape3DSW();
-};
-
class SphereShape3DSW : public Shape3DSW {
real_t radius;
@@ -235,7 +207,7 @@ public:
_FORCE_INLINE_ real_t get_height() const { return height; }
_FORCE_INLINE_ real_t get_radius() const { return radius; }
- virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; }
+ virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; }
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CAPSULE; }
@@ -389,12 +361,12 @@ public:
};
struct HeightMapShape3DSW : public ConcaveShape3DSW {
- Vector<float> heights;
+ Vector<real_t> heights;
int width = 0;
int depth = 0;
Vector3 local_origin;
- _FORCE_INLINE_ float _get_height(int p_x, int p_z) const {
+ _FORCE_INLINE_ real_t _get_height(int p_x, int p_z) const {
return heights[(p_z * width) + p_x];
}
@@ -406,10 +378,10 @@ struct HeightMapShape3DSW : public ConcaveShape3DSW {
void _get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const;
- void _setup(const Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
+ void _setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
public:
- Vector<float> get_heights() const;
+ Vector<real_t> get_heights() const;
int get_width() const;
int get_depth() const;
diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/soft_body_3d_sw.cpp
index 724125bea8..73b81444e1 100644
--- a/servers/physics_3d/soft_body_3d_sw.cpp
+++ b/servers/physics_3d/soft_body_3d_sw.cpp
@@ -928,6 +928,19 @@ void SoftBody3DSW::apply_forces() {
}
}
+void SoftBody3DSW::_compute_area_gravity(const Area3DSW *p_area) {
+ if (p_area->is_gravity_point()) {
+ if (p_area->get_gravity_distance_scale() > 0) {
+ Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin();
+ gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale() + 1, 2));
+ } else {
+ gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
+ }
+ } else {
+ gravity += p_area->get_gravity_vector() * p_area->get_gravity();
+ }
+}
+
void SoftBody3DSW::predict_motion(real_t p_delta) {
const real_t inv_delta = 1.0 / p_delta;
@@ -935,9 +948,35 @@ void SoftBody3DSW::predict_motion(real_t p_delta) {
Area3DSW *def_area = get_space()->get_default_area();
ERR_FAIL_COND(!def_area);
+ gravity = def_area->get_gravity_vector() * def_area->get_gravity();
+
+ int ac = areas.size();
+ bool stopped = false;
+
+ if (ac) {
+ areas.sort();
+ const AreaCMP *aa = &areas[0];
+ for (int i = ac - 1; i >= 0 && !stopped; i--) {
+ PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
+ switch (mode) {
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ _compute_area_gravity(aa[i].area);
+ stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ gravity = Vector3(0, 0, 0);
+ _compute_area_gravity(aa[i].area);
+ stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
+ }
+ }
// Apply forces.
- Vector3 gravity = def_area->get_gravity_vector() * def_area->get_gravity();
add_velocity(gravity * p_delta);
apply_forces();
diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/soft_body_3d_sw.h
index ac8bcbf0b9..be0620c506 100644
--- a/servers/physics_3d/soft_body_3d_sw.h
+++ b/servers/physics_3d/soft_body_3d_sw.h
@@ -31,6 +31,7 @@
#ifndef SOFT_BODY_3D_SW_H
#define SOFT_BODY_3D_SW_H
+#include "area_3d_sw.h"
#include "collision_object_3d_sw.h"
#include "core/math/aabb.h"
@@ -100,14 +101,20 @@ class SoftBody3DSW : public CollisionObject3DSW {
real_t drag_coefficient = 0.0; // [0,1]
LocalVector<int> pinned_vertices;
+ Vector3 gravity;
+
SelfList<SoftBody3DSW> active_list;
Set<Constraint3DSW *> constraints;
+ Vector<AreaCMP> areas;
+
VSet<RID> exceptions;
uint64_t island_step = 0;
+ _FORCE_INLINE_ void _compute_area_gravity(const Area3DSW *p_area);
+
public:
SoftBody3DSW();
@@ -129,6 +136,25 @@ public:
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }
+ _FORCE_INLINE_ void add_area(Area3DSW *p_area) {
+ int index = areas.find(AreaCMP(p_area));
+ if (index > -1) {
+ areas.write[index].refCount += 1;
+ } else {
+ areas.ordered_insert(AreaCMP(p_area));
+ }
+ }
+
+ _FORCE_INLINE_ void remove_area(Area3DSW *p_area) {
+ int index = areas.find(AreaCMP(p_area));
+ if (index > -1) {
+ areas.write[index].refCount -= 1;
+ if (areas[index].refCount < 1) {
+ areas.remove(index);
+ }
+ }
+ }
+
virtual void set_space(Space3DSW *p_space);
void set_mesh(const Ref<Mesh> &p_mesh);
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index bc149648d7..f9e55ad525 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -549,7 +549,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) {
keep = false;
- } else if (!p_body->layer_in_mask(static_cast<Body3DSW *>(intersection_query_results[i]))) {
+ } else if (!p_body->collides_with(static_cast<Body3DSW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
@@ -569,158 +569,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
return amount;
}
-int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
- AABB body_aabb;
-
- bool shapes_found = false;
-
- for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (p_body->is_shape_disabled(i)) {
- continue;
- }
-
- if (!shapes_found) {
- body_aabb = p_body->get_shape_aabb(i);
- shapes_found = true;
- } else {
- body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
- }
- }
-
- if (!shapes_found) {
- return 0;
- }
- // Undo the currently transform the physics server is aware of and apply the provided one
- body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_margin);
-
- Transform3D body_transform = p_transform;
-
- for (int i = 0; i < p_result_max; i++) {
- //reset results
- r_results[i].collision_depth = 0;
- }
-
- int rays_found = 0;
-
- {
- // raycast AND separate
-
- const int max_results = 32;
- int recover_attempts = 4;
- Vector3 sr[max_results * 2];
- PhysicsServer3DSW::CollCbkData cbk;
- cbk.max = max_results;
- PhysicsServer3DSW::CollCbkData *cbkptr = &cbk;
- CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk;
-
- do {
- Vector3 recover_motion;
-
- bool collided = false;
-
- int amount = _cull_aabb_for_body(p_body, body_aabb);
-
- for (int j = 0; j < p_body->get_shape_count(); j++) {
- if (p_body->is_shape_disabled(j)) {
- continue;
- }
-
- Shape3DSW *body_shape = p_body->get_shape(j);
-
- if (body_shape->get_type() != PhysicsServer3D::SHAPE_RAY) {
- continue;
- }
-
- Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
-
- for (int i = 0; i < amount; i++) {
- const CollisionObject3DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
-
- cbk.amount = 0;
- cbk.ptr = sr;
-
- if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
- const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
- }
-
- Shape3DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
- if (cbk.amount > 0) {
- collided = true;
- }
-
- int ray_index = -1; //reuse shape
- for (int k = 0; k < rays_found; k++) {
- if (r_results[k].collision_local_shape == j) {
- ray_index = k;
- }
- }
-
- if (ray_index == -1 && rays_found < p_result_max) {
- ray_index = rays_found;
- rays_found++;
- }
-
- if (ray_index != -1) {
- PhysicsServer3D::SeparationResult &result = r_results[ray_index];
-
- for (int k = 0; k < cbk.amount; k++) {
- Vector3 a = sr[k * 2 + 0];
- Vector3 b = sr[k * 2 + 1];
-
- recover_motion += (b - a) / cbk.amount;
-
- real_t depth = a.distance_to(b);
- if (depth > result.collision_depth) {
- result.collision_depth = depth;
- result.collision_point = b;
- result.collision_normal = (b - a).normalized();
- result.collision_local_shape = j;
- result.collider = col_obj->get_self();
- result.collider_id = col_obj->get_instance_id();
- result.collider_shape = shape_idx;
- //result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
- if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) {
- Body3DSW *body = (Body3DSW *)col_obj;
- Vector3 rel_vec = b - (body->get_transform().origin + body->get_center_of_mass());
- result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
- }
- }
- }
- }
- }
- }
- }
-
- if (!collided || recover_motion == Vector3()) {
- break;
- }
-
- body_transform.origin += recover_motion;
- body_aabb.position += recover_motion;
-
- recover_attempts--;
- } while (recover_attempts);
- }
-
- //optimize results (remove non colliding)
- for (int i = 0; i < rays_found; i++) {
- if (r_results[i].collision_depth == 0) {
- rays_found--;
- SWAP(r_results[i], r_results[rays_found]);
- }
- }
-
- r_recover_motion = body_transform.origin - p_transform.origin;
- return rays_found;
-}
-
-bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, const Set<RID> &p_exclude) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -751,7 +600,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
if (!shapes_found) {
if (r_result) {
*r_result = PhysicsServer3D::MotionResult();
- r_result->motion = p_motion;
+ r_result->travel = p_motion;
}
return false;
@@ -795,21 +644,15 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
- if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
- continue;
- }
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
-
- if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
- const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
}
+ int shape_idx = intersection_query_subindex_results[i];
+
if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
collided = cbk.amount > 0;
}
@@ -874,10 +717,6 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
- if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
- continue;
- }
-
Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse();
MotionShape3DSW mshape;
mshape.shape = body_shape;
@@ -890,15 +729,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
-
- if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
- const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
}
+ int shape_idx = intersection_query_subindex_results[i];
+
//test initial overlap, does it collide if going all the way?
Vector3 point_A, point_B;
Vector3 sep_axis = motion_normal;
@@ -1005,24 +841,16 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
- if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) {
- continue;
- }
-
body_aabb.position += p_motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
-
- if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
- const Body3DSW *b = static_cast<const Body3DSW *>(col_obj);
- if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
- }
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
}
+ int shape_idx = intersection_query_subindex_results[i];
rcd.object = col_obj;
rcd.shape = shape_idx;
@@ -1051,9 +879,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass());
r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
- r_result->motion = safe * p_motion;
+ r_result->travel = safe * p_motion;
r_result->remainder = p_motion - safe * p_motion;
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_from.get_origin());
}
collided = true;
@@ -1061,9 +889,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
}
if (!collided && r_result) {
- r_result->motion = p_motion;
+ r_result->travel = p_motion;
r_result->remainder = Vector3();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_from.get_origin());
}
return collided;
@@ -1093,7 +921,9 @@ void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, Coll
Area2Pair3DSW *area2_pair = memnew(Area2Pair3DSW(area_b, p_subindex_B, area, p_subindex_A));
return area2_pair;
} else if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) {
- // Area/Soft Body, not supported.
+ SoftBody3DSW *softbody = static_cast<SoftBody3DSW *>(B);
+ AreaSoftBodyPair3DSW *soft_area_pair = memnew(AreaSoftBodyPair3DSW(softbody, p_subindex_B, area, p_subindex_A));
+ return soft_area_pair;
} else {
Body3DSW *body = static_cast<Body3DSW *>(B);
AreaPair3DSW *area_pair = memnew(AreaPair3DSW(body, p_subindex_B, area, p_subindex_A));
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
index 18e93c90cc..9b5b4de069 100644
--- a/servers/physics_3d/space_3d_sw.h
+++ b/servers/physics_3d/space_3d_sw.h
@@ -203,8 +203,7 @@ public:
void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
- int test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
- bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
+ bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, const Set<RID> &p_exclude = Set<RID>());
Space3DSW();
~Space3DSW();
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index e8272f377e..c96f85446c 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -89,6 +89,8 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState2D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState2D::get_transform);
+ ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState2D::get_velocity_at_local_position);
+
ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState2D::add_central_force);
ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState2D::add_force, Vector2());
ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState2D::add_torque);
@@ -232,8 +234,8 @@ void PhysicsShapeQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters2D::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters2D::get_margin);
- ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &PhysicsShapeQueryParameters2D::set_collision_mask);
- ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsShapeQueryParameters2D::get_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsShapeQueryParameters2D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsShapeQueryParameters2D::get_collision_mask);
ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsShapeQueryParameters2D::set_exclude);
ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsShapeQueryParameters2D::get_exclude);
@@ -244,7 +246,7 @@ void PhysicsShapeQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsShapeQueryParameters2D::set_collide_with_areas);
ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
@@ -409,9 +411,9 @@ PhysicsDirectSpaceState2D::PhysicsDirectSpaceState2D() {
}
void PhysicsDirectSpaceState2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32));
ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &PhysicsDirectSpaceState2D::_cast_motion);
ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32));
@@ -420,11 +422,11 @@ void PhysicsDirectSpaceState2D::_bind_methods() {
///////////////////////////////
-Vector2 PhysicsTestMotionResult2D::get_motion() const {
- return result.motion;
+Vector2 PhysicsTestMotionResult2D::get_travel() const {
+ return result.travel;
}
-Vector2 PhysicsTestMotionResult2D::get_motion_remainder() const {
+Vector2 PhysicsTestMotionResult2D::get_remainder() const {
return result.remainder;
}
@@ -469,8 +471,8 @@ real_t PhysicsTestMotionResult2D::get_collision_unsafe_fraction() const {
}
void PhysicsTestMotionResult2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionResult2D::get_motion);
- ClassDB::bind_method(D_METHOD("get_motion_remainder"), &PhysicsTestMotionResult2D::get_motion_remainder);
+ ClassDB::bind_method(D_METHOD("get_travel"), &PhysicsTestMotionResult2D::get_travel);
+ ClassDB::bind_method(D_METHOD("get_remainder"), &PhysicsTestMotionResult2D::get_remainder);
ClassDB::bind_method(D_METHOD("get_collision_point"), &PhysicsTestMotionResult2D::get_collision_point);
ClassDB::bind_method(D_METHOD("get_collision_normal"), &PhysicsTestMotionResult2D::get_collision_normal);
ClassDB::bind_method(D_METHOD("get_collider_velocity"), &PhysicsTestMotionResult2D::get_collider_velocity);
@@ -482,8 +484,8 @@ void PhysicsTestMotionResult2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult2D::get_collision_safe_fraction);
ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult2D::get_collision_unsafe_fraction);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "", "get_motion");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_remainder"), "", "get_motion_remainder");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "travel"), "", "get_travel");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "remainder"), "", "get_remainder");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_point"), "", "get_collision_point");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_normal"), "", "get_collision_normal");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity");
@@ -498,7 +500,7 @@ void PhysicsTestMotionResult2D::_bind_methods() {
///////////////////////////////////////
-bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result, bool p_exclude_raycast_shapes, const Vector<RID> &p_exclude) {
+bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result, const Vector<RID> &p_exclude) {
MotionResult *r = nullptr;
if (p_result.is_valid()) {
r = p_result->get_result_ptr();
@@ -507,12 +509,11 @@ bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, c
for (int i = 0; i < p_exclude.size(); i++) {
exclude.insert(p_exclude[i]);
}
- return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r, p_exclude_raycast_shapes, exclude);
+ return body_test_motion(p_body, p_from, p_motion, p_margin, r, exclude);
}
void PhysicsServer2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("line_shape_create"), &PhysicsServer2D::line_shape_create);
- ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer2D::ray_shape_create);
+ ClassDB::bind_method(D_METHOD("world_margin_shape_create"), &PhysicsServer2D::world_margin_shape_create);
ClassDB::bind_method(D_METHOD("segment_shape_create"), &PhysicsServer2D::segment_shape_create);
ClassDB::bind_method(D_METHOD("circle_shape_create"), &PhysicsServer2D::circle_shape_create);
ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &PhysicsServer2D::rectangle_shape_create);
@@ -634,7 +635,7 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result", "exclude_raycast_shapes", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(true), DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state);
@@ -673,8 +674,7 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
- BIND_ENUM_CONSTANT(SHAPE_LINE);
- BIND_ENUM_CONSTANT(SHAPE_RAY);
+ BIND_ENUM_CONSTANT(SHAPE_WORLD_MARGIN);
BIND_ENUM_CONSTANT(SHAPE_SEGMENT);
BIND_ENUM_CONSTANT(SHAPE_CIRCLE);
BIND_ENUM_CONSTANT(SHAPE_RECTANGLE);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 8542b54838..4c559dd7bd 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -60,6 +60,8 @@ public:
virtual void set_transform(const Transform2D &p_transform) = 0;
virtual Transform2D get_transform() const = 0;
+ virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const = 0;
+
virtual void add_central_force(const Vector2 &p_force) = 0;
virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
virtual void add_torque(real_t p_torque) = 0;
@@ -208,7 +210,7 @@ class PhysicsServer2D : public Object {
static PhysicsServer2D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>(), bool p_exclude_raycast_shapes = true, const Vector<RID> &p_exclude = Vector<RID>());
+ virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>(), const Vector<RID> &p_exclude = Vector<RID>());
protected:
static void _bind_methods();
@@ -217,8 +219,7 @@ public:
static PhysicsServer2D *get_singleton();
enum ShapeType {
- SHAPE_LINE, ///< plane:"plane"
- SHAPE_RAY, ///< float:"length"
+ SHAPE_WORLD_MARGIN, ///< plane:"plane"
SHAPE_SEGMENT, ///< float:"length"
SHAPE_CIRCLE, ///< float:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
@@ -228,8 +229,7 @@ public:
SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
};
- virtual RID line_shape_create() = 0;
- virtual RID ray_shape_create() = 0;
+ virtual RID world_margin_shape_create() = 0;
virtual RID segment_shape_create() = 0;
virtual RID circle_shape_create() = 0;
virtual RID rectangle_shape_create() = 0;
@@ -465,7 +465,7 @@ public:
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) = 0;
struct MotionResult {
- Vector2 motion;
+ Vector2 travel;
Vector2 remainder;
Vector2 collision_point;
@@ -479,9 +479,13 @@ public:
RID collider;
int collider_shape = 0;
Variant collider_metadata;
+
+ real_t get_angle(Vector2 p_up_direction) const {
+ return Math::acos(collision_normal.dot(p_up_direction));
+ }
};
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) = 0;
struct SeparationResult {
real_t collision_depth;
@@ -495,8 +499,6 @@ public:
Variant collider_metadata;
};
- virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.08) = 0;
-
/* JOINT API */
virtual RID joint_create() = 0;
@@ -590,8 +592,8 @@ protected:
public:
PhysicsServer2D::MotionResult *get_result_ptr() const { return const_cast<PhysicsServer2D::MotionResult *>(&result); }
- Vector2 get_motion() const;
- Vector2 get_motion_remainder() const;
+ Vector2 get_travel() const;
+ Vector2 get_remainder() const;
Vector2 get_collision_point() const;
Vector2 get_collision_normal() const;
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 3ed8841119..53863cea72 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -91,6 +91,8 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState3D::get_transform);
+ ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState3D::get_velocity_at_local_position);
+
ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force, Vector3());
ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force, Vector3());
ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState3D::add_torque);
@@ -367,11 +369,11 @@ void PhysicsDirectSpaceState3D::_bind_methods() {
///////////////////////////////
-Vector3 PhysicsTestMotionResult3D::get_motion() const {
- return result.motion;
+Vector3 PhysicsTestMotionResult3D::get_travel() const {
+ return result.travel;
}
-Vector3 PhysicsTestMotionResult3D::get_motion_remainder() const {
+Vector3 PhysicsTestMotionResult3D::get_remainder() const {
return result.remainder;
}
@@ -416,8 +418,8 @@ real_t PhysicsTestMotionResult3D::get_collision_unsafe_fraction() const {
}
void PhysicsTestMotionResult3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionResult3D::get_motion);
- ClassDB::bind_method(D_METHOD("get_motion_remainder"), &PhysicsTestMotionResult3D::get_motion_remainder);
+ ClassDB::bind_method(D_METHOD("get_travel"), &PhysicsTestMotionResult3D::get_travel);
+ ClassDB::bind_method(D_METHOD("get_remainder"), &PhysicsTestMotionResult3D::get_remainder);
ClassDB::bind_method(D_METHOD("get_collision_point"), &PhysicsTestMotionResult3D::get_collision_point);
ClassDB::bind_method(D_METHOD("get_collision_normal"), &PhysicsTestMotionResult3D::get_collision_normal);
ClassDB::bind_method(D_METHOD("get_collider_velocity"), &PhysicsTestMotionResult3D::get_collider_velocity);
@@ -429,8 +431,8 @@ void PhysicsTestMotionResult3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult3D::get_collision_safe_fraction);
ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult3D::get_collision_unsafe_fraction);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "", "get_motion");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_remainder"), "", "get_motion_remainder");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_point"), "", "get_collision_point");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_normal"), "", "get_collision_normal");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_collider_velocity");
@@ -445,20 +447,22 @@ void PhysicsTestMotionResult3D::_bind_methods() {
///////////////////////////////////////
-bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result) {
+bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result, const Vector<RID> &p_exclude) {
MotionResult *r = nullptr;
if (p_result.is_valid()) {
r = p_result->get_result_ptr();
}
- return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r);
+ Set<RID> exclude;
+ for (int i = 0; i < p_exclude.size(); i++) {
+ exclude.insert(p_exclude[i]);
+ }
+ return body_test_motion(p_body, p_from, p_motion, p_margin, r, exclude);
}
RID PhysicsServer3D::shape_create(ShapeType p_shape) {
switch (p_shape) {
case SHAPE_PLANE:
return plane_shape_create();
- case SHAPE_RAY:
- return ray_shape_create();
case SHAPE_SPHERE:
return sphere_shape_create();
case SHAPE_BOX:
@@ -484,7 +488,6 @@ void PhysicsServer3D::_bind_methods() {
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("plane_shape_create"), &PhysicsServer3D::plane_shape_create);
- ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer3D::ray_shape_create);
ClassDB::bind_method(D_METHOD("sphere_shape_create"), &PhysicsServer3D::sphere_shape_create);
ClassDB::bind_method(D_METHOD("box_shape_create"), &PhysicsServer3D::box_shape_create);
ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer3D::capsule_shape_create);
@@ -606,7 +609,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "exclude"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
@@ -745,7 +748,6 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info);
BIND_ENUM_CONSTANT(SHAPE_PLANE);
- BIND_ENUM_CONSTANT(SHAPE_RAY);
BIND_ENUM_CONSTANT(SHAPE_SPHERE);
BIND_ENUM_CONSTANT(SHAPE_BOX);
BIND_ENUM_CONSTANT(SHAPE_CAPSULE);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 17bae9a057..f806fd55be 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -62,6 +62,8 @@ public:
virtual void set_transform(const Transform3D &p_transform) = 0;
virtual Transform3D get_transform() const = 0;
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const = 0;
+
virtual void add_central_force(const Vector3 &p_force) = 0;
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
virtual void add_torque(const Vector3 &p_torque) = 0;
@@ -210,7 +212,7 @@ class PhysicsServer3D : public Object {
static PhysicsServer3D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>());
+ virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>(), const Vector<RID> &p_exclude = Vector<RID>());
protected:
static void _bind_methods();
@@ -220,7 +222,6 @@ public:
enum ShapeType {
SHAPE_PLANE, ///< plane:"plane"
- SHAPE_RAY, ///< float:"length"
SHAPE_SPHERE, ///< float:"radius"
SHAPE_BOX, ///< vec3:"extents"
SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule
@@ -235,7 +236,6 @@ public:
RID shape_create(ShapeType p_shape);
virtual RID plane_shape_create() = 0;
- virtual RID ray_shape_create() = 0;
virtual RID sphere_shape_create() = 0;
virtual RID box_shape_create() = 0;
virtual RID capsule_shape_create() = 0;
@@ -473,7 +473,7 @@ public:
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0;
struct MotionResult {
- Vector3 motion;
+ Vector3 travel;
Vector3 remainder;
Vector3 collision_point;
@@ -487,23 +487,13 @@ public:
RID collider;
int collider_shape = 0;
Variant collider_metadata;
- };
-
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
- struct SeparationResult {
- real_t collision_depth;
- Vector3 collision_point;
- Vector3 collision_normal;
- Vector3 collider_velocity;
- int collision_local_shape;
- ObjectID collider_id;
- RID collider;
- int collider_shape;
- Variant collider_metadata;
+ real_t get_angle(Vector3 p_up_direction) const {
+ return Math::acos(collision_normal.dot(p_up_direction));
+ }
};
- virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set<RID> &p_exclude = Set<RID>()) = 0;
/* SOFT BODY */
@@ -766,8 +756,8 @@ protected:
public:
PhysicsServer3D::MotionResult *get_result_ptr() const { return const_cast<PhysicsServer3D::MotionResult *>(&result); }
- Vector3 get_motion() const;
- Vector3 get_motion_remainder() const;
+ Vector3 get_travel() const;
+ Vector3 get_remainder() const;
Vector3 get_collision_point() const;
Vector3 get_collision_normal() const;
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index b7cf0983af..f58d124140 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -540,13 +540,13 @@ public:
void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
void particles_set_emitting(RID p_particles, bool p_emitting) override {}
void particles_set_amount(RID p_particles, int p_amount) override {}
- void particles_set_lifetime(RID p_particles, float p_lifetime) override {}
+ void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
- void particles_set_pre_process_time(RID p_particles, float p_time) override {}
- void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) override {}
- void particles_set_randomness_ratio(RID p_particles, float p_ratio) override {}
+ void particles_set_pre_process_time(RID p_particles, double p_time) override {}
+ void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
+ void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
- void particles_set_speed_scale(RID p_particles, float p_scale) override {}
+ void particles_set_speed_scale(RID p_particles, double p_scale) override {}
void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
void particles_set_process_material(RID p_particles, RID p_material) override {}
void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
@@ -554,11 +554,11 @@ public:
void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
- void particles_set_collision_base_size(RID p_particles, float p_size) override {}
+ void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
- void particles_set_trails(RID p_particles, bool p_enable, float p_length) override {}
+ void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
void particles_restart(RID p_particles) override {}
@@ -591,11 +591,11 @@ public:
void particles_collision_initialize(RID p_rid) override {}
void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
- void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) override {}
+ void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
- void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) override {}
- void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) override {}
- void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) override {}
+ void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
+ void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
+ void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
void particles_collision_height_field_update(RID p_particles_collision) override {}
void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
@@ -724,7 +724,7 @@ public:
class RasterizerDummy : public RendererCompositor {
private:
uint64_t frame = 1;
- float delta = 0;
+ double delta = 0;
protected:
RasterizerCanvasDummy canvas;
@@ -765,7 +765,7 @@ public:
bool is_low_end() const override { return true; }
uint64_t get_frame_number() const override { return frame; }
- float get_frame_delta_time() const override { return delta; }
+ double get_frame_delta_time() const override { return delta; }
RasterizerDummy() {}
~RasterizerDummy() {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index ec0a8347f8..fd7d5b91fa 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -639,17 +639,19 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
j2 = j + 1;
- Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
+ Vector2 dir = (t + prev_t).normalized();
+ Vector2 tangent = dir * p_width * 0.5;
+ Vector2 border = dir * 2.0;
Vector2 pos = p_points[i];
points_ptr[j] = pos + tangent;
points_ptr[j2] = pos - tangent;
- points_top_ptr[j] = pos + tangent + tangent;
+ points_top_ptr[j] = pos + tangent + border;
points_top_ptr[j2] = pos + tangent;
points_bottom_ptr[j] = pos - tangent;
- points_bottom_ptr[j2] = pos - tangent - tangent;
+ points_bottom_ptr[j2] = pos - tangent - border;
if (i < p_colors.size()) {
color = p_colors[i];
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 5fe9cdffba..6206849b66 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -85,7 +85,7 @@ public:
virtual void end_frame(bool p_swap_buffers) = 0;
virtual void finalize() = 0;
virtual uint64_t get_frame_number() const = 0;
- virtual float get_frame_delta_time() const = 0;
+ virtual double get_frame_delta_time() const = 0;
virtual bool is_low_end() const = 0;
virtual bool is_xr_enabled() const;
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 47bb756d55..f5b6be4795 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -37,6 +37,10 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "thirdparty/misc/cubemap_coeffs.h"
+bool EffectsRD::get_prefer_raster_effects() {
+ return prefer_raster_effects;
+}
+
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
@@ -66,6 +70,28 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
return uniform_set;
}
+RID EffectsRD::_get_uniform_set_for_input(RID p_texture) {
+ if (input_to_uniform_set_cache.has(p_texture)) {
+ RID uniform_set = input_to_uniform_set_cache[p_texture];
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ return uniform_set;
+ }
+ }
+
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT;
+ u.binding = 0;
+ u.ids.push_back(p_texture);
+ uniforms.push_back(u);
+ // This is specific to our subpass shader
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, TONEMAP_MODE_SUBPASS), 0);
+
+ input_to_uniform_set_cache[p_texture] = uniform_set;
+
+ return uniform_set;
+}
+
RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
if (texture_to_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_uniform_set_cache[p_texture];
@@ -81,7 +107,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
u.ids.push_back(p_texture);
uniforms.push_back(u);
- //anything with the same configuration (one texture in binding 0 for set 0), is good
+ // anything with the same configuration (one texture in binding 0 for set 0), is good
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
@@ -454,7 +480,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
}
void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the fragment version of the gaussian glow with the clustered renderer.");
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -713,6 +739,26 @@ void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const S
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode mode = BLUR_MIPMAP;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip) {
CopyToDPPushConstant push_constant;
push_constant.screen_rect[0] = p_rect.position.x;
@@ -774,11 +820,11 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
if (p_settings.view_count > 1) {
// Use MULTIVIEW versions
- mode += 4;
+ mode += 6;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2);
@@ -790,6 +836,45 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
RD::get_singleton()->draw_list_end();
}
+void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings) {
+ memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
+
+ tonemap.push_constant.use_bcs = p_settings.use_bcs;
+ tonemap.push_constant.bcs[0] = p_settings.brightness;
+ tonemap.push_constant.bcs[1] = p_settings.contrast;
+ tonemap.push_constant.bcs[2] = p_settings.saturation;
+
+ ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
+ tonemap.push_constant.use_glow = p_settings.use_glow;
+
+ int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
+ if (p_settings.view_count > 1) {
+ // Use MULTIVIEW versions
+ mode += 6;
+ }
+
+ tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
+ tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
+ tonemap.push_constant.exposure = p_settings.exposure;
+ tonemap.push_constant.white = p_settings.white;
+ tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+
+ tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
+
+ tonemap.push_constant.use_debanding = p_settings.use_debanding;
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); // should be set to a default texture, it's ignored
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); // should be set to a default texture, it's ignored
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
+
+ RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
+ RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
+}
+
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
@@ -832,7 +917,7 @@ void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_
}
void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use fragment version of luminance reduction with the clustered renderer.");
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster version of luminance reduction with the clustered renderer.");
ERR_FAIL_COND_MSG(p_reduce.size() != p_fb.size(), "Incorrect frame buffer account for luminance reduction.");
luminance_reduce_raster.push_constant.max_luminance = p_max_luminance;
@@ -863,7 +948,7 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
}
}
-void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void EffectsRD::bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer.");
bokeh.push_constant.blur_far_active = p_dof_far;
@@ -892,22 +977,22 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
// The alpha channel of the source color texture is filled with the expected circle size
// If used for DOF far, the size is positive, if used for near, its negative.
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BLUR_SIZE]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_texture), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.depth_texture), 1);
- bokeh.push_constant.size[0] = p_base_texture_size.x;
- bokeh.push_constant.size[1] = p_base_texture_size.y;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
//second pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
static const int quality_samples[4] = { 6, 12, 12, 24 };
@@ -916,18 +1001,18 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
- bokeh.push_constant.size[0] = p_base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_base_texture_size.y >> 1;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
bokeh.push_constant.half_size = true;
bokeh.push_constant.blur_size *= 0.5;
} else {
//medium and high quality use full size
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.secondary_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
@@ -939,11 +1024,11 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
bokeh.push_constant.second_pass = true;
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture2), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[1]), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
} else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.secondary_texture), 1);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
@@ -954,25 +1039,25 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
//forth pass, upscale for low quality
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture2), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[1]), 1);
- bokeh.push_constant.size[0] = p_base_texture_size.x;
- bokeh.push_constant.size[1] = p_base_texture_size.y;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
bokeh.push_constant.half_size = false;
bokeh.push_constant.second_pass = false;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
}
} else {
//circle
//second pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
@@ -981,11 +1066,11 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
//circle always runs in half size, otherwise too expensive
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
- bokeh.push_constant.size[0] = p_base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_base_texture_size.y >> 1;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
bokeh.push_constant.half_size = true;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
@@ -997,93 +1082,195 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
// upscale
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
- bokeh.push_constant.size[0] = p_base_texture_size.x;
- bokeh.push_constant.size[1] = p_base_texture_size.y;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
bokeh.push_constant.half_size = false;
bokeh.push_constant.second_pass = false;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
}
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::blur_dof_raster(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_base_fb, RID p_secondary_texture, RID p_secondary_fb, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer.");
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
-
- BlurRasterMode blur_mode;
- int qsteps[4] = { 4, 4, 10, 20 };
- uint32_t base_flags = p_cam_orthogonal ? BLUR_FLAG_USE_ORTHOGONAL_PROJECTION : 0;
+ memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
- Vector2 pixel_size = Vector2(1.0 / p_base_texture_size.width, 1.0 / p_base_texture_size.height);
+ bokeh.push_constant.orthogonal = p_cam_orthogonal;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.width;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.height;
+ bokeh.push_constant.z_far = p_cam_zfar;
+ bokeh.push_constant.z_near = p_cam_znear;
- blur_raster.push_constant.dof_radius = (p_dof_blur_amount * p_dof_blur_amount) / qsteps[p_quality];
- blur_raster.push_constant.pixel_size[0] = pixel_size.x;
- blur_raster.push_constant.pixel_size[1] = pixel_size.y;
- blur_raster.push_constant.camera_z_far = p_cam_zfar;
- blur_raster.push_constant.camera_z_near = p_cam_znear;
+ bokeh.push_constant.second_pass = false;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.blur_size = p_dof_blur_amount;
if (p_dof_far || p_dof_near) {
- if (p_quality == RS::DOF_BLUR_QUALITY_HIGH) {
- blur_mode = BLUR_MODE_DOF_HIGH;
- } else if (p_quality == RS::DOF_BLUR_QUALITY_MEDIUM) {
- blur_mode = BLUR_MODE_DOF_MEDIUM;
- } else { // for LOW or VERYLOW we use LOW
- blur_mode = BLUR_MODE_DOF_LOW;
- }
-
if (p_dof_far) {
- base_flags |= BLUR_FLAG_DOF_FAR;
- blur_raster.push_constant.dof_far_begin = p_dof_far_begin;
- blur_raster.push_constant.dof_far_end = p_dof_far_begin + p_dof_far_size;
+ bokeh.push_constant.blur_far_active = true;
+ bokeh.push_constant.blur_far_begin = p_dof_far_begin;
+ bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
}
if (p_dof_near) {
- base_flags |= BLUR_FLAG_DOF_NEAR;
- blur_raster.push_constant.dof_near_begin = p_dof_near_begin;
- blur_raster.push_constant.dof_near_end = p_dof_near_begin - p_dof_near_size;
+ bokeh.push_constant.blur_near_active = true;
+ bokeh.push_constant.blur_near_begin = p_dof_near_begin;
+ bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
}
- //HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_secondary_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_secondary_fb)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base_texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_depth_texture), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ {
+ // generate our depth data
+ RID framebuffer = p_buffers.base_weight_fb;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.depth_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL;
- blur_raster.push_constant.dof_dir[0] = 1.0;
- blur_raster.push_constant.dof_dir[1] = 0.0;
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ // double pass approach
+ BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
- //VERTICAL
- draw_list = RD::get_singleton()->draw_list_begin(p_base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_base_fb)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary_texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_depth_texture), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ bokeh.push_constant.blur_size *= 0.5;
+ }
- blur_raster.push_constant.flags = base_flags;
- blur_raster.push_constant.dof_dir[0] = 0.0;
- blur_raster.push_constant.dof_dir[1] = 1.0;
+ static const int quality_samples[4] = { 6, 12, 12, 24 };
+ bokeh.push_constant.blur_scale = 0.5;
+ bokeh.push_constant.steps = quality_samples[p_quality];
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+ RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ // Pass 1
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ // Pass 2
+ if (!bokeh.push_constant.half_size) {
+ // do not output weight, we're writing back into our base buffer
+ mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
+ }
+ bokeh.push_constant.second_pass = true;
+
+ framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb;
+ RID texture = bokeh.push_constant.half_size ? p_buffers.half_texture[0] : p_buffers.secondary_texture;
+ RID weight = bokeh.push_constant.half_size ? p_buffers.weight_texture[2] : p_buffers.weight_texture[1];
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(weight), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ if (bokeh.push_constant.half_size) {
+ // Compose pass
+ mode = BOKEH_COMPOSITE;
+ framebuffer = p_buffers.base_fb;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[1]), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[3]), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ } else {
+ // circular is a single pass approach
+ BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR;
+
+ {
+ // circle always runs in half size, otherwise too expensive (though the code below does support making this optional)
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ // bokeh.push_constant.blur_size *= 0.5;
+ }
+
+ static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
+ bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.steps = 0.0;
+
+ RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ if (bokeh.push_constant.half_size) {
+ // Compose
+ mode = BOKEH_COMPOSITE;
+ framebuffer = p_buffers.base_fb;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[0]), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[2]), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ } else {
+ // Just copy it back (we use our blur raster shader here)..
+ draw_list = RD::get_singleton()->draw_list_begin(p_buffers.base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_buffers.base_fb)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.secondary_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
}
}
@@ -1447,7 +1634,9 @@ void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
+void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer.");
+
memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
@@ -1457,10 +1646,10 @@ void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffe
roughness.push_constant.face_size = p_size;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipeline);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
@@ -1472,11 +1661,37 @@ void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffe
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time.");
+
+ memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
+
+ roughness.push_constant.face_id = p_face_id;
+ roughness.push_constant.roughness = p_roughness;
+ roughness.push_constant.sample_count = p_sample_count;
+ roughness.push_constant.use_direct_write = p_roughness == 0.0;
+ roughness.push_constant.face_size = p_size;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer.");
+
cubemap_downsampler.push_constant.face_size = p_size.x;
+ cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipeline);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1);
@@ -1490,7 +1705,27 @@ void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, con
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time.");
+
+ cubemap_downsampler.push_constant.face_size = p_size.x;
+ cubemap_downsampler.push_constant.face_id = p_face_id;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_cubemap), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer.");
+
Vector<RD::Uniform> uniforms;
for (int i = 0; i < p_dest_cubemap.size(); i++) {
RD::Uniform u;
@@ -1502,12 +1737,12 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
RD::get_singleton()->free(filter.image_uniform_set);
}
- filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, 0), 2);
+ filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2);
int pipeline = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY;
pipeline = filter.use_high_quality ? pipeline : pipeline + 1;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.pipelines[pipeline]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[pipeline]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap, true), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2);
@@ -1519,6 +1754,29 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time.");
+
+ // TODO implement!
+ CubemapFilterRasterPushConstant push_constant;
+ push_constant.mip_level = p_mip_level;
+ push_constant.face_id = p_face_id;
+
+ CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_cubemap), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CubemapFilterRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
ResolvePushConstant push_constant;
push_constant.screen_size[0] = p_screen_size.x;
@@ -1635,12 +1893,11 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
// init blur shader (on compute use copy shader)
Vector<String> blur_modes;
+ blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP
blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
- blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_LOW\n"); // BLUR_MODE_DOF_LOW
- blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_MEDIUM\n"); // BLUR_MODE_DOF_MEDIUM
- blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_HIGH\n"); // BLUR_MODE_DOF_HIGH
+ blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
blur_raster.shader.initialize(blur_modes);
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -1713,11 +1970,22 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
// Initialize roughness
Vector<String> cubemap_roughness_modes;
cubemap_roughness_modes.push_back("");
- roughness.shader.initialize(cubemap_roughness_modes);
- roughness.shader_version = roughness.shader.version_create();
+ if (prefer_raster_effects) {
+ roughness.raster_shader.initialize(cubemap_roughness_modes);
+
+ roughness.shader_version = roughness.raster_shader.version_create();
+
+ roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+
+ } else {
+ roughness.compute_shader.initialize(cubemap_roughness_modes);
- roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0));
+ roughness.shader_version = roughness.compute_shader.version_create();
+
+ roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
+ roughness.raster_pipeline.clear();
+ }
}
{
@@ -1727,12 +1995,16 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n");
tonemap_modes.push_back("\n#define USE_1D_LUT\n");
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define SUBPASS\n");
+ tonemap_modes.push_back("\n#define SUBPASS\n#define USE_1D_LUT\n");
// multiview versions of our shaders
tonemap_modes.push_back("\n#define MULTIVIEW\n");
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define SUBPASS\n#define USE_1D_LUT\n");
tonemap.shader.initialize(tonemap_modes);
@@ -1741,6 +2013,8 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW, false);
}
tonemap.shader_version = tonemap.shader.version_create();
@@ -1803,23 +2077,39 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
}
+ // Initialize bokeh
+ Vector<String> bokeh_modes;
+ bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
if (prefer_raster_effects) {
- // not supported
- } else {
- // Initialize bokeh
- Vector<String> bokeh_modes;
- bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n");
- bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
+ bokeh.raster_shader.initialize(bokeh_modes);
- bokeh.shader.initialize(bokeh_modes);
+ bokeh.shader_version = bokeh.raster_shader.version_create();
- bokeh.shader_version = bokeh.shader.version_create();
+ const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 };
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]);
+ bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ } else {
+ bokeh.compute_shader.initialize(bokeh_modes);
+ bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false);
+ bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false);
+ bokeh.shader_version = bokeh.compute_shader.version_create();
for (int i = 0; i < BOKEH_MAX; i++) {
- bokeh.pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.shader.version_get_shader(bokeh.shader_version, i));
+ if (bokeh.compute_shader.is_variant_enabled(i)) {
+ bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
+ }
+ }
+
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ bokeh.raster_pipelines[i].clear();
}
}
@@ -1983,11 +2273,21 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
//Initialize cubemap downsampler
Vector<String> cubemap_downsampler_modes;
cubemap_downsampler_modes.push_back("");
- cubemap_downsampler.shader.initialize(cubemap_downsampler_modes);
- cubemap_downsampler.shader_version = cubemap_downsampler.shader.version_create();
+ if (prefer_raster_effects) {
+ cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes);
+
+ cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create();
+
+ cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes);
+
+ cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create();
- cubemap_downsampler.pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, 0));
+ cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
+ cubemap_downsampler.raster_pipeline.clear();
+ }
}
{
@@ -1999,12 +2299,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n");
cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n");
cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n");
- filter.shader.initialize(cubemap_filter_modes);
- filter.shader_version = filter.shader.version_create();
-
- for (int i = 0; i < FILTER_MODE_MAX; i++) {
- filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.shader.version_get_shader(filter.shader_version, i));
- }
if (filter.use_high_quality) {
filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs));
@@ -2014,15 +2308,51 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]);
}
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(filter.coefficient_buffer);
- uniforms.push_back(u);
+ if (prefer_raster_effects) {
+ filter.raster_shader.initialize(cubemap_filter_modes);
+
+ // array variants are not supported in raster
+ filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false);
+ filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false);
+
+ filter.shader_version = filter.raster_shader.version_create();
+
+ for (int i = 0; i < FILTER_MODE_MAX; i++) {
+ if (filter.raster_shader.is_variant_enabled(i)) {
+ filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ filter.raster_pipelines[i].clear();
+ }
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(filter.coefficient_buffer);
+ uniforms.push_back(u);
+ }
+ filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
+ } else {
+ filter.compute_shader.initialize(cubemap_filter_modes);
+ filter.shader_version = filter.compute_shader.version_create();
+
+ for (int i = 0; i < FILTER_MODE_MAX; i++) {
+ filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i));
+ filter.raster_pipelines[i].clear();
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(filter.coefficient_buffer);
+ uniforms.push_back(u);
+ }
+ filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
}
- filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
}
{
@@ -2198,18 +2528,22 @@ EffectsRD::~EffectsRD() {
if (prefer_raster_effects) {
blur_raster.shader.version_free(blur_raster.shader_version);
+ bokeh.raster_shader.version_free(blur_raster.shader_version);
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
+ roughness.raster_shader.version_free(roughness.shader_version);
+ cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
+ filter.raster_shader.version_free(filter.shader_version);
} else {
- bokeh.shader.version_free(bokeh.shader_version);
+ bokeh.compute_shader.version_free(bokeh.shader_version);
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
+ roughness.compute_shader.version_free(roughness.shader_version);
+ cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
+ filter.compute_shader.version_free(filter.shader_version);
}
copy.shader.version_free(copy.shader_version);
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
- cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
- filter.shader.version_free(filter.shader_version);
resolve.shader.version_free(resolve.shader_version);
- roughness.shader.version_free(roughness.shader_version);
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
sort.shader.version_free(sort.shader_version);
specular_merge.shader.version_free(specular_merge.shader_version);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index d072564c23..0c9b2efb7f 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -35,12 +35,16 @@
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
@@ -62,14 +66,16 @@
#include "servers/rendering_server.h"
class EffectsRD {
+private:
+ bool prefer_raster_effects;
+
enum BlurRasterMode {
+ BLUR_MIPMAP,
+
BLUR_MODE_GAUSSIAN_BLUR,
BLUR_MODE_GAUSSIAN_GLOW,
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
-
- BLUR_MODE_DOF_LOW,
- BLUR_MODE_DOF_MEDIUM,
- BLUR_MODE_DOF_HIGH,
+ BLUR_MODE_COPY,
BLUR_MODE_MAX
};
@@ -78,8 +84,6 @@ class EffectsRD {
BLUR_FLAG_HORIZONTAL = (1 << 0),
BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
- BLUR_FLAG_DOF_FAR = (1 << 3),
- BLUR_FLAG_DOF_NEAR = (1 << 4),
};
struct BlurRasterPushConstant {
@@ -97,19 +101,6 @@ class EffectsRD {
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
-
- //dof
- float dof_far_begin;
- float dof_far_end;
- float dof_near_begin;
- float dof_near_end;
-
- float dof_radius;
- float dof_pad[3];
-
- float dof_dir[2];
- float camera_z_far;
- float camera_z_near;
};
struct BlurRaster {
@@ -220,9 +211,11 @@ class EffectsRD {
struct CubemapRoughness {
CubemapRoughnessPushConstant push_constant;
- CubemapRoughnessShaderRD shader;
+ CubemapRoughnessShaderRD compute_shader;
+ CubemapRoughnessRasterShaderRD raster_shader;
RID shader_version;
- RID pipeline;
+ RID compute_pipeline;
+ PipelineCacheRD raster_pipeline;
} roughness;
enum TonemapMode {
@@ -230,39 +223,43 @@ class EffectsRD {
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
TONEMAP_MODE_1D_LUT,
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
+ TONEMAP_MODE_SUBPASS,
+ TONEMAP_MODE_SUBPASS_1D_LUT,
TONEMAP_MODE_NORMAL_MULTIVIEW,
TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
TONEMAP_MODE_1D_LUT_MULTIVIEW,
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
+ TONEMAP_MODE_SUBPASS_MULTIVIEW,
+ TONEMAP_MODE_SUBPASS_1D_LUT_MULTIVIEW,
TONEMAP_MODE_MAX
};
struct TonemapPushConstant {
- float bcs[3];
- uint32_t use_bcs;
+ float bcs[3]; // 12 - 12
+ uint32_t use_bcs; // 4 - 16
- uint32_t use_glow;
- uint32_t use_auto_exposure;
- uint32_t use_color_correction;
- uint32_t tonemapper;
+ uint32_t use_glow; // 4 - 20
+ uint32_t use_auto_exposure; // 4 - 24
+ uint32_t use_color_correction; // 4 - 28
+ uint32_t tonemapper; // 4 - 32
- uint32_t glow_texture_size[2];
- float glow_intensity;
- uint32_t pad3;
+ uint32_t glow_texture_size[2]; // 8 - 40
+ float glow_intensity; // 4 - 44
+ uint32_t pad3; // 4 - 48
- uint32_t glow_mode;
- float glow_levels[7];
+ uint32_t glow_mode; // 4 - 52
+ float glow_levels[7]; // 28 - 80
- float exposure;
- float white;
- float auto_exposure_grey;
- uint32_t pad2;
+ float exposure; // 4 - 84
+ float white; // 4 - 88
+ float auto_exposure_grey; // 4 - 92
+ uint32_t pad2; // 4 - 96
- float pixel_size[2];
- uint32_t use_fxaa;
- uint32_t use_debanding;
+ float pixel_size[2]; // 8 - 104
+ uint32_t use_fxaa; // 4 - 108
+ uint32_t use_debanding; // 4 - 112
};
/* tonemap actually writes to a framebuffer, which is
@@ -363,7 +360,9 @@ class EffectsRD {
enum BokehMode {
BOKEH_GEN_BLUR_SIZE,
BOKEH_GEN_BOKEH_BOX,
+ BOKEH_GEN_BOKEH_BOX_NOWEIGHT,
BOKEH_GEN_BOKEH_HEXAGONAL,
+ BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT,
BOKEH_GEN_BOKEH_CIRCULAR,
BOKEH_COMPOSITE,
BOKEH_MAX
@@ -371,9 +370,11 @@ class EffectsRD {
struct Bokeh {
BokehPushConstant push_constant;
- BokehDofShaderRD shader;
+ BokehDofShaderRD compute_shader;
+ BokehDofRasterShaderRD raster_shader;
RID shader_version;
- RID pipelines[BOKEH_MAX];
+ RID compute_pipelines[BOKEH_MAX];
+ PipelineCacheRD raster_pipelines[BOKEH_MAX];
} bokeh;
enum SSAOMode {
@@ -508,15 +509,17 @@ class EffectsRD {
struct CubemapDownsamplerPushConstant {
uint32_t face_size;
- float pad[3];
+ uint32_t face_id;
+ float pad[2];
};
struct CubemapDownsampler {
CubemapDownsamplerPushConstant push_constant;
- CubemapDownsamplerShaderRD shader;
+ CubemapDownsamplerShaderRD compute_shader;
+ CubemapDownsamplerRasterShaderRD raster_shader;
RID shader_version;
- RID pipeline;
-
+ RID compute_pipeline;
+ PipelineCacheRD raster_pipeline;
} cubemap_downsampler;
enum CubemapFilterMode {
@@ -527,10 +530,19 @@ class EffectsRD {
FILTER_MODE_MAX,
};
+ struct CubemapFilterRasterPushConstant {
+ uint32_t mip_level;
+ uint32_t face_id;
+ float pad[2];
+ };
+
struct CubemapFilter {
- CubemapFilterShaderRD shader;
+ CubemapFilterShaderRD compute_shader;
+ CubemapFilterRasterShaderRD raster_shader;
RID shader_version;
- RID pipelines[FILTER_MODE_MAX];
+ RID compute_pipelines[FILTER_MODE_MAX];
+ PipelineCacheRD raster_pipelines[FILTER_MODE_MAX];
+
RID uniform_set;
RID image_uniform_set;
RID coefficient_buffer;
@@ -699,6 +711,7 @@ class EffectsRD {
RID index_array;
Map<RID, RID> texture_to_uniform_set_cache;
+ Map<RID, RID> input_to_uniform_set_cache;
Map<RID, RID> image_to_uniform_set_cache;
@@ -732,15 +745,16 @@ class EffectsRD {
Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
RID _get_uniform_set_from_image(RID p_texture);
+ RID _get_uniform_set_for_input(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
- bool prefer_raster_effects;
-
public:
+ bool get_prefer_raster_effects();
+
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
@@ -752,14 +766,34 @@ public:
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
+ void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
+ void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
+ void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
- void blur_dof_raster(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_base_fb, RID p_secondary_texture, RID p_secondary_fb, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ struct BokehBuffers {
+ // bokeh buffers
+
+ // textures
+ Size2i base_texture_size;
+ RID base_texture;
+ RID depth_texture;
+ RID secondary_texture;
+ RID half_texture[2];
+
+ // raster only
+ RID base_fb;
+ RID secondary_fb; // with weights
+ RID half_fb[2]; // with weights
+ RID base_weight_fb;
+ RID weight_texture[4];
+ };
+
+ void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
struct TonemapSettings {
bool use_glow = false;
@@ -822,13 +856,16 @@ public:
};
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
+ void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
+ void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
+ void cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level);
void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index ac20515c28..5a0ad97c7c 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -183,7 +183,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
+void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support");
@@ -483,8 +483,8 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
}
if (material_uniform_set != prev_material_uniform_set) {
- //update uniform set
- if (material_uniform_set.is_valid()) {
+ // Update uniform set.
+ if (RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);
}
@@ -1533,6 +1533,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
+ if (scene_state.used_screen_texture) {
+ // Copy screen texture to backbuffer so we can read from it
+ _render_buffers_copy_screen_texture(p_render_data);
+ }
+
+ if (scene_state.used_depth_texture) {
+ // Copy depth texture to backbuffer so we can read from it
+ _render_buffers_copy_depth_texture(p_render_data);
+ }
+
RENDER_TIMESTAMP("Render Transparent Pass");
RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
@@ -1555,6 +1565,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
RD::get_singleton()->draw_command_end_label();
+
+ if (p_render_data->render_buffers.is_valid()) {
+ _debug_draw_cluster(p_render_data->render_buffers);
+
+ RENDER_TIMESTAMP("Tonemap");
+
+ _render_buffers_post_process_and_tonemap(p_render_data);
+ }
}
void RenderForwardClustered::_render_shadow_begin() {
@@ -2211,7 +2229,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
+ RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 6682c5e9b0..676f633d33 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -112,7 +112,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void ensure_specular();
void ensure_voxelgi();
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
~RenderBufferDataForwardClustered();
};
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 333e87bdbd..be18a73989 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -131,8 +131,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
-
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (version.is_null()) {
version = shader_singleton->shader.version_create();
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 5f6d9465c7..ddd2a26d71 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -78,12 +78,16 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
color = RID();
depth = RID();
- color_fb = RID();
+ for (int i = 0; i < FB_CONFIG_MAX; i++) {
+ color_fbs[i] = RID();
+ }
}
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
+ bool is_half_resolution = false; // Set this once we support this feature.
+
msaa = p_msaa;
width = p_width;
@@ -93,15 +97,50 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
color = p_color_buffer;
depth = p_depth_buffer;
- RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
+ // We are creating 4 configurations here for our framebuffers.
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
Vector<RID> fb;
- fb.push_back(p_color_buffer);
- fb.push_back(depth);
+ fb.push_back(p_color_buffer); // 0 - color buffer
+ fb.push_back(depth); // 1 - depth buffer
+
+ // Now define our subpasses
+ Vector<RD::FramebufferPass> passes;
+ RD::FramebufferPass pass;
+
+ // re-using the same attachments
+ pass.color_attachments.push_back(0);
+ pass.depth_attachment = 1;
+
+ // - opaque pass
+ passes.push_back(pass);
+ color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+
+ // - add sky pass
+ passes.push_back(pass);
+ color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+
+ // - add alpha pass
+ passes.push_back(pass);
+ color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ if (!is_half_resolution) {
+ // - add blit to 2D pass
+ fb.push_back(p_target_buffer); // 2 - target buffer
+
+ RD::FramebufferPass blit_pass;
+ blit_pass.color_attachments.push_back(2);
+ blit_pass.input_attachments.push_back(0);
+ passes.push_back(blit_pass);
+
+ color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+ } else {
+ // can't do our blit pass if resolutions don't match
+ color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
+ }
} else {
+ RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
+
RD::TextureFormat tf;
if (view_count > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
@@ -134,14 +173,87 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
{
Vector<RID> fb;
- fb.push_back(color_msaa);
- fb.push_back(depth_msaa);
+ fb.push_back(color_msaa); // 0 - msaa color buffer
+ fb.push_back(depth_msaa); // 1 - msaa depth buffer
+
+ // Now define our subpasses
+ Vector<RD::FramebufferPass> passes;
+ RD::FramebufferPass pass;
+
+ // re-using the same attachments
+ pass.color_attachments.push_back(0);
+ pass.depth_attachment = 1;
+
+ // - opaque pass
+ passes.push_back(pass);
+
+ // - add sky pass
+ fb.push_back(color); // 2 - color buffer
+ passes.push_back(pass); // without resolve for our 3 + 4 subpass config
+ {
+ // but with resolve for our 2 subpass config
+ Vector<RD::FramebufferPass> two_passes;
+ two_passes.push_back(pass); // opaque subpass without resolve
+ pass.resolve_attachments.push_back(2);
+ two_passes.push_back(pass); // sky subpass with resolve
+
+ color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
+ }
+
+ // - add alpha pass (with resolve, we just added that above)
+ passes.push_back(pass);
+ color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ {
+ // we also need our one pass with resolve
+ Vector<RD::FramebufferPass> one_pass_with_resolve;
+ one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve..
+ color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
+ }
+
+ if (!is_half_resolution) {
+ // - add blit to 2D pass
+ fb.push_back(p_target_buffer); // 3 - target buffer
+ RD::FramebufferPass blit_pass;
+ blit_pass.color_attachments.push_back(3);
+ blit_pass.input_attachments.push_back(2);
+ passes.push_back(blit_pass);
+
+ color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+ } else {
+ // can't do our blit pass if resolutions don't match
+ color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
+ }
}
}
}
+RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
+ // Our attachments
+ Vector<RID> fb;
+ fb.push_back(p_color); // 0
+ fb.push_back(p_depth); // 1
+
+ // Now define our subpasses
+ Vector<RD::FramebufferPass> passes;
+ RD::FramebufferPass pass;
+
+ // re-using the same attachments
+ pass.color_attachments.push_back(0);
+ pass.depth_attachment = 1;
+
+ // - opaque pass
+ passes.push_back(pass);
+
+ // - sky pass
+ passes.push_back(pass);
+
+ // - alpha pass
+ passes.push_back(pass);
+
+ return RD::get_singleton()->framebuffer_create_multipass(fb, passes);
+}
+
RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() {
clear();
}
@@ -302,7 +414,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
+ RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
uniforms.push_back(u);
}
@@ -365,14 +478,29 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ // We can only use our full subpass approach if we're:
+ // - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE
+ // - not using ssr/sss (currently not supported)
+ // - not using glow or other post effects (can't do 4th subpass)
+ // - rendering to a half sized render buffer (can't do 4th subpass)
+ // We'll need to restrict how far we're going with subpasses based on this.
+
Size2i screen_size;
- RID opaque_framebuffer;
- RID alpha_framebuffer;
+ RID framebuffer;
bool reverse_cull = false;
+ bool using_subpass_transparent = true;
+ bool using_subpass_post_process = true;
- // I don't think we support either of these in our mobile renderer so probably should phase them out
- bool using_ssr = false;
- bool using_sss = false;
+ bool is_half_resolution = false; // Set this once we support this feature.
+ bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out
+ bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out
+
+ // fill our render lists early so we can find out if we use various features
+ _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
+ render_list[RENDER_LIST_OPAQUE].sort_by_key();
+ render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
+ _fill_element_info(RENDER_LIST_OPAQUE);
+ _fill_element_info(RENDER_LIST_ALPHA);
if (p_render_data->render_info) {
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_render_data->instances->size();
@@ -384,15 +512,36 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- opaque_framebuffer = render_buffer->color_fb;
- alpha_framebuffer = opaque_framebuffer;
+ if (is_half_resolution) {
+ // can't do blit subpass
+ using_subpass_post_process = false;
+ } else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) {
+ // can't do blit subpass
+ using_subpass_post_process = false;
+ }
+
+ if (using_ssr || using_sss || scene_state.used_screen_texture || scene_state.used_depth_texture) {
+ // can't use our last two subpasses
+ using_subpass_transparent = false;
+ using_subpass_post_process = false;
+ }
+
+ if (using_subpass_post_process) {
+ // all as subpasses
+ framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES];
+ } else if (using_subpass_transparent) {
+ // our tonemap pass is separate
+ framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES];
+ } else {
+ // only opaque and sky as subpasses
+ framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES];
+ }
} else if (p_render_data->reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- alpha_framebuffer = opaque_framebuffer;
+ framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
@@ -400,6 +549,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
reverse_cull = true;
+ using_subpass_transparent = true; // we ignore our screen/depth texture here
+ using_subpass_post_process = false; // not applicable at all for reflection probes.
} else {
ERR_FAIL(); //bug?
}
@@ -411,17 +562,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
- _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
- render_list[RENDER_LIST_OPAQUE].sort_by_key();
- render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
-
- // we no longer use this...
- _fill_instance_data(RENDER_LIST_OPAQUE);
- _fill_instance_data(RENDER_LIST_ALPHA);
-
- RD::get_singleton()->draw_command_end_label();
-
- // note, no depth prepass here!
+ RD::get_singleton()->draw_command_end_label(); // Render Setup
// setup environment
RID radiance_texture;
@@ -496,97 +637,211 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// do not try to draw sky if invalid
draw_sky = false;
}
- RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label(); // Setup Sky
}
} else {
clear_color = p_default_bg_color;
}
- // opaque pass
+ // update sky buffers (if required)
+ if (draw_sky || draw_sky_fog_only) {
+ // !BAS! @TODO See if we can limit doing some things double and maybe even move this into _pre_opaque_render
+ // and change Forward Clustered in the same way as we have here (but without using subpasses)
+ RENDER_TIMESTAMP("Setup Sky resolution buffers");
+
+ RD::get_singleton()->draw_command_begin_label("Setup Sky resolution buffers");
+
+ if (p_render_data->reflection_probe.is_valid()) {
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ CameraMatrix projection = correction * p_render_data->cam_projection;
+ sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time);
+ } else {
+ sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
+ }
- // !BAS! Look into this, seems most of the code in here related to clustered only, may want to move this code into ForwardClustered/RenderForwardMobile before calling it from here
- // does trigger shadow map rendering so kinda important
_pre_opaque_render(p_render_data, false, false, RID(), RID());
- RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
+ {
+ if (render_buffer) {
+ RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
+ } else {
+ RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass");
+ }
- scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
+ // opaque pass
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
+ RD::get_singleton()->draw_command_begin_label("Render Opaque Subpass");
- RENDER_TIMESTAMP("Render Opaque Pass");
+ scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
- RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true);
+ _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
- bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
- bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
+ if (using_subpass_transparent && using_subpass_post_process) {
+ RENDER_TIMESTAMP("Render Opaque + Transparent + Tonemap");
+ } else if (using_subpass_transparent) {
+ RENDER_TIMESTAMP("Render Opaque + Transparent");
+ } else {
+ RENDER_TIMESTAMP("Render Opaque");
+ }
- {
- bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
- bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true);
- // regular forward for now
- Vector<Color> c;
- c.push_back(clear_color.to_linear());
+ bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture && !using_ssr && !using_sss;
+ bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture && !using_ssr && !using_sss;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
- _render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- }
+ {
+ // regular forward for now
+ Vector<Color> c;
+ c.push_back(clear_color.to_linear()); // our render buffer
+ if (render_buffer) {
+ if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ c.push_back(clear_color.to_linear()); // our resolve buffer
+ }
+ if (using_subpass_post_process) {
+ c.push_back(Color()); // our 2D buffer we're copying into
+ }
+ }
- RD::get_singleton()->draw_command_end_label();
+ RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ render_list_params.framebuffer_format = fb_format;
+ if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
+ // secondary command buffers need more testing at this time
+ //multi threaded
+ thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ } else {
+ //single threaded
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ _render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
+ }
+ }
- if (draw_sky || draw_sky_fog_only) {
- RENDER_TIMESTAMP("Render Sky");
+ RD::get_singleton()->draw_command_end_label(); //Render Opaque Subpass
- RD::get_singleton()->draw_command_begin_label("Draw Sky");
+ if (draw_sky || draw_sky_fog_only) {
+ RD::get_singleton()->draw_command_begin_label("Draw Sky Subpass");
- if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
- correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
+
+ if (p_render_data->reflection_probe.is_valid()) {
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ CameraMatrix projection = correction * p_render_data->cam_projection;
+ sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ } else {
+ sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
+
+ // note, if MSAA is used in 2-subpass approach we should get an automatic resolve here
} else {
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ // switch to subpass but we do nothing here so basically we skip (though this should trigger resolve with 2-subpass MSAA).
+ RD::get_singleton()->draw_list_switch_to_next_pass();
}
- RD::get_singleton()->draw_command_end_label();
- }
- if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
- /*
- if (using_separate_specular) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular);
+ if (!using_subpass_transparent) {
+ // We're done with our subpasses so end our container pass
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+
+ RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
}
- */
- }
- if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth);
- }
+ if (scene_state.used_screen_texture) {
+ // Copy screen texture to backbuffer so we can read from it
+ _render_buffers_copy_screen_texture(p_render_data);
+ }
- // transparent pass
- RENDER_TIMESTAMP("Render Transparent Pass");
+ if (scene_state.used_depth_texture) {
+ // Copy depth texture to backbuffer so we can read from it
+ _render_buffers_copy_depth_texture(p_render_data);
+ }
- RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
+ // transparent pass
- rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
+ RD::get_singleton()->draw_command_begin_label("Render Transparent Subpass");
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
- {
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
- _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
+ if (using_subpass_transparent) {
+ RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ render_list_params.framebuffer_format = fb_format;
+ if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
+ // secondary command buffers need more testing at this time
+ //multi threaded
+ thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr());
+ render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
+ RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ } else {
+ //single threaded
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
+ render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
+ _render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass
+
+ // note if we are using MSAA we should get an automatic resolve through our subpass configuration.
+
+ // blit to tonemap
+ if (render_buffer && using_subpass_post_process) {
+ _post_process_subpass(render_buffer->color, framebuffer, p_render_data);
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
+
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+ } else {
+ RENDER_TIMESTAMP("Render Transparent");
+
+ framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS];
+
+ // this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
+ // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+
+ RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ render_list_params.framebuffer_format = fb_format;
+ if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
+ // secondary command buffers need more testing at this time
+ //multi threaded
+ thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
+ RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+ } else {
+ //single threaded
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
+ _render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass
+ }
}
- RD::get_singleton()->draw_command_end_label();
+ if (render_buffer && !using_subpass_post_process) {
+ RD::get_singleton()->draw_command_begin_label("Post process pass");
+
+ // If we need extra effects we do this in its own pass
+ RENDER_TIMESTAMP("Tonemap");
- RD::get_singleton()->draw_command_begin_label("Resolve");
+ _render_buffers_post_process_and_tonemap(p_render_data);
- if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
+ RD::get_singleton()->draw_command_end_label(); // Post process pass
}
- RD::get_singleton()->draw_command_end_label();
+ if (render_buffer) {
+ _disable_clear_request(p_render_data);
+ }
}
/* these are being called from RendererSceneRenderRD::_pre_opaque_render */
@@ -635,7 +890,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, true);
uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from;
render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size);
- _fill_instance_data(RENDER_LIST_SECONDARY, render_list_from, render_list_size, false);
+ _fill_element_info(RENDER_LIST_SECONDARY, render_list_from, render_list_size);
{
//regular forward for now
@@ -713,7 +968,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
render_list[RENDER_LIST_SECONDARY].sort_by_key();
- _fill_instance_data(RENDER_LIST_SECONDARY);
+ _fill_element_info(RENDER_LIST_SECONDARY);
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
@@ -754,7 +1009,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
render_list[RENDER_LIST_SECONDARY].sort_by_key();
- _fill_instance_data(RENDER_LIST_SECONDARY);
+ _fill_element_info(RENDER_LIST_SECONDARY);
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
@@ -827,7 +1082,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
render_list[RENDER_LIST_SECONDARY].sort_by_key();
- _fill_instance_data(RENDER_LIST_SECONDARY);
+ _fill_element_info(RENDER_LIST_SECONDARY);
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID());
@@ -1413,9 +1668,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER);
}
-void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) {
- // !BAS! Rename this to make clear this is not the same as with the forward renderer and remove p_update_buffer?
-
+void RenderForwardMobile::_fill_element_info(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements) {
RenderList *rl = &render_list[p_render_list];
uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size();
@@ -1669,7 +1922,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
prev_index_array_rd = index_array_rd;
}
- RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, p_params->subpass);
if (pipeline_rd != prev_pipeline_rd) {
// checking with prev shader does not make so much sense, as
@@ -1684,8 +1937,8 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
}
if (material_uniform_set != prev_material_uniform_set) {
- //update uniform set
- if (material_uniform_set.is_valid()) {
+ // Update uniform set.
+ if (RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);
}
@@ -2325,6 +2578,8 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
+ sky.set_texture_format(_render_buffers_get_color_format());
+
String defines;
defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 973925d562..b981592840 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -92,6 +92,18 @@ protected:
/* Render Buffer */
+ // We can have:
+ // - 4 subpasses combining the full render cycle
+ // - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
+ // - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
+ enum RenderBufferMobileFramebufferConfigType {
+ FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
+ FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
+ FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
+ FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
+ FB_CONFIG_MAX
+ };
+
struct RenderBufferDataForwardMobile : public RenderBufferData {
RID color;
RID depth;
@@ -104,12 +116,12 @@ protected:
RID depth_msaa;
// RID normal_roughness_buffer_msaa;
- RID color_fb;
+ RID color_fbs[FB_CONFIG_MAX];
int width, height;
uint32_t view_count;
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
~RenderBufferDataForwardMobile();
};
@@ -152,6 +164,7 @@ protected:
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
uint32_t barrier = RD::BARRIER_MASK_ALL;
+ uint32_t subpass = 0;
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
@@ -195,7 +208,7 @@ protected:
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
- void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
+ void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);
// void _update_instance_data_buffer(RenderListType p_render_list);
static RenderForwardMobile *singleton;
@@ -576,6 +589,8 @@ protected:
void _update_shader_quality_settings() override;
public:
+ virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
+
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index bcdcb05653..735014a2ec 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -135,8 +135,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
-
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (version.is_null()) {
version = shader_singleton->shader.version_create();
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 18c1fe02a0..f8aefdb29c 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -480,6 +480,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
case Item::Command::TYPE_RECT: {
const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
+ if (rect->flags & CANVAS_RECT_TILE) {
+ current_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
+ }
+
//bind pipeline
{
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
@@ -1089,7 +1093,8 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
if (material_data) {
if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
pipeline_variants = &material_data->shader_data->pipeline_variants;
- if (material_data->uniform_set.is_valid()) {
+ // Update uniform set.
+ if (RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set.
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET);
}
} else {
@@ -1965,8 +1970,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
-
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 15b3b77ed9..8639362da9 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -80,7 +80,7 @@ protected:
Map<RID, RID> render_target_descriptors;
double time;
- float delta;
+ double delta;
static uint64_t frame;
@@ -100,7 +100,7 @@ public:
void finalize();
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
- _ALWAYS_INLINE_ float get_frame_delta_time() const { return delta; }
+ _ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
_ALWAYS_INLINE_ double get_total_time() const { return time; }
static Error is_viable() {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 2e0e7c3c43..5016c99a1e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -629,6 +629,8 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
+ RD::get_singleton()->draw_command_begin_label("Reflection probe render");
+
if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
@@ -675,12 +677,9 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
atlas->reflections.resize(atlas->count);
for (int i = 0; i < atlas->count; i++) {
- atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers);
+ atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
for (int j = 0; j < 6; j++) {
- Vector<RID> fb;
- fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]);
- fb.push_back(atlas->depth_buffer);
- atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb);
+ atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
}
}
@@ -721,9 +720,18 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
rpi->processing_layer = 1;
rpi->processing_side = 0;
+ RD::get_singleton()->draw_command_end_label();
+
return true;
}
+RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
+ Vector<RID> fb;
+ fb.push_back(p_color);
+ fb.push_back(p_depth);
+ return RD::get_singleton()->framebuffer_create(fb);
+}
+
bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
@@ -1456,6 +1464,85 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
base_width = MAX(1, base_width >> 1);
base_height = MAX(1, base_height >> 1);
}
+
+ if (!_render_buffers_can_be_storage()) {
+ // create 4 weight textures, 2 full size, 2 half size
+
+ tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
+ tf.width = rb->width;
+ tf.height = rb->height;
+ tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
+ tf.array_layers = rb->view_count;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.mipmaps = 1;
+ for (uint32_t i = 0; i < 4; i++) {
+ // associated blur texture
+ RID texture;
+ if (i == 0) {
+ texture = rb->texture;
+ } else if (i == 1) {
+ texture = rb->blur[0].mipmaps[0].texture;
+ } else if (i == 2) {
+ texture = rb->blur[1].mipmaps[0].texture;
+ } else if (i == 3) {
+ texture = rb->blur[0].mipmaps[1].texture;
+ }
+
+ // create weight texture
+ rb->weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ // create frame buffer
+ Vector<RID> fb;
+ fb.push_back(texture);
+ fb.push_back(rb->weight_buffers[i].weight);
+ rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
+
+ if (i == 1) {
+ // next 2 are half size
+ tf.width = MAX(1, tf.width >> 1);
+ tf.height = MAX(1, tf.height >> 1);
+ }
+ }
+
+ {
+ // and finally an FB for just our base weights
+ Vector<RID> fb;
+ fb.push_back(rb->weight_buffers[0].weight);
+ rb->base_weight_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ }
+}
+
+void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *rb) {
+ ERR_FAIL_COND(!rb->depth_back_texture.is_null());
+
+ {
+ RD::TextureFormat tf;
+ if (rb->view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
+ // We're not using this as a depth stencil, just copying our data into this. May need to look into using a different format on mobile, maybe R16?
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+
+ tf.width = rb->width;
+ tf.height = rb->height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tf.array_layers = rb->view_count; // create a layer for every view
+
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // set this as color attachment because we're copying data into it, it's not actually used as a depth buffer
+
+ rb->depth_back_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ if (!_render_buffers_can_be_storage()) {
+ // create framebuffer so we can write into this...
+
+ Vector<RID> fb;
+ fb.push_back(rb->depth_back_texture);
+
+ rb->depth_back_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count);
+ }
}
void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
@@ -1524,6 +1611,16 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->depth_texture = RID();
}
+ if (rb->depth_back_fb.is_valid()) {
+ RD::get_singleton()->free(rb->depth_back_fb);
+ rb->depth_back_fb = RID();
+ }
+
+ if (rb->depth_back_texture.is_valid()) {
+ RD::get_singleton()->free(rb->depth_back_texture);
+ rb->depth_back_texture = RID();
+ }
+
for (int i = 0; i < 2; i++) {
for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
// do we free the texture slice here? or is it enough to free the main texture?
@@ -1824,6 +1921,58 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ssao.downsample_uniform_set, rb->ssao.gather_uniform_set, rb->ssao.importance_map_uniform_set);
}
+void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ RD::get_singleton()->draw_command_begin_label("Copy screen texture");
+
+ if (rb->blur[0].texture.is_null()) {
+ _allocate_blur_textures(rb);
+ }
+
+ // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
+
+ bool can_use_storage = _render_buffers_can_be_storage();
+
+ if (can_use_storage) {
+ storage->get_effects()->copy_to_rect(rb->texture, rb->blur[0].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height));
+ for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) {
+ storage->get_effects()->make_mipmap(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].texture, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height));
+ }
+ } else {
+ storage->get_effects()->copy_to_fb_rect(rb->texture, rb->blur[0].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height));
+ for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) {
+ storage->get_effects()->make_mipmap_raster(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].fb, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height));
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ RD::get_singleton()->draw_command_begin_label("Copy depth texture");
+
+ if (rb->depth_back_texture.is_null()) {
+ _allocate_depth_backbuffer_textures(rb);
+ }
+
+ // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
+
+ bool can_use_storage = _render_buffers_can_be_storage();
+
+ if (can_use_storage) {
+ storage->get_effects()->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height));
+ } else {
+ storage->get_effects()->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height));
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -1843,11 +1992,34 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
_allocate_blur_textures(rb);
}
+ EffectsRD::BokehBuffers buffers;
+
+ // textures we use
+ buffers.base_texture_size = Size2i(rb->width, rb->height);
+ buffers.base_texture = rb->texture;
+ buffers.depth_texture = rb->depth_texture;
+ buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
+ buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
+ buffers.half_texture[1] = rb->blur[0].mipmaps[1].texture;
+
+ float bokeh_size = camfx->dof_blur_amount * 64.0;
if (can_use_storage) {
- float bokeh_size = camfx->dof_blur_amount * 64.0;
- storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
} else {
- storage->get_effects()->blur_dof_raster(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->texture_fb, rb->blur[0].mipmaps[0].texture, rb->blur[0].mipmaps[0].fb, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, camfx->dof_blur_amount, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ // set framebuffers
+ buffers.base_fb = rb->texture_fb;
+ buffers.secondary_fb = rb->weight_buffers[1].fb;
+ buffers.half_fb[0] = rb->weight_buffers[2].fb;
+ buffers.half_fb[1] = rb->weight_buffers[3].fb;
+ buffers.weight_texture[0] = rb->weight_buffers[0].weight;
+ buffers.weight_texture[1] = rb->weight_buffers[1].weight;
+ buffers.weight_texture[2] = rb->weight_buffers[2].weight;
+ buffers.weight_texture[3] = rb->weight_buffers[3].weight;
+
+ // set weight buffers
+ buffers.base_weight_fb = rb->base_weight_fb;
+
+ storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1992,6 +2164,74 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
storage->render_target_disable_clear_request(rb->render_target);
}
+void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
+ RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
+
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment);
+
+ bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
+
+ EffectsRD::TonemapSettings tonemap;
+
+ if (env) {
+ tonemap.tonemap_mode = env->tone_mapper;
+ tonemap.exposure = env->exposure;
+ tonemap.white = env->white;
+ }
+
+ // We don't support glow or auto exposure here, if they are needed, don't use subpasses!
+ // The problem is that we need to use the result so far and process them before we can
+ // apply this to our results.
+ if (can_use_effects && env && env->glow_enabled) {
+ ERR_FAIL_MSG("Glow is not supported when using subpasses.");
+ }
+ if (can_use_effects && env && env->auto_exposure) {
+ ERR_FAIL_MSG("Glow is not supported when using subpasses.");
+ }
+
+ tonemap.use_glow = false;
+ tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.use_auto_exposure = false;
+ tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+
+ tonemap.use_color_correction = false;
+ tonemap.use_1d_color_correction = false;
+ tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+
+ if (can_use_effects && env) {
+ tonemap.use_bcs = env->adjustments_enabled;
+ tonemap.brightness = env->adjustments_brightness;
+ tonemap.contrast = env->adjustments_contrast;
+ tonemap.saturation = env->adjustments_saturation;
+ if (env->adjustments_enabled && env->color_correction.is_valid()) {
+ tonemap.use_color_correction = true;
+ tonemap.use_1d_color_correction = env->use_1d_color_correction;
+ tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction);
+ }
+ }
+
+ tonemap.use_debanding = rb->use_debanding;
+ tonemap.texture_size = Vector2i(rb->width, rb->height);
+
+ tonemap.view_count = p_render_data->view_count;
+
+ storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
+
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_data) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ storage->render_target_disable_clear_request(rb->render_target);
+}
+
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
EffectsRD *effects = storage->get_effects();
@@ -2081,6 +2321,15 @@ RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_b
return rb->blur[0].texture;
}
+RID RendererSceneRenderRD::render_buffers_get_back_depth_texture(RID p_render_buffers) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND_V(!rb, RID());
+ if (!rb->depth_back_texture.is_valid()) {
+ return RID(); //not valid at the moment
+ }
+ return rb->depth_back_texture;
+}
+
RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
@@ -2279,12 +2528,11 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.width = rb->width;
tf.height = rb->height;
tf.array_layers = rb->view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
- } else {
- tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
}
+ tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
@@ -2322,7 +2570,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
}
- rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count);
+ RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
+ rb->data->configure(rb->texture, rb->depth_texture, target_texture, p_width, p_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
@@ -2701,7 +2950,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
float bias_scale = li->shadow_transform[j].bias_scale;
- light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale;
+ light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
@@ -2872,14 +3121,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.shadow_enabled = true;
if (type == RS::LIGHT_SPOT) {
- light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
- float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0;
- shadow_texel_size *= light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
-
- light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size;
+ light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0);
} else { //omni
- light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0;
+ light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space
}
@@ -3842,9 +4087,28 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
_render_scene(&render_data, clear_color);
if (p_render_buffers.is_valid()) {
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
+ /*
+ _debug_draw_cluster(p_render_buffers);
+
+ RENDER_TIMESTAMP("Tonemap");
+
+ _render_buffers_post_process_and_tonemap(&render_data);
+ */
+
+ _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
+ rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
+ }
+ }
+}
+
+void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
+ if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) {
+ RS::ViewportDebugDraw dd = get_debug_draw_mode();
+
+ if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX;
- switch (debug_draw) {
+ switch (dd) {
case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS:
elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT;
break;
@@ -3860,17 +4124,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
default: {
}
}
- if (current_cluster_builder != nullptr) {
- current_cluster_builder->debug(elem_type);
- }
- }
-
- RENDER_TIMESTAMP("Tonemap");
-
- _render_buffers_post_process_and_tonemap(&render_data);
- _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
- rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
+ current_cluster_builder->debug(elem_type);
}
}
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index bb06eb608f..5306df36f0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -95,7 +95,7 @@ protected:
double time_step = 0;
struct RenderBufferData {
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
@@ -117,6 +117,7 @@ protected:
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
+ void _debug_draw_cluster(RID p_render_buffers);
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
@@ -133,6 +134,12 @@ protected:
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer);
+ void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
+ void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
+ void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
+ void _post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data);
+ void _disable_clear_request(const RenderDataRD *p_render_data);
+
// needed for a single argument calls (material and uv2)
PagedArrayPool<GeometryInstance *> cull_argument_pool;
PagedArray<GeometryInstance *> cull_argument; //need this to exist
@@ -146,7 +153,7 @@ protected:
} else {
return nullptr;
}
- }
+ };
//used for mobile renderer mostly
@@ -478,6 +485,18 @@ private:
Blur blur[2]; //the second one starts from the first mipmap
+ struct WeightBuffers {
+ RID weight;
+ RID fb; // FB with both texture and weight
+ };
+
+ // 2 full size, 2 half size
+ WeightBuffers weight_buffers[4]; // Only used in raster
+ RID base_weight_fb; // base buffer for weight
+
+ RID depth_back_texture;
+ RID depth_back_fb; // only used on mobile
+
struct Luminance {
Vector<RID> reduce;
RID current;
@@ -521,10 +540,10 @@ private:
void _free_render_buffer_data(RenderBuffers *rb);
void _allocate_blur_textures(RenderBuffers *rb);
+ void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
void _allocate_luminance_textures(RenderBuffers *rb);
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
- void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
/* Cluster */
@@ -923,6 +942,12 @@ public:
virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
+ bool camera_effects_uses_dof(RID p_camera_effects) {
+ CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
+
+ return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
+ }
+
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
@@ -1065,6 +1090,7 @@ public:
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth);
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
@@ -1163,6 +1189,7 @@ public:
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
+ RID render_buffers_get_back_depth_texture(RID p_render_buffers);
RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
RID render_buffers_get_default_voxel_gi_buffer();
RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index bc1603a219..9e85608f1e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -92,8 +92,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
Error err = scene_singleton->sky.sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
-
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (version.is_null()) {
version = scene_singleton->sky.sky_shader.shader.version_create();
@@ -283,14 +282,17 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
RD::DrawListID draw_list = p_list;
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format, false, RD::get_singleton()->draw_list_get_current_pass()));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0);
- if (p_uniform_set.is_valid()) { //material may not have uniform set
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
+ // Update uniform sets.
+ {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0);
+ if (RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
+ }
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
}
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
@@ -313,12 +315,16 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
coefficient_buffer = RID();
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers) {
+void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
//recreate radiance and all data
int mipmaps = p_mipmaps;
uint32_t w = p_size, h = p_size;
+ EffectsRD *effects = p_storage->get_effects();
+ ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
+ bool prefer_raster_effects = effects->get_prefer_raster_effects();
+
if (p_use_array) {
int num_layers = p_low_quality ? 8 : p_roughness_layers;
@@ -377,9 +383,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
}
radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
-
+ RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = p_texture_format;
tf.width = 64; // Always 64x64
tf.height = 64;
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
@@ -388,6 +394,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
{
uint32_t mmw = 64;
uint32_t mmh = 64;
@@ -397,6 +404,18 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
mm.size.width = mmw;
mm.size.height = mmh;
mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP);
+ RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip " + itos(j) + " ");
+ if (prefer_raster_effects) {
+ // we need a framebuffer for each side of our cubemap
+
+ for (int k = 0; k < 6; k++) {
+ mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, k, j);
+ RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip: " + itos(j) + " Face: " + itos(k) + " ");
+ Vector<RID> fbtex;
+ fbtex.push_back(mm.views[k]);
+ mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+ }
mmw = MAX(1, mmw >> 1);
mmh = MAX(1, mmh >> 1);
@@ -405,50 +424,128 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
}
void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
- p_storage->get_effects()->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
+ EffectsRD *effects = p_storage->get_effects();
+ ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
+ bool prefer_raster_effects = effects->get_prefer_raster_effects();
+
+ if (prefer_raster_effects) {
+ RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
+ for (int k = 0; k < 6; k++) {
+ effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
+ }
- for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
- p_storage->get_effects()->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
- }
+ for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
+ for (int k = 0; k < 6; k++) {
+ effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
+ }
+ }
+ RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
- Vector<RID> views;
- if (p_use_arrays) {
- for (int i = 1; i < layers.size(); i++) {
- views.push_back(layers[i].views[0]);
+ if (p_use_arrays) {
+ RD::get_singleton()->draw_command_begin_label("filter radiance map into array heads");
+ for (int i = 0; i < layers.size(); i++) {
+ for (int k = 0; k < 6; k++) {
+ effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i);
+ }
+ }
+ } else {
+ RD::get_singleton()->draw_command_begin_label("filter radiance map into mipmaps directly");
+ for (int j = 0; j < layers[0].mipmaps.size(); j++) {
+ for (int k = 0; k < 6; k++) {
+ effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j);
+ }
+ }
}
+ RD::get_singleton()->draw_command_end_label(); // Filter radiance
} else {
- for (int i = 1; i < layers[0].views.size(); i++) {
- views.push_back(layers[0].views[i]);
+ effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
+
+ for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
+ effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
}
- }
- p_storage->get_effects()->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
+ Vector<RID> views;
+ if (p_use_arrays) {
+ for (int i = 1; i < layers.size(); i++) {
+ views.push_back(layers[i].views[0]);
+ }
+ } else {
+ for (int i = 1; i < layers[0].views.size(); i++) {
+ views.push_back(layers[0].views[i]);
+ }
+ }
+
+ effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
+ }
}
void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
- if (p_use_arrays) {
- //render directly to the layers
- p_storage->get_effects()->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
+ EffectsRD *effects = p_storage->get_effects();
+ ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
+ bool prefer_raster_effects = effects->get_prefer_raster_effects();
+
+ if (prefer_raster_effects) {
+ // Need to ask clayjohn but p_cube_side is set to 10, looks like in the compute shader we're doing all 6 sides in one call
+ // here we need to do them one by one so ignoring p_cube_side
+ if (p_use_arrays) {
+ for (int k = 0; k < 6; k++) {
+ effects->cubemap_roughness_raster(
+ radiance_base_cubemap,
+ layers[p_base_layer].mipmaps[0].framebuffers[k],
+ k,
+ p_sky_ggx_samples_quality,
+ float(p_base_layer) / (layers.size() - 1.0),
+ layers[p_base_layer].mipmaps[0].size.x);
+ }
+ } else {
+ for (int k = 0; k < 6; k++) {
+ effects->cubemap_roughness_raster(
+ layers[0].views[p_base_layer - 1],
+ layers[0].mipmaps[p_base_layer].framebuffers[k],
+ k,
+ p_sky_ggx_samples_quality,
+ float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
+ layers[0].mipmaps[p_base_layer].size.x);
+ }
+ }
} else {
- p_storage->get_effects()->cubemap_roughness(
- layers[0].views[p_base_layer - 1],
- layers[0].views[p_base_layer],
- p_cube_side,
- p_sky_ggx_samples_quality,
- float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
- layers[0].mipmaps[p_base_layer].size.x);
+ if (p_use_arrays) {
+ //render directly to the layers
+ effects->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
+ } else {
+ effects->cubemap_roughness(
+ layers[0].views[p_base_layer - 1],
+ layers[0].views[p_base_layer],
+ p_cube_side,
+ p_sky_ggx_samples_quality,
+ float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
+ layers[0].mipmaps[p_base_layer].size.x);
+ }
}
}
void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) {
+ EffectsRD *effects = p_storage->get_effects();
+ ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
+ bool prefer_raster_effects = effects->get_prefer_raster_effects();
+
+ RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps");
for (int i = p_start; i < p_end; i++) {
for (int j = 0; j < layers[i].views.size() - 1; j++) {
RID view = layers[i].views[j];
- RID texture = layers[i].views[j + 1];
Size2i size = layers[i].mipmaps[j + 1].size;
- p_storage->get_effects()->cubemap_downsample(view, texture, size);
+ if (prefer_raster_effects) {
+ for (int k = 0; k < 6; k++) {
+ RID framebuffer = layers[i].mipmaps[j + 1].framebuffers[k];
+ effects->cubemap_downsample_raster(view, framebuffer, k, size);
+ }
+ } else {
+ RID texture = layers[i].views[j + 1];
+ effects->cubemap_downsample(view, texture, size);
+ }
}
}
+ RD::get_singleton()->draw_command_end_label();
}
////////////////////////////////////////////////////////////////////////////////
@@ -902,6 +999,10 @@ void sky() {
}
}
+void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
+ texture_format = p_texture_format;
+}
+
RendererSceneSkyRD::~RendererSceneSkyRD() {
// TODO cleanup anything created in init...
@@ -1170,6 +1271,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
cm = correction * cm;
if (shader_data->uses_quarter_res) {
+ RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
Vector<Color> clear_colors;
@@ -1177,17 +1279,18 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::DrawListID cubemap_draw_list;
for (int i = 0; i < 6; i++) {
- Transform3D local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
+ RD::get_singleton()->draw_command_end_label();
}
if (shader_data->uses_half_res) {
+ RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
Vector<Color> clear_colors;
@@ -1195,28 +1298,29 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::DrawListID cubemap_draw_list;
for (int i = 0; i < 6; i++) {
- Transform3D local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
+ RD::get_singleton()->draw_command_end_label();
}
RD::DrawListID cubemap_draw_list;
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
+ RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap");
for (int i = 0; i < 6; i++) {
- Transform3D local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
+ RD::get_singleton()->draw_command_end_label();
if (sky_mode == RS::SKY_MODE_REALTIME) {
sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array);
@@ -1362,6 +1466,179 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
RD::get_singleton()->draw_list_end();
}
+void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+ ERR_FAIL_COND(!p_env);
+
+ ERR_FAIL_COND(p_view_count == 0);
+ ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
+
+ Sky *sky = get_sky(p_env->sky);
+ ERR_FAIL_COND(!sky);
+
+ SkyMaterialData *material = nullptr;
+ RID sky_material;
+
+ RS::EnvironmentBG background = p_env->background;
+
+ if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
+ ERR_FAIL_COND(!sky);
+ sky_material = sky_get_material(p_env->sky);
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+ }
+
+ if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
+ sky_material = sky_scene_state.fog_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ Basis sky_transform = p_env->sky_orientation;
+ sky_transform.invert();
+
+ float multiplier = p_env->bg_energy;
+ float custom_fov = p_env->sky_custom_fov;
+
+ // Camera
+ CameraMatrix camera;
+ uint32_t view_count = p_view_count;
+ const CameraMatrix *projections = p_projections;
+
+ if (custom_fov) {
+ // With custom fov we don't support stereo...
+ float near_plane = p_projections[0].get_z_near();
+ float far_plane = p_projections[0].get_z_far();
+ float aspect = p_projections[0].get_aspect();
+
+ camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
+
+ view_count = 1;
+ projections = &camera;
+ }
+
+ sky_transform = p_transform.basis * sky_transform;
+
+ if (shader_data->uses_quarter_res) {
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
+
+ RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ if (shader_data->uses_half_res) {
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
+
+ RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
+
+ Vector<Color> clear_colors;
+ clear_colors.push_back(Color(0.0, 0.0, 0.0));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
+void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+ ERR_FAIL_COND(!p_env);
+
+ ERR_FAIL_COND(p_view_count == 0);
+ ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
+
+ Sky *sky = get_sky(p_env->sky);
+ ERR_FAIL_COND(!sky);
+
+ SkyMaterialData *material = nullptr;
+ RID sky_material;
+
+ RS::EnvironmentBG background = p_env->background;
+
+ if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
+ ERR_FAIL_COND(!sky);
+ sky_material = sky_get_material(p_env->sky);
+
+ if (sky_material.is_valid()) {
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ sky_material = sky_shader.default_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+ }
+
+ if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
+ sky_material = sky_scene_state.fog_material;
+ material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ SkyShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ Basis sky_transform = p_env->sky_orientation;
+ sky_transform.invert();
+
+ float multiplier = p_env->bg_energy;
+ float custom_fov = p_env->sky_custom_fov;
+
+ // Camera
+ CameraMatrix camera;
+ uint32_t view_count = p_view_count;
+ const CameraMatrix *projections = p_projections;
+
+ if (custom_fov) {
+ // With custom fov we don't support stereo...
+ float near_plane = p_projections[0].get_z_near();
+ float far_plane = p_projections[0].get_z_far();
+ float aspect = p_projections[0].get_aspect();
+
+ camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
+
+ view_count = 1;
+ projections = &camera;
+ }
+
+ sky_transform = p_transform.basis * sky_transform;
+
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
+
+ RID texture_uniform_set;
+ if (sky) {
+ texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
+ } else {
+ texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
+ }
+
+ _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+}
+
void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
if (!p_sky->dirty) {
p_sky->dirty = true;
@@ -1393,7 +1670,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
//array (higher quality, 6 times more memory)
RD::TextureFormat tf;
tf.array_layers = layers * 6;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = texture_format;
tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
tf.mipmaps = mipmaps;
tf.width = w;
@@ -1402,13 +1679,13 @@ void RendererSceneSkyRD::update_dirty_skys() {
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
- sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
+ sky->reflection.update_reflection_data(storage, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
} else {
//regular cubemap, lower quality (aliasing, less memory)
RD::TextureFormat tf;
tf.array_layers = 6;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = texture_format;
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
tf.mipmaps = MIN(mipmaps, layers);
tf.width = w;
@@ -1417,7 +1694,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
- sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
+ sky->reflection.update_reflection_data(storage, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
}
texture_set_dirty = true;
}
@@ -1425,7 +1702,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
// Create subpass buffers if they haven't been created already
if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tformat.format = texture_format;
tformat.width = sky->screen_size.x / 2;
tformat.height = sky->screen_size.y / 2;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1440,7 +1717,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tformat.format = texture_format;
tformat.width = sky->screen_size.x / 4;
tformat.height = sky->screen_size.y / 4;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 4f852e55a7..7b670bddd5 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -64,6 +64,7 @@ public:
private:
RendererStorageRD *storage;
+ RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
RID index_array;
@@ -190,6 +191,10 @@ public:
struct Mipmap {
RID view;
Size2i size;
+
+ // for mobile only
+ RID views[6];
+ RID framebuffers[6];
};
Vector<Mipmap> mipmaps;
};
@@ -204,7 +209,7 @@ public:
Vector<Layer> layers;
void clear_reflection_data();
- void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers);
+ void update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
void create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays);
void create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
@@ -284,11 +289,14 @@ public:
RendererSceneSkyRD();
void init(RendererStorageRD *p_storage);
+ void set_texture_format(RD::DataFormat p_texture_format);
~RendererSceneSkyRD();
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
+ void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
+ void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index d5c7db6fd2..7d438345f1 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -3453,6 +3453,7 @@ void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances
if (multimesh->buffer.is_valid()) {
RD::get_singleton()->free(multimesh->buffer);
multimesh->buffer = RID();
+ multimesh->uniform_set_2d = RID(); //cleared by dependency
multimesh->uniform_set_3d = RID(); //cleared by dependency
}
@@ -4091,7 +4092,7 @@ void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) {
particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
}
-void RendererStorageRD::particles_set_lifetime(RID p_particles, float p_lifetime) {
+void RendererStorageRD::particles_set_lifetime(RID p_particles, double p_lifetime) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->lifetime = p_lifetime;
@@ -4103,17 +4104,17 @@ void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot)
particles->one_shot = p_one_shot;
}
-void RendererStorageRD::particles_set_pre_process_time(RID p_particles, float p_time) {
+void RendererStorageRD::particles_set_pre_process_time(RID p_particles, double p_time) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->pre_process_time = p_time;
}
-void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, float p_ratio) {
+void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->explosiveness = p_ratio;
}
-void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, float p_ratio) {
+void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->randomness = p_ratio;
@@ -4126,7 +4127,7 @@ void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p
particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
-void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) {
+void RendererStorageRD::particles_set_speed_scale(RID p_particles, double p_scale) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
@@ -4169,7 +4170,7 @@ void RendererStorageRD::particles_set_fractional_delta(RID p_particles, bool p_e
particles->fractional_delta = p_enable;
}
-void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, float p_length) {
+void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
ERR_FAIL_COND(p_length < 0.1);
@@ -4205,7 +4206,7 @@ void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Ve
particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
}
-void RendererStorageRD::particles_set_collision_base_size(RID p_particles, float p_size) {
+void RendererStorageRD::particles_set_collision_base_size(RID p_particles, real_t p_size) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
@@ -4442,7 +4443,7 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool
particles->sdf_collision_texture = p_texture;
}
-void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
+void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) {
if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -4491,7 +4492,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
}
- float new_phase = Math::fmod((float)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, (float)1.0);
+ double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
//move back history (if there is any)
for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
@@ -5131,14 +5132,14 @@ void RendererStorageRD::update_particles() {
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
if (particles->clear && particles->pre_process_time > 0.0) {
- float frame_time;
+ double frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
- float todo = particles->pre_process_time;
+ double todo = particles->pre_process_time;
while (todo >= 0) {
_particles_process(particles, frame_time);
@@ -5147,8 +5148,8 @@ void RendererStorageRD::update_particles() {
}
if (fixed_fps > 0) {
- float frame_time;
- float decr;
+ double frame_time;
+ double decr;
if (zero_time_scale) {
frame_time = 0.0;
decr = 1.0 / fixed_fps;
@@ -5156,13 +5157,13 @@ void RendererStorageRD::update_particles() {
frame_time = 1.0 / fixed_fps;
decr = frame_time;
}
- float delta = RendererCompositorRD::singleton->get_frame_delta_time();
+ double delta = RendererCompositorRD::singleton->get_frame_delta_time();
if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
delta = 0.1;
} else if (delta <= 0.0) { //unlikely but..
delta = 0.001;
}
- float todo = particles->frame_remainder + delta;
+ double todo = particles->frame_remainder + delta;
while (todo >= frame_time) {
_particles_process(particles, frame_time);
@@ -5267,8 +5268,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
-
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (version.is_null()) {
version = base_singleton->particles_shader.shader.version_create();
@@ -5463,7 +5463,7 @@ void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collis
particles_collision->cull_mask = p_cull_mask;
}
-void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) {
+void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
@@ -5479,21 +5479,21 @@ void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_coll
particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
-void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) {
+void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->attractor_strength = p_strength;
}
-void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) {
+void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
particles_collision->attractor_directionality = p_directionality;
}
-void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) {
+void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
@@ -9128,26 +9128,42 @@ RendererStorageRD::RendererStorageRD() {
} break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
} break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
} break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
sampler_state.use_anisotropy = true;
sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
} break;
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
sampler_state.use_anisotropy = true;
sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index b290c07705..c048be5dc8 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -663,19 +663,19 @@ private:
uint32_t type;
uint32_t texture_index; //texture index for vector field
- float scale;
+ real_t scale;
uint32_t pad[2];
};
uint32_t emitting;
- float system_phase;
- float prev_system_phase;
+ double system_phase;
+ double prev_system_phase;
uint32_t cycle;
- float explosiveness;
- float randomness;
- float time;
- float delta;
+ real_t explosiveness;
+ real_t randomness;
+ double time;
+ double delta;
uint32_t frame;
uint32_t pad0;
@@ -715,14 +715,14 @@ private:
struct Particles {
RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
bool inactive = true;
- float inactive_time = 0.0;
+ double inactive_time = 0.0;
bool emitting = false;
bool one_shot = false;
int amount = 0;
- float lifetime = 1.0;
- float pre_process_time = 0.0;
- float explosiveness = 0.0;
- float randomness = 0.0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness = 0.0;
+ real_t randomness = 0.0;
bool restart_request = false;
AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
bool use_local_coords = true;
@@ -766,20 +766,20 @@ private:
RID sub_emitter;
- float phase = 0.0;
- float prev_phase = 0.0;
+ double phase = 0.0;
+ double prev_phase = 0.0;
uint64_t prev_ticks = 0;
uint32_t random_seed = 0;
uint32_t cycle_number = 0;
- float speed_scale = 1.0;
+ double speed_scale = 1.0;
int fixed_fps = 30;
bool interpolate = true;
bool fractional_delta = false;
- float frame_remainder = 0;
- float collision_base_size = 0.01;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
bool clear = true;
@@ -796,7 +796,7 @@ private:
Dependency dependency;
- float trail_length = 1.0;
+ double trail_length = 1.0;
bool trails_enabled = false;
LocalVector<ParticlesFrameParams> frame_history;
LocalVector<ParticlesFrameParams> trail_params;
@@ -805,14 +805,14 @@ private:
}
};
- void _particles_process(Particles *p_particles, float p_delta);
+ void _particles_process(Particles *p_particles, double p_delta);
void _particles_allocate_emission_buffer(Particles *particles);
void _particles_free_data(Particles *particles);
void _particles_update_buffers(Particles *particles);
struct ParticlesShader {
struct PushConstant {
- float lifetime;
+ double lifetime;
uint32_t clear;
uint32_t total_particles;
uint32_t trail_size;
@@ -2144,22 +2144,22 @@ public:
void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode);
void particles_set_emitting(RID p_particles, bool p_emitting);
void particles_set_amount(RID p_particles, int p_amount);
- void particles_set_lifetime(RID p_particles, float p_lifetime);
+ void particles_set_lifetime(RID p_particles, double p_lifetime);
void particles_set_one_shot(RID p_particles, bool p_one_shot);
- void particles_set_pre_process_time(RID p_particles, float p_time);
- void particles_set_explosiveness_ratio(RID p_particles, float p_ratio);
- void particles_set_randomness_ratio(RID p_particles, float p_ratio);
+ void particles_set_pre_process_time(RID p_particles, double p_time);
+ void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio);
+ void particles_set_randomness_ratio(RID p_particles, real_t p_ratio);
void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
- void particles_set_speed_scale(RID p_particles, float p_scale);
+ void particles_set_speed_scale(RID p_particles, double p_scale);
void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
void particles_set_process_material(RID p_particles, RID p_material);
void particles_set_fixed_fps(RID p_particles, int p_fps);
void particles_set_interpolate(RID p_particles, bool p_enable);
void particles_set_fractional_delta(RID p_particles, bool p_enable);
- void particles_set_collision_base_size(RID p_particles, float p_size);
+ void particles_set_collision_base_size(RID p_particles, real_t p_size);
void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align);
- void particles_set_trails(RID p_particles, bool p_enable, float p_length);
+ void particles_set_trails(RID p_particles, bool p_enable, double p_length);
void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses);
void particles_restart(RID p_particles);
@@ -2252,11 +2252,11 @@ public:
virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type);
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask);
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius); //for spheres
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius); //for spheres
virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents); //for non-spheres
- virtual void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength);
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality);
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve);
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength);
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality);
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve);
virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture); //for SDF and vector field, heightfield is dynamic
virtual void particles_collision_height_field_update(RID p_particles_collision); //for SDF and vector field
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution); //for SDF and vector field
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 9c1068ea2e..8aa03b6426 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -887,7 +887,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
bool use_fragment_varying = false;
- if (!(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
+ if (!vnode->is_local && !(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
if (p_assigning) {
if (shader->varyings.has(vnode->name)) {
use_fragment_varying = true;
@@ -1037,7 +1037,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
bool use_fragment_varying = false;
- if (!(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
+ if (!anode->is_local && !(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
if (anode->assign_expression != nullptr && shader->varyings.has(anode->name)) {
use_fragment_varying = true;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
index b1d1c2365e..0789a4b396 100644
--- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
@@ -37,32 +37,6 @@ layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(location = 0) out vec4 frag_color;
-//DOF
-#ifdef MODE_DOF_BLUR
-
-layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
-
-#ifdef DOF_QUALITY_LOW
-const int dof_kernel_size = 5;
-const int dof_kernel_from = 2;
-const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
-#endif
-
-#ifdef DOF_QUALITY_MEDIUM
-const int dof_kernel_size = 11;
-const int dof_kernel_from = 5;
-const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
-
-#endif
-
-#ifdef DOF_QUALITY_HIGH
-const int dof_kernel_size = 21;
-const int dof_kernel_from = 10;
-const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
-#endif
-
-#endif
-
void main() {
#ifdef MODE_MIPMAP
@@ -155,74 +129,8 @@ void main() {
#endif
-#ifdef MODE_DOF_BLUR
-
- vec4 color_accum = vec4(0.0);
-
- float depth = texture(dof_source_depth, uv_interp, 0.0).r;
- depth = depth * 2.0 - 1.0;
-
- if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
- depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
- } else {
- depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
- }
-
- // mix near and far blur amount
- float amount = 1.0;
- if (bool(blur.flags & FLAG_DOF_FAR)) {
- amount *= 1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, depth);
- }
- if (bool(blur.flags & FLAG_DOF_NEAR)) {
- amount *= smoothstep(blur.dof_near_end, blur.dof_near_begin, depth);
- }
- amount = 1.0 - amount;
-
- if (amount > 0.0) {
- float k_accum = 0.0;
-
- for (int i = 0; i < dof_kernel_size; i++) {
- int int_ofs = i - dof_kernel_from;
- vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius;
-
- float tap_k = dof_kernel[i];
-
- float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
- tap_depth = tap_depth * 2.0 - 1.0;
-
- if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
- tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
- } else {
- tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
- }
-
- // mix near and far blur amount
- float tap_amount = 1.0;
- if (bool(blur.flags & FLAG_DOF_FAR)) {
- tap_amount *= mix(1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, tap_depth), 0.0, int_ofs == 0);
- }
- if (bool(blur.flags & FLAG_DOF_NEAR)) {
- tap_amount *= mix(smoothstep(blur.dof_near_end, blur.dof_near_begin, tap_depth), 0.0, int_ofs == 0);
- }
- tap_amount = 1.0 - tap_amount;
-
- tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
-
- vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k;
-
- k_accum += tap_k * tap_amount;
- color_accum += tap_color * tap_amount;
- }
-
- if (k_accum > 0.0) {
- color_accum /= k_accum;
- }
-
- frag_color = color_accum; ///k_accum;
- } else {
- // we are in focus, don't waste time
- frag_color = texture(source_color, uv_interp, 0.0);
- }
-
+#ifdef MODE_COPY
+ vec4 color = textureLod(source_color, uv_interp, 0.0);
+ frag_color = color;
#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
index 6ea968e595..52bf2886b5 100644
--- a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
@@ -1,8 +1,6 @@
#define FLAG_HORIZONTAL (1 << 0)
#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
#define FLAG_GLOW_FIRST_PASS (1 << 2)
-#define FLAG_DOF_FAR (1 << 3)
-#define FLAG_DOF_NEAR (1 << 4)
layout(push_constant, binding = 1, std430) uniform Blur {
vec2 pixel_size;
@@ -19,18 +17,5 @@ layout(push_constant, binding = 1, std430) uniform Blur {
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
-
- // DOF.
- float dof_far_begin;
- float dof_far_end;
- float dof_near_begin;
- float dof_near_end;
-
- float dof_radius;
- float dof_pad[3];
-
- vec2 dof_dir;
- float camera_z_far;
- float camera_z_near;
}
blur;
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl
index b70e0b6bd5..0438671dd2 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl
@@ -25,34 +25,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
// based on https://www.shadertoy.com/view/Xd3GDl
-layout(push_constant, binding = 1, std430) uniform Params {
- ivec2 size;
- float z_far;
- float z_near;
-
- bool orthogonal;
- float blur_size;
- float blur_scale;
- int blur_steps;
-
- bool blur_near_active;
- float blur_near_begin;
- float blur_near_end;
- bool blur_far_active;
-
- float blur_far_begin;
- float blur_far_end;
- bool second_pass;
- bool half_size;
-
- bool use_jitter;
- float jitter_seed;
- uint pad[2];
-}
-params;
-
-//used to work around downsampling filter
-#define DEPTH_GAP 0.0
+#include "bokeh_dof_inc.glsl"
#ifdef MODE_GEN_BLUR_SIZE
@@ -80,15 +53,6 @@ float get_blur_size(float depth) {
#endif
-const float GOLDEN_ANGLE = 2.39996323;
-
-//note: uniform pdf rand [0;1[
-float hash12n(vec2 p) {
- p = fract(p * vec2(5.3987, 5.4421));
- p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
- return fract(p.x * p.y * 95.4307);
-}
-
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl
new file mode 100644
index 0000000000..fadea1631c
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl
@@ -0,0 +1,37 @@
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec2 size;
+ float z_far;
+ float z_near;
+
+ bool orthogonal;
+ float blur_size;
+ float blur_scale;
+ int blur_steps;
+
+ bool blur_near_active;
+ float blur_near_begin;
+ float blur_near_end;
+ bool blur_far_active;
+
+ float blur_far_begin;
+ float blur_far_end;
+ bool second_pass;
+ bool half_size;
+
+ bool use_jitter;
+ float jitter_seed;
+ uint pad[2];
+}
+params;
+
+//used to work around downsampling filter
+#define DEPTH_GAP 0.0
+
+const float GOLDEN_ANGLE = 2.39996323;
+
+//note: uniform pdf rand [0;1[
+float hash12n(vec2 p) {
+ p = fract(p * vec2(5.3987, 5.4421));
+ p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
+ return fract(p.x * p.y * 95.4307);
+}
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
new file mode 100644
index 0000000000..43a2a29616
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
@@ -0,0 +1,253 @@
+/* clang-format off */
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "bokeh_dof_inc.glsl"
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+}
+
+/* clang-format off */
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "bokeh_dof_inc.glsl"
+
+layout(location = 0) in vec2 uv_interp;
+/* clang-format on */
+
+#ifdef MODE_GEN_BLUR_SIZE
+layout(location = 0) out float weight;
+
+layout(set = 0, binding = 0) uniform sampler2D source_depth;
+#else
+layout(location = 0) out vec4 frag_color;
+#ifdef OUTPUT_WEIGHT
+layout(location = 1) out float weight;
+#endif
+
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+layout(set = 1, binding = 0) uniform sampler2D source_weight;
+#ifdef MODE_COMPOSITE_BOKEH
+layout(set = 2, binding = 0) uniform sampler2D original_weight;
+#endif
+#endif
+
+//DOF
+// Bokeh single pass implementation based on http://tuxedolabs.blogspot.com/2018/05/bokeh-depth-of-field-in-single-pass.html
+
+#ifdef MODE_GEN_BLUR_SIZE
+
+float get_depth_at_pos(vec2 uv) {
+ float depth = textureLod(source_depth, uv, 0.0).x;
+ if (params.orthogonal) {
+ depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ } else {
+ depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ }
+ return depth;
+}
+
+float get_blur_size(float depth) {
+ if (params.blur_near_active && depth < params.blur_near_begin) {
+ return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
+ }
+
+ if (params.blur_far_active && depth > params.blur_far_begin) {
+ return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ }
+
+ return 0.0;
+}
+
+#endif
+
+#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
+
+vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
+ dir *= pixel_size;
+ vec4 color = texture(source_color, uv);
+ color.a = texture(source_weight, uv).r;
+
+ vec4 accum = color;
+ float total = 1.0;
+
+ float blur_scale = params.blur_size / float(params.blur_steps);
+
+ if (params.use_jitter) {
+ uv += dir * (hash12n(uv + params.jitter_seed) - 0.5);
+ }
+
+ for (int i = -params.blur_steps; i <= params.blur_steps; i++) {
+ if (i == 0) {
+ continue;
+ }
+ float radius = float(i) * blur_scale;
+ vec2 suv = uv + dir * radius;
+ radius = abs(radius);
+
+ vec4 sample_color = texture(source_color, suv);
+ sample_color.a = texture(source_weight, suv).r;
+ float limit;
+
+ if (sample_color.a < color.a) {
+ limit = abs(sample_color.a);
+ } else {
+ limit = abs(color.a);
+ }
+
+ limit -= DEPTH_GAP;
+
+ float m = smoothstep(radius - 0.5, radius + 0.5, limit);
+
+ accum += mix(color, sample_color, m);
+
+ total += 1.0;
+ }
+
+ return accum / total;
+}
+
+#endif
+
+void main() {
+ vec2 pixel_size = 1.0 / vec2(params.size);
+ vec2 uv = uv_interp;
+
+#ifdef MODE_GEN_BLUR_SIZE
+ uv += pixel_size * 0.5;
+ float center_depth = get_depth_at_pos(uv);
+ weight = get_blur_size(center_depth);
+#endif
+
+#ifdef MODE_BOKEH_BOX
+ //pixel_size*=0.5; //resolution is doubled
+ if (params.second_pass || !params.half_size) {
+ uv += pixel_size * 0.5; //half pixel to read centers
+ } else {
+ uv += pixel_size * 0.25; //half pixel to read centers from full res
+ }
+
+ float alpha = texture(source_color, uv).a; // retain this
+ vec2 dir = (params.second_pass ? vec2(0.0, 1.0) : vec2(1.0, 0.0));
+
+ vec4 color = weighted_filter_dir(dir, uv, pixel_size);
+
+ frag_color = color;
+ frag_color.a = alpha; // attempt to retain this in case we have a transparent background, ignored if half_size
+#ifdef OUTPUT_WEIGHT
+ weight = color.a;
+#endif
+
+#endif
+
+#ifdef MODE_BOKEH_HEXAGONAL
+
+ //pixel_size*=0.5; //resolution is doubled
+ if (params.second_pass || !params.half_size) {
+ uv += pixel_size * 0.5; //half pixel to read centers
+ } else {
+ uv += pixel_size * 0.25; //half pixel to read centers from full res
+ }
+
+ float alpha = texture(source_color, uv).a; // retain this
+
+ vec2 dir = (params.second_pass ? normalize(vec2(1.0, 0.577350269189626)) : vec2(0.0, 1.0));
+
+ vec4 color = weighted_filter_dir(dir, uv, pixel_size);
+
+ if (params.second_pass) {
+ dir = normalize(vec2(-1.0, 0.577350269189626));
+
+ vec4 color2 = weighted_filter_dir(dir, uv, pixel_size);
+
+ color.rgb = min(color.rgb, color2.rgb);
+ color.a = (color.a + color2.a) * 0.5;
+ }
+
+ frag_color = color;
+ frag_color.a = alpha; // attempt to retain this in case we have a transparent background, ignored if half_size
+#ifdef OUTPUT_WEIGHT
+ weight = color.a;
+#endif
+
+#endif
+
+#ifdef MODE_BOKEH_CIRCULAR
+ if (params.half_size) {
+ pixel_size *= 0.5; //resolution is doubled
+ }
+
+ uv += pixel_size * 0.5; //half pixel to read centers
+
+ vec4 color = texture(source_color, uv);
+ float alpha = color.a; // retain this
+ color.a = texture(source_weight, uv).r;
+
+ vec4 color_accum = color;
+ float accum = 1.0;
+
+ float radius = params.blur_scale;
+ for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) {
+ vec2 uv_adj = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;
+
+ vec4 sample_color = texture(source_color, uv_adj);
+ sample_color.a = texture(source_weight, uv_adj).r;
+
+ float limit;
+
+ if (sample_color.a < color.a) {
+ limit = abs(sample_color.a);
+ } else {
+ limit = abs(color.a);
+ }
+
+ limit -= DEPTH_GAP;
+
+ float m = smoothstep(radius - 0.5, radius + 0.5, limit);
+ color_accum += mix(color_accum / accum, sample_color, m);
+ accum += 1.0;
+
+ radius += params.blur_scale / radius;
+ }
+
+ color_accum = color_accum / accum;
+
+ frag_color.rgb = color_accum.rgb;
+ frag_color.a = alpha; // attempt to retain this in case we have a transparent background, ignored if half_size
+#ifdef OUTPUT_WEIGHT
+ weight = color_accum.a;
+#endif
+
+#endif
+
+#ifdef MODE_COMPOSITE_BOKEH
+ frag_color.rgb = texture(source_color, uv).rgb;
+
+ float center_weigth = texture(source_weight, uv).r;
+ float sample_weight = texture(original_weight, uv).r;
+
+ float mix_amount;
+ if (sample_weight < center_weigth) {
+ mix_amount = min(1.0, max(0.0, max(abs(center_weigth), abs(sample_weight)) - DEPTH_GAP));
+ } else {
+ mix_amount = min(1.0, max(0.0, abs(center_weigth) - DEPTH_GAP));
+ }
+
+ // let alpha blending take care of mixing
+ frag_color.a = mix_amount;
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl
index 9fa84657d1..63f0ce690e 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl
+++ b/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl
@@ -32,53 +32,7 @@ layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
-layout(push_constant, binding = 1, std430) uniform Params {
- uint face_size;
-}
-params;
-
-#define M_PI 3.14159265359
-
-void get_dir_0(out vec3 dir, in float u, in float v) {
- dir[0] = 1.0;
- dir[1] = v;
- dir[2] = -u;
-}
-
-void get_dir_1(out vec3 dir, in float u, in float v) {
- dir[0] = -1.0;
- dir[1] = v;
- dir[2] = u;
-}
-
-void get_dir_2(out vec3 dir, in float u, in float v) {
- dir[0] = u;
- dir[1] = 1.0;
- dir[2] = -v;
-}
-
-void get_dir_3(out vec3 dir, in float u, in float v) {
- dir[0] = u;
- dir[1] = -1.0;
- dir[2] = v;
-}
-
-void get_dir_4(out vec3 dir, in float u, in float v) {
- dir[0] = u;
- dir[1] = v;
- dir[2] = 1.0;
-}
-
-void get_dir_5(out vec3 dir, in float u, in float v) {
- dir[0] = -u;
- dir[1] = v;
- dir[2] = -1.0;
-}
-
-float calcWeight(float u, float v) {
- float val = u * u + v * v + 1.0;
- return val * sqrt(val);
-}
+#include "cubemap_downsampler_inc.glsl"
void main() {
uvec3 id = gl_GlobalInvocationID;
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl b/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl
new file mode 100644
index 0000000000..b329e67293
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl
@@ -0,0 +1,48 @@
+layout(push_constant, binding = 1, std430) uniform Params {
+ uint face_size;
+ uint face_id; // only used in raster shader
+}
+params;
+
+#define M_PI 3.14159265359
+
+void get_dir_0(out vec3 dir, in float u, in float v) {
+ dir[0] = 1.0;
+ dir[1] = v;
+ dir[2] = -u;
+}
+
+void get_dir_1(out vec3 dir, in float u, in float v) {
+ dir[0] = -1.0;
+ dir[1] = v;
+ dir[2] = u;
+}
+
+void get_dir_2(out vec3 dir, in float u, in float v) {
+ dir[0] = u;
+ dir[1] = 1.0;
+ dir[2] = -v;
+}
+
+void get_dir_3(out vec3 dir, in float u, in float v) {
+ dir[0] = u;
+ dir[1] = -1.0;
+ dir[2] = v;
+}
+
+void get_dir_4(out vec3 dir, in float u, in float v) {
+ dir[0] = u;
+ dir[1] = v;
+ dir[2] = 1.0;
+}
+
+void get_dir_5(out vec3 dir, in float u, in float v) {
+ dir[0] = -u;
+ dir[1] = v;
+ dir[2] = -1.0;
+}
+
+float calcWeight(float u, float v) {
+ float val = u * u + v * v + 1.0;
+ return val * sqrt(val);
+}
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl b/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl
new file mode 100644
index 0000000000..0828ffd921
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl
@@ -0,0 +1,163 @@
+// Copyright 2016 Activision Publishing, Inc.
+//
+// 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.
+
+/* clang-format off */
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "cubemap_downsampler_inc.glsl"
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex] * float(params.face_size);
+ gl_Position = vec4(base_arr[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
+}
+
+/* clang-format off */
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "cubemap_downsampler_inc.glsl"
+
+layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
+
+layout(location = 0) in vec2 uv_interp;
+layout(location = 0) out vec4 frag_color;
+/* clang-format on */
+
+void main() {
+ // Converted from compute shader which uses absolute coordinates.
+ // Could possibly simplify this
+ float face_size = float(params.face_size);
+
+ if (uv_interp.x < face_size && uv_interp.y < face_size) {
+ float inv_face_size = 1.0 / face_size;
+
+ float u0 = (uv_interp.x * 2.0 + 1.0 - 0.75) * inv_face_size - 1.0;
+ float u1 = (uv_interp.x * 2.0 + 1.0 + 0.75) * inv_face_size - 1.0;
+
+ float v0 = (uv_interp.y * 2.0 + 1.0 - 0.75) * -inv_face_size + 1.0;
+ float v1 = (uv_interp.y * 2.0 + 1.0 + 0.75) * -inv_face_size + 1.0;
+
+ float weights[4];
+ weights[0] = calcWeight(u0, v0);
+ weights[1] = calcWeight(u1, v0);
+ weights[2] = calcWeight(u0, v1);
+ weights[3] = calcWeight(u1, v1);
+
+ const float wsum = 0.5 / (weights[0] + weights[1] + weights[2] + weights[3]);
+ for (int i = 0; i < 4; i++) {
+ weights[i] = weights[i] * wsum + .125;
+ }
+
+ vec3 dir;
+ vec4 color;
+ switch (params.face_id) {
+ case 0:
+ get_dir_0(dir, u0, v0);
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
+
+ get_dir_0(dir, u1, v0);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
+
+ get_dir_0(dir, u0, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
+
+ get_dir_0(dir, u1, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
+ break;
+ case 1:
+ get_dir_1(dir, u0, v0);
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
+
+ get_dir_1(dir, u1, v0);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
+
+ get_dir_1(dir, u0, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
+
+ get_dir_1(dir, u1, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
+ break;
+ case 2:
+ get_dir_2(dir, u0, v0);
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
+
+ get_dir_2(dir, u1, v0);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
+
+ get_dir_2(dir, u0, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
+
+ get_dir_2(dir, u1, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
+ break;
+ case 3:
+ get_dir_3(dir, u0, v0);
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
+
+ get_dir_3(dir, u1, v0);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
+
+ get_dir_3(dir, u0, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
+
+ get_dir_3(dir, u1, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
+ break;
+ case 4:
+ get_dir_4(dir, u0, v0);
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
+
+ get_dir_4(dir, u1, v0);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
+
+ get_dir_4(dir, u0, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
+
+ get_dir_4(dir, u1, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
+ break;
+ default:
+ get_dir_5(dir, u0, v0);
+ color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
+
+ get_dir_5(dir, u1, v0);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
+
+ get_dir_5(dir, u0, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
+
+ get_dir_5(dir, u1, v1);
+ color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
+ break;
+ }
+ frag_color = color;
+ }
+}
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl b/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl
new file mode 100644
index 0000000000..324d306218
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl
@@ -0,0 +1,256 @@
+// Copyright 2016 Activision Publishing, Inc.
+//
+// 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.
+
+/* clang-format off */
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ int mip_level;
+ uint face_id;
+}
+params;
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+ gl_Position = vec4(base_arr[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
+}
+
+/* clang-format off */
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ int mip_level;
+ uint face_id;
+}
+params;
+
+layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
+
+layout(location = 0) in vec2 uv_interp;
+layout(location = 0) out vec4 frag_color;
+
+/* clang-format on */
+
+#ifdef USE_HIGH_QUALITY
+#define NUM_TAPS 32
+#else
+#define NUM_TAPS 8
+#endif
+
+#define BASE_RESOLUTION 128
+
+#ifdef USE_HIGH_QUALITY
+layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
+ vec4[7][5][3][24] coeffs;
+}
+data;
+#else
+layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
+ vec4[7][5][6] coeffs;
+}
+data;
+#endif
+
+void get_dir(out vec3 dir, in vec2 uv, in uint face) {
+ switch (face) {
+ case 0:
+ dir = vec3(1.0, uv[1], -uv[0]);
+ break;
+ case 1:
+ dir = vec3(-1.0, uv[1], uv[0]);
+ break;
+ case 2:
+ dir = vec3(uv[0], 1.0, -uv[1]);
+ break;
+ case 3:
+ dir = vec3(uv[0], -1.0, uv[1]);
+ break;
+ case 4:
+ dir = vec3(uv[0], uv[1], 1.0);
+ break;
+ default:
+ dir = vec3(-uv[0], uv[1], -1.0);
+ break;
+ }
+}
+
+void main() {
+ // determine dir / pos for the texel
+ vec3 dir, adir, frameZ;
+ {
+ vec2 uv;
+ uv.x = uv_interp.x;
+ uv.y = 1.0 - uv_interp.y;
+ uv = uv * 2.0 - 1.0;
+
+ get_dir(dir, uv, params.face_id);
+ frameZ = normalize(dir);
+
+ adir = abs(dir);
+ }
+
+ // determine which texel this is
+ // NOTE (macOS/MoltenVK): Do not rename, "level" variable name conflicts with the Metal "level(float lod)" mipmap sampling function name.
+ int mip_level = 0;
+
+ if (params.mip_level < 0) {
+ // return as is
+ frag_color.rgb = textureLod(source_cubemap, frameZ, 0.0).rgb;
+ frag_color.a = 1.0;
+ return;
+ } else if (params.mip_level > 6) {
+ // maximum level
+ mip_level = 6;
+ } else {
+ mip_level = params.mip_level;
+ }
+
+ // GGX gather colors
+ vec4 color = vec4(0.0);
+ for (int axis = 0; axis < 3; axis++) {
+ const int otherAxis0 = 1 - (axis & 1) - (axis >> 1);
+ const int otherAxis1 = 2 - (axis >> 1);
+
+ float frameweight = (max(adir[otherAxis0], adir[otherAxis1]) - .75) / .25;
+ if (frameweight > 0.0) {
+ // determine frame
+ vec3 UpVector;
+ switch (axis) {
+ case 0:
+ UpVector = vec3(1, 0, 0);
+ break;
+ case 1:
+ UpVector = vec3(0, 1, 0);
+ break;
+ default:
+ UpVector = vec3(0, 0, 1);
+ break;
+ }
+
+ vec3 frameX = normalize(cross(UpVector, frameZ));
+ vec3 frameY = cross(frameZ, frameX);
+
+ // calculate parametrization for polynomial
+ float Nx = dir[otherAxis0];
+ float Ny = dir[otherAxis1];
+ float Nz = adir[axis];
+
+ float NmaxXY = max(abs(Ny), abs(Nx));
+ Nx /= NmaxXY;
+ Ny /= NmaxXY;
+
+ float theta;
+ if (Ny < Nx) {
+ if (Ny <= -0.999)
+ theta = Nx;
+ else
+ theta = Ny;
+ } else {
+ if (Ny >= 0.999)
+ theta = -Nx;
+ else
+ theta = -Ny;
+ }
+
+ float phi;
+ if (Nz <= -0.999)
+ phi = -NmaxXY;
+ else if (Nz >= 0.999)
+ phi = NmaxXY;
+ else
+ phi = Nz;
+
+ float theta2 = theta * theta;
+ float phi2 = phi * phi;
+
+ // sample
+ for (int iSuperTap = 0; iSuperTap < NUM_TAPS / 4; iSuperTap++) {
+ const int index = (NUM_TAPS / 4) * axis + iSuperTap;
+
+#ifdef USE_HIGH_QUALITY
+ vec4 coeffsDir0[3];
+ vec4 coeffsDir1[3];
+ vec4 coeffsDir2[3];
+ vec4 coeffsLevel[3];
+ vec4 coeffsWeight[3];
+
+ for (int iCoeff = 0; iCoeff < 3; iCoeff++) {
+ coeffsDir0[iCoeff] = data.coeffs[mip_level][0][iCoeff][index];
+ coeffsDir1[iCoeff] = data.coeffs[mip_level][1][iCoeff][index];
+ coeffsDir2[iCoeff] = data.coeffs[mip_level][2][iCoeff][index];
+ coeffsLevel[iCoeff] = data.coeffs[mip_level][3][iCoeff][index];
+ coeffsWeight[iCoeff] = data.coeffs[mip_level][4][iCoeff][index];
+ }
+
+ for (int iSubTap = 0; iSubTap < 4; iSubTap++) {
+ // determine sample attributes (dir, weight, mip_level)
+ vec3 sample_dir = frameX * (coeffsDir0[0][iSubTap] + coeffsDir0[1][iSubTap] * theta2 + coeffsDir0[2][iSubTap] * phi2) + frameY * (coeffsDir1[0][iSubTap] + coeffsDir1[1][iSubTap] * theta2 + coeffsDir1[2][iSubTap] * phi2) + frameZ * (coeffsDir2[0][iSubTap] + coeffsDir2[1][iSubTap] * theta2 + coeffsDir2[2][iSubTap] * phi2);
+
+ float sample_level = coeffsLevel[0][iSubTap] + coeffsLevel[1][iSubTap] * theta2 + coeffsLevel[2][iSubTap] * phi2;
+
+ float sample_weight = coeffsWeight[0][iSubTap] + coeffsWeight[1][iSubTap] * theta2 + coeffsWeight[2][iSubTap] * phi2;
+#else
+ vec4 coeffsDir0 = data.coeffs[mip_level][0][index];
+ vec4 coeffsDir1 = data.coeffs[mip_level][1][index];
+ vec4 coeffsDir2 = data.coeffs[mip_level][2][index];
+ vec4 coeffsLevel = data.coeffs[mip_level][3][index];
+ vec4 coeffsWeight = data.coeffs[mip_level][4][index];
+
+ for (int iSubTap = 0; iSubTap < 4; iSubTap++) {
+ // determine sample attributes (dir, weight, mip_level)
+ vec3 sample_dir = frameX * coeffsDir0[iSubTap] + frameY * coeffsDir1[iSubTap] + frameZ * coeffsDir2[iSubTap];
+
+ float sample_level = coeffsLevel[iSubTap];
+
+ float sample_weight = coeffsWeight[iSubTap];
+#endif
+
+ sample_weight *= frameweight;
+
+ // adjust for jacobian
+ sample_dir /= max(abs(sample_dir[0]), max(abs(sample_dir[1]), abs(sample_dir[2])));
+ sample_level += 0.75 * log2(dot(sample_dir, sample_dir));
+ // sample cubemap
+ color.xyz += textureLod(source_cubemap, normalize(sample_dir), sample_level).xyz * sample_weight;
+ color.w += sample_weight;
+ }
+ }
+ }
+ }
+ color /= color.w;
+
+ // write color
+ color.xyz = max(vec3(0.0), color.xyz);
+ color.w = 1.0;
+
+ frag_color = color;
+}
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl
index ce7c03c1d4..28f4dc59ec 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl
+++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl
@@ -12,100 +12,7 @@ layout(set = 0, binding = 0) uniform samplerCube source_cube;
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
-layout(push_constant, binding = 1, std430) uniform Params {
- uint face_id;
- uint sample_count;
- float roughness;
- bool use_direct_write;
- float face_size;
-}
-params;
-
-#define M_PI 3.14159265359
-
-vec3 texelCoordToVec(vec2 uv, uint faceID) {
- mat3 faceUvVectors[6];
-
- // -x
- faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
- faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
-
- // +x
- faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
- faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
-
- // -y
- faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
- faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
- faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
-
- // +y
- faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
- faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
- faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
-
- // -z
- faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
- faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
-
- // +z
- faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
- faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
-
- // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
- vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
- return normalize(result);
-}
-
-vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
- float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
-
- // Compute distribution direction
- float Phi = 2.0 * M_PI * Xi.x;
- float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
- float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
-
- // Convert to spherical direction
- vec3 H;
- H.x = SinTheta * cos(Phi);
- H.y = SinTheta * sin(Phi);
- H.z = CosTheta;
-
- vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
- vec3 TangentX = normalize(cross(UpVector, N));
- vec3 TangentY = cross(N, TangentX);
-
- // Tangent to world space
- return TangentX * H.x + TangentY * H.y + N * H.z;
-}
-
-// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
-float GGX(float NdotV, float a) {
- float k = a / 2.0;
- return NdotV / (NdotV * (1.0 - k) + k);
-}
-
-// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
-float G_Smith(float a, float nDotV, float nDotL) {
- return GGX(nDotL, a * a) * GGX(nDotV, a * a);
-}
-
-float radicalInverse_VdC(uint bits) {
- bits = (bits << 16u) | (bits >> 16u);
- bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
- bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
- bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
- bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
- return float(bits) * 2.3283064365386963e-10; // / 0x100000000
-}
-
-vec2 Hammersley(uint i, uint N) {
- return vec2(float(i) / float(N), radicalInverse_VdC(i));
-}
+#include "cubemap_roughness_inc.glsl"
void main() {
uvec3 id = gl_GlobalInvocationID;
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl
new file mode 100644
index 0000000000..80c0ac4fb4
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl
@@ -0,0 +1,94 @@
+#define M_PI 3.14159265359
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ uint face_id;
+ uint sample_count;
+ float roughness;
+ bool use_direct_write;
+ float face_size;
+}
+params;
+
+vec3 texelCoordToVec(vec2 uv, uint faceID) {
+ mat3 faceUvVectors[6];
+
+ // -x
+ faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
+ faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
+
+ // +x
+ faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
+ faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
+
+ // -y
+ faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
+ faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
+
+ // +y
+ faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
+ faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
+
+ // -z
+ faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
+ faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
+
+ // +z
+ faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
+
+ // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
+ vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
+ return normalize(result);
+}
+
+vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
+ float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
+
+ // Compute distribution direction
+ float Phi = 2.0 * M_PI * Xi.x;
+ float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
+ float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
+
+ // Convert to spherical direction
+ vec3 H;
+ H.x = SinTheta * cos(Phi);
+ H.y = SinTheta * sin(Phi);
+ H.z = CosTheta;
+
+ vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 TangentX = normalize(cross(UpVector, N));
+ vec3 TangentY = cross(N, TangentX);
+
+ // Tangent to world space
+ return TangentX * H.x + TangentY * H.y + N * H.z;
+}
+
+// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float GGX(float NdotV, float a) {
+ float k = a / 2.0;
+ return NdotV / (NdotV * (1.0 - k) + k);
+}
+
+// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float G_Smith(float a, float nDotV, float nDotL) {
+ return GGX(nDotL, a * a) * GGX(nDotV, a * a);
+}
+
+float radicalInverse_VdC(uint bits) {
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+vec2 Hammersley(uint i, uint N) {
+ return vec2(float(i) / float(N), radicalInverse_VdC(i));
+}
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl
new file mode 100644
index 0000000000..2570308816
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl
@@ -0,0 +1,63 @@
+/* clang-format off */
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "cubemap_roughness_inc.glsl"
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+}
+
+/* clang-format off */
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "cubemap_roughness_inc.glsl"
+
+layout(location = 0) in vec2 uv_interp;
+
+layout(set = 0, binding = 0) uniform samplerCube source_cube;
+
+layout(location = 0) out vec4 frag_color;
+/* clang-format on */
+
+void main() {
+ vec3 N = texelCoordToVec(uv_interp * 2.0 - 1.0, params.face_id);
+
+ //vec4 color = color_interp;
+
+ if (params.use_direct_write) {
+ frag_color = vec4(texture(source_cube, N).rgb, 1.0);
+ } else {
+ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
+
+ for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) {
+ vec2 xi = Hammersley(sampleNum, params.sample_count);
+
+ vec3 H = ImportanceSampleGGX(xi, params.roughness, N);
+ vec3 V = N;
+ vec3 L = (2.0 * dot(V, H) * H - V);
+
+ float ndotl = clamp(dot(N, L), 0.0, 1.0);
+
+ if (ndotl > 0.0) {
+ sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
+ sum.a += ndotl;
+ }
+ }
+ sum /= sum.a;
+
+ frag_color = vec4(sum.rgb, 1.0);
+ }
+}
diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
index 2fce258cff..9155216d7e 100644
--- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
@@ -3,7 +3,7 @@
#define LIGHT_BAKE_STATIC 2
struct LightData { //this structure needs to be as packed as possible
- vec3 position;
+ highp vec3 position;
float inv_radius;
vec3 direction;
@@ -17,8 +17,8 @@ struct LightData { //this structure needs to be as packed as possible
float specular_amount;
bool shadow_enabled;
- vec4 atlas_rect; // rect in the shadow atlas
- mat4 shadow_matrix;
+ highp vec4 atlas_rect; // rect in the shadow atlas
+ highp mat4 shadow_matrix;
float shadow_bias;
float shadow_normal_bias;
float transmittance_bias;
@@ -27,7 +27,7 @@ struct LightData { //this structure needs to be as packed as possible
uint mask;
float shadow_volumetric_fog_fade;
uint bake_mode;
- vec4 projector_rect; //projector rect in srgb decal atlas
+ highp vec4 projector_rect; //projector rect in srgb decal atlas
};
#define REFLECTION_AMBIENT_DISABLED 0
@@ -69,13 +69,13 @@ struct DirectionalLightData {
vec4 shadow_bias;
vec4 shadow_normal_bias;
vec4 shadow_transmittance_bias;
- vec4 shadow_z_range;
- vec4 shadow_range_begin;
+ highp vec4 shadow_z_range;
+ highp vec4 shadow_range_begin;
vec4 shadow_split_offsets;
- mat4 shadow_matrix1;
- mat4 shadow_matrix2;
- mat4 shadow_matrix3;
- mat4 shadow_matrix4;
+ highp mat4 shadow_matrix1;
+ highp mat4 shadow_matrix2;
+ highp mat4 shadow_matrix3;
+ highp mat4 shadow_matrix4;
vec4 shadow_color1;
vec4 shadow_color2;
vec4 shadow_color3;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index b3a349c948..4f140dd10d 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -466,6 +466,11 @@ layout(location = 0) out vec4 frag_color;
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+/* Make a default specular mode SPECULAR_SCHLICK_GGX. */
+#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON)
+#define SPECULAR_SCHLICK_GGX
+#endif
+
#include "scene_forward_lights_inc.glsl"
#include "scene_forward_gi_inc.glsl"
@@ -907,6 +912,8 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
+ specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 7039ea2942..4a41c66ef3 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -208,11 +208,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
//normalized blinn
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
- float blinn = pow(cNdotH, shininess) * cNdotL;
- blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
- float intensity = blinn;
+ float blinn = pow(cNdotH, shininess);
+ blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI));
- specular_light += light_color * intensity * attenuation * specular_amount;
+ specular_light += light_color * attenuation * specular_amount * blinn * f0 * unpackUnorm4x8(orms).w;
#elif defined(SPECULAR_PHONG)
@@ -220,10 +219,9 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float phong = pow(cRdotV, shininess);
- phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
- float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
+ phong *= (shininess + 1.0) * (1.0 / (8.0 * M_PI));
- specular_light += light_color * intensity * attenuation * specular_amount;
+ specular_light += light_color * attenuation * specular_amount * phong * f0 * unpackUnorm4x8(orms).w;
#elif defined(SPECULAR_TOON)
@@ -412,14 +410,8 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
vec4 v = vec4(vertex, 1.0);
vec4 splane = (omni_lights.data[idx].shadow_matrix * v);
- float shadow_len = length(splane.xyz); //need to remember shadow len from here
- {
- vec3 nofs = normal_interp * omni_lights.data[idx].shadow_normal_bias / omni_lights.data[idx].inv_radius;
- nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
- v.xyz += nofs;
- splane = (omni_lights.data[idx].shadow_matrix * v);
- }
+ float shadow_len = length(splane.xyz); //need to remember shadow len from here
float shadow;
@@ -528,7 +520,8 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
splane.xy /= splane.z;
splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = (shadow_len - omni_lights.data[idx].shadow_bias) * omni_lights.data[idx].inv_radius;
+ splane.z = shadow_len * omni_lights.data[idx].inv_radius;
+ splane.z -= omni_lights.data[idx].shadow_bias;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
splane.w = 1.0; //needed? i think it should be 1 already
shadow = sample_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
@@ -704,27 +697,17 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
//there is a shadowmap
vec4 v = vec4(vertex, 1.0);
- v.xyz -= spot_dir * spot_lights.data[idx].shadow_bias;
-
- float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius;
-
- float depth_bias_scale = 1.0 / (max(0.0001, z_norm)); //the closer to the light origin, the more you have to offset to reach 1px in the map
- vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * spot_lights.data[idx].shadow_normal_bias * depth_bias_scale;
- normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
- v.xyz += normal_bias;
-
- //adjust with bias
- z_norm = dot(spot_dir, v.xyz - spot_lights.data[idx].position) * spot_lights.data[idx].inv_radius;
-
float shadow;
vec4 splane = (spot_lights.data[idx].shadow_matrix * v);
splane /= splane.w;
+ splane.z -= spot_lights.data[idx].shadow_bias;
if (sc_use_light_soft_shadows && spot_lights.data[idx].soft_shadow_size > 0.0) {
//soft shadow
//find blocker
+ float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius;
vec2 shadow_uv = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 70900a847c..2babe92c1c 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -59,27 +59,27 @@ layout(location = 11) in vec4 weight_attrib;
/* Varyings */
-layout(location = 0) out vec3 vertex_interp;
+layout(location = 0) highp out vec3 vertex_interp;
#ifdef NORMAL_USED
-layout(location = 1) out vec3 normal_interp;
+layout(location = 1) mediump out vec3 normal_interp;
#endif
#if defined(COLOR_USED)
-layout(location = 2) out vec4 color_interp;
+layout(location = 2) mediump out vec4 color_interp;
#endif
#ifdef UV_USED
-layout(location = 3) out vec2 uv_interp;
+layout(location = 3) mediump out vec2 uv_interp;
#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
-layout(location = 4) out vec2 uv2_interp;
+layout(location = 4) mediump out vec2 uv2_interp;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 5) out vec3 tangent_interp;
-layout(location = 6) out vec3 binormal_interp;
+layout(location = 5) mediump out vec3 tangent_interp;
+layout(location = 6) mediump out vec3 binormal_interp;
#endif
#ifdef MATERIAL_UNIFORMS_USED
@@ -370,6 +370,10 @@ void main() {
#VERSION_DEFINES
+//use medium precision for floats on mobile.
+
+precision mediump float;
+
/* Specialization Constants */
/* Specialization Constants (Toggles) */
@@ -395,32 +399,32 @@ layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
/* Varyings */
-layout(location = 0) in vec3 vertex_interp;
+layout(location = 0) highp in vec3 vertex_interp;
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_interp;
+layout(location = 1) mediump in vec3 normal_interp;
#endif
#if defined(COLOR_USED)
-layout(location = 2) in vec4 color_interp;
+layout(location = 2) mediump in vec4 color_interp;
#endif
#ifdef UV_USED
-layout(location = 3) in vec2 uv_interp;
+layout(location = 3) mediump in vec2 uv_interp;
#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
-layout(location = 4) in vec2 uv2_interp;
+layout(location = 4) mediump in vec2 uv2_interp;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 5) in vec3 tangent_interp;
-layout(location = 6) in vec3 binormal_interp;
+layout(location = 5) mediump in vec3 tangent_interp;
+layout(location = 6) mediump in vec3 binormal_interp;
#endif
#ifdef MODE_DUAL_PARABOLOID
-layout(location = 8) in float dp_clip;
+layout(location = 8) highp in float dp_clip;
#endif
@@ -491,6 +495,11 @@ layout(location = 0) out vec4 frag_color;
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+/* Make a default specular mode SPECULAR_SCHLICK_GGX. */
+#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON)
+#define SPECULAR_SCHLICK_GGX
+#endif
+
#include "scene_forward_lights_inc.glsl"
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -843,6 +852,8 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
+ specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index d9682d7b23..f1e554d01c 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -16,12 +16,12 @@
/* don't exceed 128 bytes!! */
/* put instance data into our push content, not a array */
layout(push_constant, binding = 0, std430) uniform DrawCall {
- mat4 transform; // 64 - 64
+ highp mat4 transform; // 64 - 64
uint flags; // 04 - 68
uint instance_uniforms_ofs; //base offset in global buffer for instance variables // 04 - 72
uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) // 04 - 76
uint layer_mask; // 04 - 80
- vec4 lightmap_uv_scale; // 16 - 96 doubles as uv_offset when needed
+ highp vec4 lightmap_uv_scale; // 16 - 96 doubles as uv_offset when needed
uvec2 reflection_probes; // 08 - 104
uvec2 omni_lights; // 08 - 112
@@ -126,14 +126,14 @@ global_variables;
/* Set 1: Render Pass (changes per render pass) */
layout(set = 1, binding = 0, std140) uniform SceneData {
- mat4 projection_matrix;
- mat4 inv_projection_matrix;
- mat4 camera_matrix;
- mat4 inv_camera_matrix;
+ highp mat4 projection_matrix;
+ highp mat4 inv_projection_matrix;
+ highp mat4 camera_matrix;
+ highp mat4 inv_camera_matrix;
// only used for multiview
- mat4 projection_matrix_view[MAX_VIEWS];
- mat4 inv_projection_matrix_view[MAX_VIEWS];
+ highp mat4 projection_matrix_view[MAX_VIEWS];
+ highp mat4 inv_projection_matrix_view[MAX_VIEWS];
vec2 viewport_size;
vec2 screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 23f83b3b9c..3c685c25b9 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -35,11 +35,15 @@ void main() {
layout(location = 0) in vec2 uv_interp;
-#ifdef MULTIVIEW
+#ifdef SUBPASS
+layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput input_color;
+#else
+#if MULTIVIEW
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
#else
layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
+#endif
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(set = 2, binding = 0) uniform sampler2D source_glow;
#ifdef USE_1D_LUT
@@ -180,10 +184,6 @@ vec3 tonemap_aces(vec3 color, float white) {
}
vec3 tonemap_reinhard(vec3 color, float white) {
- // Ensure color values are positive.
- // They can be negative in the case of negative lights, which leads to undesired behavior.
- color = max(vec3(0.0), color);
-
return (white * color + color) / (color * white + white);
}
@@ -207,7 +207,7 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
return tonemap_reinhard(color, white);
} else if (params.tonemapper == TONEMAPPER_FILMIC) {
return tonemap_filmic(color, white);
- } else { //aces
+ } else { // TONEMAPPER_ACES
return tonemap_aces(color, white);
}
}
@@ -291,6 +291,7 @@ vec3 apply_color_correction(vec3 color) {
}
#endif
+#ifndef SUBPASS
vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_REDUCE_MIN = (1.0 / 128.0);
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
@@ -346,6 +347,7 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
return rgbB;
}
}
+#endif // !SUBPASS
// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom)
@@ -360,7 +362,10 @@ vec3 screen_space_dither(vec2 frag_coord) {
}
void main() {
-#ifdef MULTIVIEW
+#ifdef SUBPASS
+ // SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer
+ vec3 color = subpassLoad(input_color).rgb;
+#elif MULTIVIEW
vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
#else
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
@@ -370,14 +375,16 @@ void main() {
float exposure = params.exposure;
+#ifndef SUBPASS
if (params.use_auto_exposure) {
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
}
+#endif
color *= exposure;
// Early Tonemap & SRGB Conversion
-
+#ifndef SUBPASS
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
vec3 glow = gather_glow(source_glow, uv_interp);
color.rgb = mix(color.rgb, glow, params.glow_intensity);
@@ -386,15 +393,21 @@ void main() {
if (params.use_fxaa) {
color = do_fxaa(color, exposure, uv_interp);
}
+#endif
+
if (params.use_debanding) {
// For best results, debanding should be done before tonemapping.
// Otherwise, we're adding noise to an already-quantized image.
color += screen_space_dither(gl_FragCoord.xy);
}
- color = apply_tonemapping(color, params.white);
+
+ // Ensure color values passed to tonemappers are positive.
+ // They can be negative in the case of negative lights, which leads to undesired behavior.
+ color = apply_tonemapping(max(vec3(0.0), color), params.white);
color = linear_to_srgb(color); // regular linear -> SRGB conversion
+#ifndef SUBPASS
// Glow
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
@@ -406,6 +419,7 @@ void main() {
color = apply_glow(color, glow);
}
+#endif
// Additional effects
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 83d1b33bf2..4a4976718c 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1866,7 +1866,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
//rotate it
Basis rot = lightmap->transform.basis.orthonormalized();
for (int i = 0; i < 3; i++) {
- float csh[9];
+ real_t csh[9];
for (int j = 0; j < 9; j++) {
csh[j] = sh[j][i];
}
@@ -1878,7 +1878,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);
- float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
+ real_t blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
//make blend more rounded
blend = Math::lerp(inner_pos.length(), blend, blend);
blend *= blend;
@@ -1955,10 +1955,6 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
- real_t first_radius = 0.0;
-
- real_t min_distance_bias_scale = distances[1];
-
cull.shadow_count = p_shadow_index + 1;
cull.shadows[p_shadow_index].cascade_count = splits;
cull.shadows[p_shadow_index].light_instance = light->instance;
@@ -2006,8 +2002,8 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
real_t z_min_cam = 0.f;
//real_t z_max_cam = 0.f;
- real_t bias_scale = 1.0;
- real_t aspect_bias_scale = 1.0;
+ //real_t bias_scale = 1.0;
+ //real_t aspect_bias_scale = 1.0;
//used for culling
@@ -2061,12 +2057,6 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
radius *= texture_size / (texture_size - 2.0); //add a texel by each side
- if (i == 0) {
- first_radius = radius;
- } else {
- bias_scale = radius / first_radius;
- }
-
z_min_cam = z_vec.dot(center) - radius;
{
@@ -2110,64 +2100,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
// a pre pass will need to be needed to determine the actual z-near to be used
- if (pancake_size > 0) {
- z_max = z_vec.dot(center) + radius + pancake_size;
- }
-
- if (aspect != 1.0) {
- // if the aspect is different, then the radius will become larger.
- // if this happens, then bias needs to be adjusted too, as depth will increase
- // to do this, compare the depth of one that would have resulted from a square frustum
-
- CameraMatrix camera_matrix_square;
- if (p_cam_orthogonal) {
- Vector2 vp_he = camera_matrix.get_viewport_half_extents();
- if (p_cam_vaspect) {
- camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
- } else {
- camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
- }
- } else {
- Vector2 vp_he = camera_matrix.get_viewport_half_extents();
- if (p_cam_vaspect) {
- camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
- } else {
- camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
- }
- }
-
- Vector3 endpoints_square[8]; // frustum plane endpoints
- res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square);
- ERR_CONTINUE(!res);
- Vector3 center_square;
-
- for (int j = 0; j < 8; j++) {
- center_square += endpoints_square[j];
- }
-
- center_square /= 8.0;
-
- real_t radius_square = 0;
-
- for (int j = 0; j < 8; j++) {
- real_t d = center_square.distance_to(endpoints_square[j]);
- if (d > radius_square) {
- radius_square = d;
- }
- }
-
- radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side
-
- float z_max_square = z_vec.dot(center_square) + radius_square + pancake_size;
-
- real_t z_min_cam_square = z_vec.dot(center_square) - radius_square;
-
- aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square);
-
- // this is not entirely perfect, because the cull-adjusted z-max may be different
- // but at least it's warranted that it results in a greater bias, so no acne should be present either way.
- // pancaking also helps with this.
- }
+ z_max = z_vec.dot(center) + radius + pancake_size;
{
CameraMatrix ortho_camera;
@@ -2188,7 +2121,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
cull.shadows[p_shadow_index].cascades[i].zfar = z_max - z_min_cam;
cull.shadows[p_shadow_index].cascades[i].split = distances[i + 1];
cull.shadows[p_shadow_index].cascades[i].shadow_texel_size = radius * 2.0 / texture_size;
- cull.shadows[p_shadow_index].cascades[i].bias_scale = bias_scale * aspect_bias_scale * min_distance_bias_scale;
+ cull.shadows[p_shadow_index].cascades[i].bias_scale = (z_max - z_min_cam);
cull.shadows[p_shadow_index].cascades[i].range_begin = z_max;
cull.shadows[p_shadow_index].cascades[i].uv_scale = uv_scale;
}
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 1d0f53c0bf..e06b3ba153 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -60,7 +60,7 @@ public:
void update_mips();
- _FORCE_INLINE_ bool is_occluded(const float p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, float p_near) const {
+ _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, real_t p_near) const {
if (is_empty()) {
return false;
}
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index b9bc349f79..2304394501 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -468,23 +468,23 @@ public:
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
- virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
- virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0;
- virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
- virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
- virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
- virtual void particles_set_collision_base_size(RID p_particles, float p_size) = 0;
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
- virtual void particles_set_trails(RID p_particles, bool p_enable, float p_length) = 0;
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
virtual void particles_restart(RID p_particles) = 0;
@@ -523,11 +523,11 @@ public:
virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) = 0; //for spheres
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
- virtual void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) = 0;
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) = 0;
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) = 0;
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index b298ad193b..bb9ffffe8a 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -420,8 +420,8 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color()));
- ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>()));
- ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
@@ -431,7 +431,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2i()));
+ ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2()));
ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass);
@@ -739,7 +739,7 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_UPDATE_BIT);
BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_FROM_BIT);
BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_TO_BIT);
- BIND_ENUM_CONSTANT(TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT);
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_IDENTITY);
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ZERO);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index eaf1ace798..bb028cb84c 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -422,7 +422,7 @@ public:
TEXTURE_USAGE_CAN_UPDATE_BIT = (1 << 6),
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
- TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT = (1 << 9),
+ TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9),
};
enum TextureSwizzle {
@@ -1065,6 +1065,7 @@ public:
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0;
virtual void draw_list_disable_scissor(DrawListID p_list) = 0;
+ virtual uint32_t draw_list_get_current_pass() = 0;
virtual DrawListID draw_list_switch_to_next_pass() = 0;
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) = 0;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index c79dfb1649..bed6ade1f6 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -134,8 +134,8 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
}
if (RSG::storage->capturing_timestamps) {
- new_profile.write[i].gpu_msec = float((time_gpu - base_gpu) / 1000) / 1000.0;
- new_profile.write[i].cpu_msec = float(time_cpu - base_cpu) / 1000.0;
+ new_profile.write[i].gpu_msec = double((time_gpu - base_gpu) / 1000) / 1000.0;
+ new_profile.write[i].cpu_msec = double(time_cpu - base_cpu) / 1000.0;
new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
}
}
@@ -149,7 +149,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
if (print_frame_profile_ticks_from == 0) {
print_frame_profile_ticks_from = OS::get_singleton()->get_ticks_usec();
}
- float total_time = 0.0;
+ double total_time = 0.0;
for (int i = 0; i < frame_profile.size() - 1; i++) {
String name = frame_profile[i].name;
@@ -157,7 +157,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
continue;
}
- float time = frame_profile[i + 1].gpu_msec - frame_profile[i].gpu_msec;
+ double time = frame_profile[i + 1].gpu_msec - frame_profile[i].gpu_msec;
if (name[0] != '<' && name[0] != '>') {
if (print_gpu_profile_task_time.has(name)) {
@@ -179,7 +179,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
float print_threshold = 0.01;
for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) {
- float time = E.value() / float(print_frame_profile_frame_count);
+ double time = E.value() / double(print_frame_profile_frame_count);
if (time > print_threshold) {
print_line("\t-" + E.key() + ": " + rtos(time) + "ms");
}
@@ -193,7 +193,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::storage->update_memory_info();
}
-float RenderingServerDefault::get_frame_setup_time_cpu() const {
+double RenderingServerDefault::get_frame_setup_time_cpu() const {
return frame_setup_time;
}
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 282b0564da..c1336ee42d 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -71,7 +71,7 @@ class RenderingServerDefault : public RenderingServer {
uint64_t frame_profile_frame;
Vector<FrameProfileArea> frame_profile;
- float frame_setup_time = 0;
+ double frame_setup_time = 0;
//for printing
bool print_gpu_profile = false;
@@ -440,13 +440,13 @@ public:
FUNC2(particles_set_emitting, RID, bool)
FUNC1R(bool, particles_get_emitting, RID)
FUNC2(particles_set_amount, RID, int)
- FUNC2(particles_set_lifetime, RID, float)
+ FUNC2(particles_set_lifetime, RID, double)
FUNC2(particles_set_one_shot, RID, bool)
- FUNC2(particles_set_pre_process_time, RID, float)
+ FUNC2(particles_set_pre_process_time, RID, double)
FUNC2(particles_set_explosiveness_ratio, RID, float)
FUNC2(particles_set_randomness_ratio, RID, float)
FUNC2(particles_set_custom_aabb, RID, const AABB &)
- FUNC2(particles_set_speed_scale, RID, float)
+ FUNC2(particles_set_speed_scale, RID, double)
FUNC2(particles_set_use_local_coordinates, RID, bool)
FUNC2(particles_set_process_material, RID, RID)
FUNC2(particles_set_fixed_fps, RID, int)
@@ -478,11 +478,11 @@ public:
FUNC2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
FUNC2(particles_collision_set_cull_mask, RID, uint32_t)
- FUNC2(particles_collision_set_sphere_radius, RID, float)
+ FUNC2(particles_collision_set_sphere_radius, RID, real_t)
FUNC2(particles_collision_set_box_extents, RID, const Vector3 &)
- FUNC2(particles_collision_set_attractor_strength, RID, float)
- FUNC2(particles_collision_set_attractor_directionality, RID, float)
- FUNC2(particles_collision_set_attractor_attenuation, RID, float)
+ FUNC2(particles_collision_set_attractor_strength, RID, real_t)
+ FUNC2(particles_collision_set_attractor_directionality, RID, real_t)
+ FUNC2(particles_collision_set_attractor_attenuation, RID, real_t)
FUNC2(particles_collision_set_field_texture, RID, RID)
FUNC1(particles_collision_height_field_update, RID)
FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
@@ -574,8 +574,8 @@ public:
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
FUNC2(viewport_set_measure_render_time, RID, bool)
- FUNC1RC(float, viewport_get_measured_render_time_cpu, RID)
- FUNC1RC(float, viewport_get_measured_render_time_gpu, RID)
+ FUNC1RC(double, viewport_get_measured_render_time_cpu, RID)
+ FUNC1RC(double, viewport_get_measured_render_time_gpu, RID)
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
@@ -890,7 +890,7 @@ public:
/* TESTING */
- virtual float get_frame_setup_time_cpu() const override;
+ virtual double get_frame_setup_time_cpu() const override;
virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override;
virtual void set_default_clear_color(const Color &p_color) override;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index baa5381554..20fcb1396d 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -1424,7 +1424,7 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
DataType nb = p_op->arguments[1]->get_datatype();
if (na == nb) {
- valid = (na > TYPE_BOOL && na < TYPE_MAT2) || (p_op->op == OP_ASSIGN_MUL && na >= TYPE_MAT2 && na <= TYPE_MAT4);
+ valid = (na > TYPE_BOOL && na <= TYPE_MAT4);
ret_type = na;
} else if (na == TYPE_IVEC2 && nb == TYPE_INT) {
valid = true;
@@ -1598,723 +1598,723 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
//constructors
- { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
+ { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
//conversion scalars
- { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
+ { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
+ { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
+ { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
//conversion vectors
- { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
//conversion between matrixes
- { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
+ { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
//builtins - trigonometry
- { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+
+ { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+
+ { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+
+ { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+
+ { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+
+ { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+
+ { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
//builtins - exponential
- { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
//builtins - common
- { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
+ { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+
+ { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+
+ { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+
+ { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+
+ { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+
+ { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+
+ { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+
+ { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
//builtins - geometric
- { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
+ { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
+
+ { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+ { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+ { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+
+ { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+ { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+ { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+
+ { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+
+ { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+
+ { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
- { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
- { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
//builtins - texture
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+
+ { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
//sub-functions
//array
- { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true },
+ { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true },
// modern functions
- { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
- { nullptr, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false }
+ { nullptr, TYPE_VOID, { TYPE_VOID }, { "" }, TAG_GLOBAL, false }
};
const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
@@ -4228,6 +4228,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
IdentifierType ident_type;
int array_size = 0;
StringName struct_name;
+ bool is_local = false;
if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) {
int idx = 0;
@@ -4252,9 +4253,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (ident_type == IDENTIFIER_VARYING) {
TkPos prev_pos = _get_tkpos();
Token next_token = _get_token();
+
+ // An array of varyings.
+ if (next_token.type == TK_BRACKET_OPEN) {
+ _get_token(); // Pass constant.
+ _get_token(); // Pass TK_BRACKET_CLOSE.
+ next_token = _get_token();
+ }
_set_tkpos(prev_pos);
- String error;
+ String error;
if (is_token_operator_assign(next_token.type)) {
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
_set_error(error);
@@ -4277,6 +4285,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else {
last_type = ident_type;
}
+
+ is_local = ident_type == IDENTIFIER_LOCAL_VAR || ident_type == IDENTIFIER_FUNCTION_ARGUMENT;
}
Node *index_expression = nullptr;
@@ -4351,6 +4361,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
arrname->assign_expression = assign_expression;
arrname->is_const = is_const;
arrname->array_size = array_size;
+ arrname->is_local = is_local;
expr = arrname;
} else {
VariableNode *varname = alloc_node<VariableNode>();
@@ -4358,6 +4369,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
varname->datatype_cache = data_type;
varname->is_const = is_const;
varname->struct_name = struct_name;
+ varname->is_local = is_local;
expr = varname;
}
#ifdef DEBUG_ENABLED
@@ -6616,6 +6628,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
+ TkPos prev_pos;
if (tk.type != TK_SHADER_TYPE) {
_set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types));
@@ -6637,11 +6650,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types));
return ERR_PARSE_ERROR;
}
-
+ prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
+ _set_tkpos(prev_pos);
_set_error("Expected ';' after 'shader_type <type>'.");
+ return ERR_PARSE_ERROR;
}
tk = _get_token();
@@ -6860,6 +6875,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataInterpolation interpolation = INTERPOLATION_SMOOTH;
DataType type;
StringName name;
+ int array_size = 0;
tk = _get_token();
if (is_token_interpolation(tk.type)) {
@@ -6890,12 +6906,36 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
tk = _get_token();
+
+ if (tk.type == TK_BRACKET_OPEN) {
+ if (uniform) {
+ _set_error(vformat("Uniform arrays are not yet implemented!"));
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
+ array_size = (int)tk.constant;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
+ tk = _get_token();
+ } else {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier!");
return ERR_PARSE_ERROR;
}
- TkPos name_pos = _get_tkpos();
+ prev_pos = _get_tkpos();
name = tk.text;
if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
@@ -7188,7 +7228,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
varying.type = type;
varying.precision = precision;
varying.interpolation = interpolation;
- varying.tkpos = name_pos;
+ varying.tkpos = prev_pos;
+ varying.array_size = array_size;
tk = _get_token();
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
@@ -7197,6 +7238,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type == TK_BRACKET_OPEN) {
+ if (array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
tk = _get_token();
if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
varying.array_size = (int)tk.constant;
@@ -7272,7 +7317,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
type = get_token_datatype(tk.type);
}
- TkPos prev_pos = _get_tkpos();
+ prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -7415,13 +7460,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
+ prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
array_size2 = constant.array_size;
tk = _get_token();
} else {
- _set_tkpos(pos2);
+ _set_tkpos(prev_pos);
Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
@@ -8434,6 +8479,12 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += get_datatype_name(builtin_func_defs[idx].args[i]);
+ String arg_name = (String)builtin_func_defs[idx].args_names[i];
+ if (!arg_name.is_empty()) {
+ calltip += " ";
+ calltip += arg_name;
+ }
+
if (i == completion_argument) {
calltip += char32_t(0xFFFF);
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index c02d6c47ec..9e0a63f0f7 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -409,6 +409,7 @@ public:
StringName name;
StringName struct_name;
bool is_const = false;
+ bool is_local = false;
virtual DataType get_datatype() const override { return datatype_cache; }
virtual String get_datatype_name() const override { return String(struct_name); }
@@ -444,6 +445,7 @@ public:
Node *assign_expression = nullptr;
bool is_const = false;
int array_size = 0;
+ bool is_local = false;
virtual DataType get_datatype() const override { return datatype_cache; }
virtual String get_datatype_name() const override { return String(struct_name); }
@@ -939,6 +941,7 @@ private:
const char *name;
DataType rettype;
const DataType args[MAX_ARGS];
+ const char *args_names[MAX_ARGS];
SubClassTag tag;
bool high_end;
};
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 376d23ccb3..4488069698 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -31,18 +31,22 @@
#include "shader_types.h"
#include "core/math/math_defs.h"
-const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) {
+const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const {
return shader_modes[p_mode].functions;
}
-const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) {
+const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const {
return shader_modes[p_mode].modes;
}
-const Set<String> &ShaderTypes::get_types() {
+const Set<String> &ShaderTypes::get_types() const {
return shader_types;
}
+const List<String> &ShaderTypes::get_types_list() const {
+ return shader_types_list;
+}
+
ShaderTypes *ShaderTypes::singleton = nullptr;
static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) {
@@ -440,8 +444,12 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
shader_modes[RS::SHADER_SKY].modes.push_back("disable_fog");
- shader_types.insert("spatial");
- shader_types.insert("canvas_item");
- shader_types.insert("particles");
- shader_types.insert("sky");
+ shader_types_list.push_back("spatial");
+ shader_types_list.push_back("canvas_item");
+ shader_types_list.push_back("particles");
+ shader_types_list.push_back("sky");
+
+ for (int i = 0; i < shader_types_list.size(); i++) {
+ shader_types.insert(shader_types_list[i]);
+ }
}
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index e59cef6b79..75a310a1b1 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -46,13 +46,15 @@ class ShaderTypes {
static ShaderTypes *singleton;
Set<String> shader_types;
+ List<String> shader_types_list;
public:
static ShaderTypes *get_singleton() { return singleton; }
- const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode);
- const Vector<StringName> &get_modes(RS::ShaderMode p_mode);
- const Set<String> &get_types();
+ const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
+ const Vector<StringName> &get_modes(RS::ShaderMode p_mode) const;
+ const Set<String> &get_types() const;
+ const List<String> &get_types_list() const;
ShaderTypes();
};
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 314b59869d..222ea9e622 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -242,7 +242,7 @@ RID RenderingServer::_make_test_cube() {
return test_cube;
}
-RID RenderingServer::make_sphere_mesh(int p_lats, int p_lons, float p_radius) {
+RID RenderingServer::make_sphere_mesh(int p_lats, int p_lons, real_t p_radius) {
Vector<Vector3> vertices;
Vector<Vector3> normals;
const double lat_step = Math_TAU / p_lats;
@@ -412,26 +412,40 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
} break;
case RS::ARRAY_TANGENT: {
- ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
+ Variant::Type type = p_arrays[ai].get_type();
+ ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
+ if (type == Variant::PACKED_FLOAT32_ARRAY) {
+ Vector<float> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
+ const float *src = array.ptr();
- Vector<real_t> array = p_arrays[ai];
-
- ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
-
- const real_t *src = array.ptr();
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ uint32_t value = 0;
+ value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (src[i * 4 + 3] > 0) {
+ value |= 3 << 30;
+ }
- for (int i = 0; i < p_vertex_array_len; i++) {
- uint32_t value = 0;
- value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
- value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
- if (src[i * 4 + 3] > 0) {
- value |= 3 << 30;
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
}
+ } else { // if (type == Variant::PACKED_FLOAT64_ARRAY)
+ Vector<double> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
+ const double *src = array.ptr();
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ uint32_t value = 0;
+ value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (src[i * 4 + 3] > 0) {
+ value |= 3 << 30;
+ }
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ }
}
-
} break;
case RS::ARRAY_COLOR: {
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_COLOR_ARRAY, ERR_INVALID_PARAMETER);
@@ -543,27 +557,38 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
} break;
case RS::ARRAY_WEIGHTS: {
- ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
-
+ Variant::Type type = p_arrays[ai].get_type();
+ ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
uint32_t bone_count = (p_format & ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 8 : 4;
+ if (type == Variant::PACKED_FLOAT32_ARRAY) {
+ Vector<float> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != (int32_t)(p_vertex_array_len * bone_count), ERR_INVALID_PARAMETER);
+ const float *src = array.ptr();
+ {
+ uint16_t data[8];
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ for (uint32_t j = 0; j < bone_count; j++) {
+ data[j] = CLAMP(src[i * bone_count + j] * 65535, 0, 65535);
+ }
- Vector<real_t> array = p_arrays[ai];
-
- ERR_FAIL_COND_V(array.size() != (int32_t)(p_vertex_array_len * bone_count), ERR_INVALID_PARAMETER);
-
- const real_t *src = array.ptr();
-
- {
- uint16_t data[8];
- for (int i = 0; i < p_vertex_array_len; i++) {
- for (uint32_t j = 0; j < bone_count; j++) {
- data[j] = CLAMP(src[i * bone_count + j] * 65535, 0, 65535);
+ memcpy(&sw[p_offsets[ai] + i * p_skin_stride], data, 2 * bone_count);
}
+ }
+ } else { // if (type == Variant::PACKED_FLOAT64_ARRAY)
+ Vector<double> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != (int32_t)(p_vertex_array_len * bone_count), ERR_INVALID_PARAMETER);
+ const double *src = array.ptr();
+ {
+ uint16_t data[8];
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ for (uint32_t j = 0; j < bone_count; j++) {
+ data[j] = CLAMP(src[i * bone_count + j] * 65535, 0, 65535);
+ }
- memcpy(&sw[p_offsets[ai] + i * p_skin_stride], data, 2 * bone_count);
+ memcpy(&sw[p_offsets[ai] + i * p_skin_stride], data, 2 * bone_count);
+ }
}
}
-
} break;
case RS::ARRAY_BONES: {
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_INT32_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
@@ -2801,13 +2826,13 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/driver/depth_prepass/enable", true);
GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
- GLOBAL_DEF("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
- GLOBAL_DEF("rendering/textures/default_filters/anisotropic_filtering_level", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/anisotropic_filtering_level", PropertyInfo(Variant::INT, "rendering/textures/default_filters/anisotropic_filtering_level", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Faster),4x (Fast),8x (Average),16x (Slow)"));
+ GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
+ GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/anisotropic_filtering_level", PropertyInfo(Variant::INT, "rendering/textures/default_filters/anisotropic_filtering_level", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Faster),4× (Fast),8× (Average),16× (Slow)")));
GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_bokeh_shape", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/camera/depth_of_field/depth_of_field_bokeh_shape", PropertyInfo(Variant::INT, "rendering/camera/depth_of_field/depth_of_field_bokeh_shape", PROPERTY_HINT_ENUM, "Box (Fast),Hexagon (Average),Circle (Slow)"));
- GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_bokeh_quality", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/camera/depth_of_field/depth_of_field_bokeh_shape", PropertyInfo(Variant::INT, "rendering/camera/depth_of_field/depth_of_field_bokeh_shape", PROPERTY_HINT_ENUM, "Box (Fast),Hexagon (Average),Circle (Slowest)"));
+ GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_bokeh_quality", 1);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/camera/depth_of_field/depth_of_field_bokeh_quality", PropertyInfo(Variant::INT, "rendering/camera/depth_of_field/depth_of_field_bokeh_quality", PROPERTY_HINT_ENUM, "Very Low (Fastest),Low (Fast),Medium (Average),High (Slow)"));
GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_use_jitter", false);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 28aee1b575..545270dcd9 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -613,13 +613,13 @@ public:
virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0;
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
- virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
- virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
- virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
@@ -687,11 +687,11 @@ public:
virtual void particles_collision_set_collision_type(RID p_particles_collision, ParticlesCollisionType p_type) = 0;
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) = 0; //for spheres
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
- virtual void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) = 0;
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) = 0;
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) = 0;
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
@@ -900,8 +900,8 @@ public:
virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0;
virtual void viewport_set_measure_render_time(RID p_viewport, bool p_enable) = 0;
- virtual float viewport_get_measured_render_time_cpu(RID p_viewport) const = 0;
- virtual float viewport_get_measured_render_time_gpu(RID p_viewport) const = 0;
+ virtual double viewport_get_measured_render_time_cpu(RID p_viewport) const = 0;
+ virtual double viewport_get_measured_render_time_gpu(RID p_viewport) const = 0;
/* SKY API */
@@ -1436,15 +1436,15 @@ public:
struct FrameProfileArea {
String name;
- float gpu_msec;
- float cpu_msec;
+ double gpu_msec;
+ double cpu_msec;
};
virtual void set_frame_profiling_enabled(bool p_enable) = 0;
virtual Vector<FrameProfileArea> get_frame_profile() = 0;
virtual uint64_t get_frame_profile_frame() = 0;
- virtual float get_frame_setup_time_cpu() const = 0;
+ virtual double get_frame_setup_time_cpu() const = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@@ -1457,7 +1457,7 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
- virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius);
+ virtual RID make_sphere_mesh(int p_lats, int p_lons, real_t p_radius);
virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data);
virtual void mesh_add_surface_from_planes(RID p_mesh, const Vector<Plane> &p_planes);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 1491368109..6bace8cf9e 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -314,8 +314,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_preserve_control", "shaped"), &TextServer::shaped_text_get_preserve_control);
ClassDB::bind_method(D_METHOD("shaped_text_add_string", "shaped", "text", "fonts", "size", "opentype_features", "language"), &TextServer::shaped_text_add_string, DEFVAL(Dictionary()), DEFVAL(""));
- ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(VALIGN_CENTER), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(VALIGN_CENTER));
+ ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGN_CENTER));
ClassDB::bind_method(D_METHOD("shaped_text_substr", "shaped", "start", "length"), &TextServer::shaped_text_substr);
ClassDB::bind_method(D_METHOD("shaped_text_get_parent", "shaped"), &TextServer::shaped_text_get_parent);
@@ -739,6 +739,11 @@ Vector<Vector2i> TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_gra
return words;
}
+TextServer::TrimData TextServer::shaped_text_get_trim_data(RID p_shaped) const {
+ WARN_PRINT("Getting overrun data not supported by this TextServer.");
+ return TrimData();
+}
+
void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_leading_caret, Direction &p_leading_dir, Rect2 &p_trailing_caret, Direction &p_trailing_dir) const {
Vector<Rect2> carets;
const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
@@ -976,7 +981,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - start), off + advance));
}
}
- // Selection range is within grapheme
+ // Selection range is within grapheme.
if (glyphs[i].start < start && glyphs[i].end > end) {
float advance = 0.f;
for (int j = 0; j < glyphs[i].count; j++) {
@@ -1137,10 +1142,26 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped);
+ bool rtl = shaped_text_get_direction(p_shaped) == DIRECTION_RTL;
+ TrimData trim_data = shaped_text_get_trim_data(p_shaped);
+
int v_size = visual.size();
const Glyph *glyphs = visual.ptr();
Vector2 ofs = p_pos;
+ // Draw RTL ellipsis string when needed.
+ if (rtl && trim_data.ellipsis_pos >= 0) {
+ for (int i = trim_data.ellipsis_glyph_buf.size() - 1; i >= 0; i--) {
+ for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
+ font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ } else {
+ ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ }
+ }
+ }
+ }
// Draw at the baseline.
for (int i = 0; i < v_size; i++) {
for (int j = 0; j < glyphs[i].repeat; j++) {
@@ -1170,6 +1191,18 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
}
+ if (trim_data.trim_pos >= 0) {
+ if (rtl) {
+ if (i < trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ continue;
+ }
+ } else {
+ if (i >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ break;
+ }
+ }
+ }
+
if (glyphs[i].font_rid != RID()) {
font_draw_glyph(glyphs[i].font_rid, p_canvas, glyphs[i].font_size, ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, p_color);
} else if (hex_codes && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
@@ -1182,15 +1215,44 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
}
+ // Draw LTR ellipsis string when needed.
+ if (!rtl && trim_data.ellipsis_pos >= 0) {
+ for (int i = 0; i < trim_data.ellipsis_glyph_buf.size(); i++) {
+ for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
+ font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ } else {
+ ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ }
+ }
+ }
+ }
}
void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
+ bool rtl = (shaped_text_get_direction(p_shaped) == DIRECTION_RTL);
+ TrimData trim_data = shaped_text_get_trim_data(p_shaped);
+
int v_size = visual.size();
const Glyph *glyphs = visual.ptr();
Vector2 ofs = p_pos;
+ // Draw RTL ellipsis string when needed.
+ if (rtl && trim_data.ellipsis_pos >= 0) {
+ for (int i = trim_data.ellipsis_glyph_buf.size() - 1; i >= 0; i--) {
+ for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
+ font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ } else {
+ ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ }
+ }
+ }
+ }
// Draw at the baseline.
for (int i = 0; i < v_size; i++) {
for (int j = 0; j < glyphs[i].repeat; j++) {
@@ -1220,6 +1282,17 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
}
+ if (trim_data.trim_pos >= 0) {
+ if (rtl) {
+ if (i < trim_data.trim_pos) {
+ continue;
+ }
+ } else {
+ if (i >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ break;
+ }
+ }
+ }
if (glyphs[i].font_rid != RID()) {
font_draw_glyph_outline(glyphs[i].font_rid, p_canvas, glyphs[i].font_size, p_outline_size, ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, p_color);
}
@@ -1230,6 +1303,19 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
}
+ // Draw LTR ellipsis string when needed.
+ if (!rtl && trim_data.ellipsis_pos >= 0) {
+ for (int i = 0; i < trim_data.ellipsis_glyph_buf.size(); i++) {
+ for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
+ font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ } else {
+ ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ }
+ }
+ }
+ }
}
RID TextServer::_create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size) {
diff --git a/servers/text_server.h b/servers/text_server.h
index 4c2ada7fc9..26993838a3 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -59,7 +59,8 @@ public:
JUSTIFICATION_KASHIDA = 1 << 0,
JUSTIFICATION_WORD_BOUND = 1 << 1,
JUSTIFICATION_TRIM_EDGE_SPACES = 1 << 2,
- JUSTIFICATION_AFTER_LAST_TAB = 1 << 3
+ JUSTIFICATION_AFTER_LAST_TAB = 1 << 3,
+ JUSTIFICATION_CONSTRAIN_ELLIPSIS = 1 << 4,
};
enum LineBreakFlag {
@@ -67,7 +68,7 @@ public:
BREAK_MANDATORY = 1 << 4,
BREAK_WORD_BOUND = 1 << 5,
BREAK_GRAPHEME_BOUND = 1 << 6,
- BREAK_WORD_BOUND_ADAPTIVE = 1 << 5 | 1 << 7
+ BREAK_WORD_BOUND_ADAPTIVE = 1 << 5 | 1 << 7,
};
enum TextOverrunFlag {
@@ -75,7 +76,8 @@ public:
OVERRUN_TRIM = 1 << 0,
OVERRUN_TRIM_WORD_ONLY = 1 << 1,
OVERRUN_ADD_ELLIPSIS = 1 << 2,
- OVERRUN_ENFORCE_ELLIPSIS = 1 << 3
+ OVERRUN_ENFORCE_ELLIPSIS = 1 << 3,
+ OVERRUN_JUSTIFICATION_AWARE = 1 << 4,
};
enum GraphemeFlag {
@@ -154,6 +156,12 @@ public:
}
};
+ struct TrimData {
+ int trim_pos = -1;
+ int ellipsis_pos = -1;
+ Vector<TextServer::Glyph> ellipsis_glyph_buf;
+ };
+
struct ShapedTextData {
/* Source data */
RID parent; // Substring parent ShapedTextData.
@@ -181,7 +189,7 @@ public:
struct EmbeddedObject {
int pos = 0;
- VAlign inline_align = VALIGN_TOP;
+ InlineAlign inline_align = INLINE_ALIGN_CENTER;
Rect2 rect;
};
Map<Variant, EmbeddedObject> objects;
@@ -192,6 +200,7 @@ public:
bool line_breaks_valid = false; // Line and word break flags are populated (and virtual zero width spaces inserted).
bool justification_ops_valid = false; // Virtual elongation glyphs are added to the string.
bool sort_valid = false;
+ bool text_trimmed = false;
bool preserve_invalid = true; // Draw hex code box instead of missing characters.
bool preserve_control = false; // Draw control characters.
@@ -199,10 +208,14 @@ public:
float ascent = 0.f; // Ascent for horizontal layout, 1/2 of width for vertical.
float descent = 0.f; // Descent for horizontal layout, 1/2 of width for vertical.
float width = 0.f; // Width for horizontal layout, height for vertical.
+ float width_trimmed = 0.f;
float upos = 0.f;
float uthk = 0.f;
+ TrimData overrun_trim_data;
+ bool fit_width_minimum_reached = false;
+
Vector<TextServer::Glyph> glyphs;
Vector<TextServer::Glyph> glyphs_logical;
};
@@ -332,8 +345,8 @@ public:
virtual bool shaped_text_get_preserve_control(RID p_shaped) const = 0;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") = 0;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1) = 0;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER) = 0;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) = 0;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) = 0;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(RID p_shaped) const = 0;
@@ -357,7 +370,8 @@ public:
virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
- virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_clip_flags) = 0;
+ virtual TrimData shaped_text_get_trim_data(RID p_shaped) const;
+ virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_trim_flags) = 0;
virtual Array shaped_text_get_objects(RID p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0;