summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer.h15
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp291
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h46
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp9
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.h5
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp12
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp96
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.h11
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp542
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.h57
-rw-r--r--servers/rendering/rasterizer_rd/shader_compiler_rd.cpp5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/SCsub1
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas.glsl38
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl18
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl135
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl26
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl33
-rw-r--r--servers/rendering/rasterizer_rd/shaders/tonemap.glsl24
-rw-r--r--servers/rendering/rendering_server_canvas.cpp228
-rw-r--r--servers/rendering/rendering_server_canvas.h7
-rw-r--r--servers/rendering/rendering_server_raster.h8
-rw-r--r--servers/rendering/rendering_server_scene.cpp6
-rw-r--r--servers/rendering/rendering_server_scene.h1
-rw-r--r--servers/rendering/rendering_server_viewport.cpp45
-rw-r--r--servers/rendering/rendering_server_viewport.h5
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h9
-rw-r--r--servers/rendering/shader_types.cpp27
27 files changed, 1407 insertions, 293 deletions
diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h
index 01c957e242..30577e6247 100644
--- a/servers/rendering/rasterizer.h
+++ b/servers/rendering/rasterizer.h
@@ -109,7 +109,7 @@ public:
virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
- virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
+ virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
@@ -522,6 +522,8 @@ public:
virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
+ virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0;
+ virtual bool light_directional_is_sky_only(RID p_light) const = 0;
virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0;
@@ -752,6 +754,9 @@ public:
virtual void render_target_disable_clear_request(RID p_render_target) = 0;
virtual void render_target_do_clear_request(RID p_render_target) = 0;
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
+
virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
virtual bool free(RID p_rid) = 0;
@@ -1324,7 +1329,7 @@ public:
}
};
- virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) = 0;
+ virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) = 0;
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
struct LightOccluderInstance {
@@ -1336,12 +1341,14 @@ public:
Transform2D xform;
Transform2D xform_cache;
int light_mask;
+ bool sdf_collision;
RS::CanvasOccluderPolygonCullMode cull_cache;
LightOccluderInstance *next;
LightOccluderInstance() {
enabled = true;
+ sdf_collision = false;
next = nullptr;
light_mask = 1;
cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
@@ -1354,8 +1361,10 @@ public:
virtual void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0;
virtual void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) = 0;
+ virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) = 0;
+
virtual RID occluder_polygon_create() = 0;
- virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) = 0;
+ virtual void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) = 0;
virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0;
virtual void set_shadow_texture_size(int p_size) = 0;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
index 174f2d0e58..f5360cbd36 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -30,6 +30,7 @@
#include "rasterizer_canvas_rd.h"
#include "core/config/project_settings.h"
+#include "core/math/geometry_2d.h"
#include "core/math/math_funcs.h"
#include "rasterizer_rd.h"
@@ -118,9 +119,9 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
Vector<uint8_t> polygon_buffer;
polygon_buffer.resize(buffer_size * sizeof(float));
Vector<RD::VertexAttribute> descriptions;
- descriptions.resize(4);
+ descriptions.resize(5);
Vector<RID> buffers;
- buffers.resize(4);
+ buffers.resize(5);
{
const uint8_t *r = polygon_buffer.ptr();
@@ -217,7 +218,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
//bones
if ((uint32_t)p_indices.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) {
RD::VertexAttribute vd;
- vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_BONES;
vd.stride = stride * sizeof(float);
@@ -225,16 +226,42 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
descriptions.write[3] = vd;
const int *bone_ptr = p_bones.ptr();
- const float *weight_ptr = p_weights.ptr();
for (uint32_t i = 0; i < vertex_count; i++) {
uint16_t *bone16w = (uint16_t *)&uptr[base_offset + i * stride];
- uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride + 2];
bone16w[0] = bone_ptr[i * 4 + 0];
bone16w[1] = bone_ptr[i * 4 + 1];
bone16w[2] = bone_ptr[i * 4 + 2];
bone16w[3] = bone_ptr[i * 4 + 3];
+ }
+
+ base_offset += 2;
+ } else {
+ RD::VertexAttribute vd;
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ vd.offset = 0;
+ vd.location = RS::ARRAY_BONES;
+ vd.stride = 0;
+
+ descriptions.write[3] = vd;
+ buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES);
+ }
+
+ //weights
+ if ((uint32_t)p_weights.size() == vertex_count * 4) {
+ RD::VertexAttribute vd;
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
+ vd.offset = base_offset * sizeof(float);
+ vd.location = RS::ARRAY_WEIGHTS;
+ vd.stride = stride * sizeof(float);
+
+ descriptions.write[4] = vd;
+
+ const float *weight_ptr = p_weights.ptr();
+
+ for (uint32_t i = 0; i < vertex_count; i++) {
+ uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride];
weight16w[0] = CLAMP(weight_ptr[i * 4 + 0] * 65535, 0, 65535);
weight16w[1] = CLAMP(weight_ptr[i * 4 + 1] * 65535, 0, 65535);
@@ -242,16 +269,16 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
weight16w[3] = CLAMP(weight_ptr[i * 4 + 3] * 65535, 0, 65535);
}
- base_offset += 4;
+ base_offset += 2;
} else {
RD::VertexAttribute vd;
- vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = 0;
- vd.location = RS::ARRAY_BONES;
+ vd.location = RS::ARRAY_WEIGHTS;
vd.stride = 0;
- descriptions.write[3] = vd;
- buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES);
+ descriptions.write[4] = vd;
+ buffers.write[4] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES);
}
//check that everything is as it should be
@@ -1051,10 +1078,19 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_
}
{
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 7;
+ RID sdf = storage->render_target_get_sdf_texture(p_to_render_target);
+ u.ids.push_back(sdf);
+ uniforms.push_back(u);
+ }
+
+ {
//needs samplers for the material (uses custom textures) create them
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 7;
+ u.binding = 8;
u.ids.resize(12);
RID *ids_ptr = u.ids.ptrw();
ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -1075,7 +1111,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 8;
+ u.binding = 9;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1182,7 +1218,8 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
RD::get_singleton()->draw_list_end();
}
-void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) {
+void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
+ r_sdf_used = false;
int item_count = 0;
//setup canvas state uniforms if needed
@@ -1365,6 +1402,25 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
state_buffer.directional_light_count = directional_light_count;
+ Vector2 canvas_scale = p_canvas_transform.get_scale();
+
+ state_buffer.sdf_to_screen[0] = render_target_size.width / canvas_scale.x;
+ state_buffer.sdf_to_screen[1] = render_target_size.height / canvas_scale.y;
+
+ state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
+ state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
+
+ Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
+ Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
+
+ state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
+ state_buffer.sdf_to_tex[1] = 1.0 / sdf_tex_rect.size.height;
+ state_buffer.sdf_to_tex[2] = -sdf_tex_rect.position.x / sdf_tex_rect.size.width;
+ state_buffer.sdf_to_tex[3] = -sdf_tex_rect.position.y / sdf_tex_rect.size.height;
+
+ //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale));
+ state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5);
+
RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true);
}
@@ -1402,6 +1458,9 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
}
+ if (md->shader_data->uses_sdf) {
+ r_sdf_used = true;
+ }
if (md->last_frame != RasterizerRD::singleton->get_frame_number()) {
md->last_frame = RasterizerRD::singleton->get_frame_number();
if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
@@ -1687,18 +1746,105 @@ void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow
cl->shadow.directional_xform = to_shadow * to_light_xform;
}
+void RasterizerCanvasRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) {
+ RID fb = storage->render_target_get_sdf_framebuffer(p_render_target);
+ Rect2i rect = storage->render_target_get_sdf_rect(p_render_target);
+
+ Transform2D to_sdf;
+ to_sdf.elements[0] *= rect.size.width;
+ to_sdf.elements[1] *= rect.size.height;
+ to_sdf.elements[2] = rect.position;
+
+ Transform2D to_clip;
+ to_clip.elements[0] *= 2.0;
+ to_clip.elements[1] *= 2.0;
+ to_clip.elements[2] = -Vector2(1.0, 1.0);
+
+ to_clip = to_clip * to_sdf.affine_inverse();
+
+ Vector<Color> cc;
+ cc.push_back(Color(0, 0, 0, 0));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc);
+
+ CameraMatrix projection;
+
+ ShadowRenderPushConstant push_constant;
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 4; x++) {
+ push_constant.projection[y * 4 + x] = projection.matrix[y][x];
+ }
+ }
+
+ push_constant.direction[0] = 0.0;
+ push_constant.direction[1] = 0.0;
+ push_constant.z_far = 0;
+ push_constant.pad = 0;
+
+ LightOccluderInstance *instance = p_occluders;
+
+ while (instance) {
+ OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
+
+ if (!co || co->sdf_index_array.is_null()) {
+ instance = instance->next;
+ continue;
+ }
+
+ _update_transform_2d_to_mat2x4(to_clip * instance->xform_cache, push_constant.modelview);
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.sdf_render_pipelines[co->sdf_is_lines ? SHADOW_RENDER_SDF_LINES : SHADOW_RENDER_SDF_TRIANGLES]);
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->sdf_vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, co->sdf_index_array);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+
+ instance = instance->next;
+ }
+
+ RD::get_singleton()->draw_list_end();
+
+ storage->render_target_sdf_process(p_render_target); //done rendering, process it
+}
+
RID RasterizerCanvasRD::occluder_polygon_create() {
OccluderPolygon occluder;
- occluder.point_count = 0;
+ occluder.line_point_count = 0;
+ occluder.sdf_point_count = 0;
+ occluder.sdf_index_count = 0;
occluder.cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
return occluder_polygon_owner.make_rid(occluder);
}
-void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) {
+void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) {
OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder);
ERR_FAIL_COND(!oc);
- if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) {
+ Vector<Vector2> lines;
+
+ if (p_points.size()) {
+ int lc = p_points.size() * 2;
+
+ lines.resize(lc - (p_closed ? 0 : 2));
+ {
+ Vector2 *w = lines.ptrw();
+ const Vector2 *r = p_points.ptr();
+
+ int max = lc / 2;
+ if (!p_closed) {
+ max--;
+ }
+ for (int i = 0; i < max; i++) {
+ Vector2 a = r[i];
+ Vector2 b = r[(i + 1) % (lc / 2)];
+ w[i * 2 + 0] = a;
+ w[i * 2 + 1] = b;
+ }
+ }
+ }
+
+ if (oc->line_point_count != lines.size() && oc->vertex_array.is_valid()) {
RD::get_singleton()->free(oc->vertex_array);
RD::get_singleton()->free(oc->vertex_buffer);
RD::get_singleton()->free(oc->index_array);
@@ -1708,12 +1854,14 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
oc->vertex_buffer = RID();
oc->index_array = RID();
oc->index_buffer = RID();
+
+ oc->line_point_count = lines.size();
}
- if (p_lines.size()) {
+ if (lines.size()) {
Vector<uint8_t> geometry;
Vector<uint8_t> indices;
- int lc = p_lines.size();
+ int lc = lines.size();
geometry.resize(lc * 6 * sizeof(float));
indices.resize(lc * 3 * sizeof(uint16_t));
@@ -1724,7 +1872,7 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
uint8_t *iw = indices.ptrw();
uint16_t *iwptr = (uint16_t *)iw;
- const Vector2 *lr = p_lines.ptr();
+ const Vector2 *lr = lines.ptr();
const int POLY_HEIGHT = 16384;
@@ -1778,6 +1926,64 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
RD::get_singleton()->buffer_update(oc->index_buffer, 0, indices.size(), ir);
}
}
+
+ // sdf
+
+ Vector<int> sdf_indices;
+
+ if (p_points.size()) {
+ if (p_closed) {
+ sdf_indices = Geometry2D::triangulate_polygon(p_points);
+ oc->sdf_is_lines = false;
+ } else {
+ int max = p_points.size();
+ sdf_indices.resize(max * 2);
+
+ int *iw = sdf_indices.ptrw();
+ for (int i = 0; i < max; i++) {
+ iw[i * 2 + 0] = i;
+ iw[i * 2 + 1] = (i + 1) % max;
+ }
+ oc->sdf_is_lines = true;
+ }
+ }
+
+ if (oc->sdf_index_count != sdf_indices.size() && oc->sdf_point_count != p_points.size() && oc->sdf_vertex_array.is_valid()) {
+ RD::get_singleton()->free(oc->sdf_vertex_array);
+ RD::get_singleton()->free(oc->sdf_vertex_buffer);
+ RD::get_singleton()->free(oc->sdf_index_array);
+ RD::get_singleton()->free(oc->sdf_index_buffer);
+
+ oc->sdf_vertex_array = RID();
+ oc->sdf_vertex_buffer = RID();
+ oc->sdf_index_array = RID();
+ oc->sdf_index_buffer = RID();
+
+ oc->sdf_index_count = sdf_indices.size();
+ oc->sdf_point_count = p_points.size();
+
+ oc->sdf_is_lines = false;
+ }
+
+ if (sdf_indices.size()) {
+ if (oc->sdf_vertex_array.is_null()) {
+ //create from scratch
+ //vertices
+ oc->sdf_vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_points.size() * 2 * sizeof(real_t), p_points.to_byte_array());
+ oc->sdf_index_buffer = RD::get_singleton()->index_buffer_create(sdf_indices.size(), RD::INDEX_BUFFER_FORMAT_UINT32, sdf_indices.to_byte_array());
+ oc->sdf_index_array = RD::get_singleton()->index_array_create(oc->sdf_index_buffer, 0, sdf_indices.size());
+
+ Vector<RID> buffer;
+ buffer.push_back(oc->sdf_vertex_buffer);
+ oc->sdf_vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), shadow_render.sdf_vertex_format, buffer);
+ //indices
+
+ } else {
+ //update existing
+ RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr());
+ RD::get_singleton()->buffer_update(oc->index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr());
+ }
+ }
}
void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) {
@@ -1794,6 +2000,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
+ uses_sdf = false;
if (code == String()) {
return; //just invalid, but no error
@@ -1801,7 +2008,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
ShaderCompilerRD::GeneratedCode gen_code;
- int light_mode = LIGHT_MODE_NORMAL;
int blend_mode = BLEND_MODE_MIX;
uses_screen_texture = false;
@@ -1814,10 +2020,8 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA);
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED);
- actions.render_mode_values["unshaded"] = Pair<int *, int>(&light_mode, LIGHT_MODE_UNSHADED);
- actions.render_mode_values["light_only"] = Pair<int *, int>(&light_mode, LIGHT_MODE_LIGHT_ONLY);
-
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
+ actions.usage_flag_pointers["texture_sdf"] = &uses_sdf;
actions.uniforms = &uniforms;
@@ -2038,6 +2242,7 @@ Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &
RasterizerCanvasRD::ShaderData::ShaderData() {
valid = false;
uses_screen_texture = false;
+ uses_sdf = false;
}
RasterizerCanvasRD::ShaderData::~ShaderData() {
@@ -2302,6 +2507,11 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
actions.renames["LIGHT"] = "light";
actions.renames["SHADOW_MODULATE"] = "shadow_modulate";
+ actions.renames["texture_sdf"] = "texture_sdf";
+ actions.renames["texture_sdf_normal"] = "texture_sdf_normal";
+ actions.renames["sdf_to_screen_uv"] = "sdf_to_screen_uv";
+ actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf";
+
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
@@ -2311,6 +2521,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
+ actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
+ actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n";
actions.custom_samplers["TEXTURE"] = "texture_sampler";
actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler";
@@ -2331,7 +2543,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
{ //shadow rendering
Vector<String> versions;
- versions.push_back(String()); //no versions
+ versions.push_back("\n#define MODE_SHADOW\n"); //shadow
+ versions.push_back("\n#define MODE_SDF\n"); //sdf
shadow_render.shader.initialize(versions);
{
@@ -2352,16 +2565,34 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
shadow_render.framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments);
}
+ {
+ Vector<RD::AttachmentFormat> attachments;
+
+ RD::AttachmentFormat af_color;
+ af_color.format = RD::DATA_FORMAT_R8_UNORM;
+ af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ attachments.push_back(af_color);
+
+ shadow_render.sdf_framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments);
+ }
+
//pipelines
Vector<RD::VertexAttribute> vf;
RD::VertexAttribute vd;
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ vd.format = sizeof(real_t) == sizeof(float) ? RD::DATA_FORMAT_R32G32B32_SFLOAT : RD::DATA_FORMAT_R64G64B64_SFLOAT;
vd.location = 0;
vd.offset = 0;
- vd.stride = sizeof(float) * 3;
+ vd.stride = sizeof(real_t) * 3;
vf.push_back(vd);
shadow_render.vertex_format = RD::get_singleton()->vertex_format_create(vf);
+ vd.format = sizeof(real_t) == sizeof(float) ? RD::DATA_FORMAT_R32G32_SFLOAT : RD::DATA_FORMAT_R64G64_SFLOAT;
+ vd.stride = sizeof(real_t) * 2;
+
+ vf.write[0] = vd;
+ shadow_render.sdf_vertex_format = RD::get_singleton()->vertex_format_create(vf);
+
shadow_render.shader_version = shadow_render.shader.version_create();
for (int i = 0; i < 3; i++) {
@@ -2371,7 +2602,11 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
ds.enable_depth_write = true;
ds.enable_depth_test = true;
ds.depth_compare_operator = RD::COMPARE_OP_LESS;
- shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
+ shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, SHADOW_RENDER_MODE_SHADOW), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+
+ for (int i = 0; i < 2; i++) {
+ shadow_render.sdf_render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, SHADOW_RENDER_MODE_SDF), shadow_render.sdf_framebuffer_format, shadow_render.sdf_vertex_format, i == 0 ? RD::RENDER_PRIMITIVE_TRIANGLES : RD::RENDER_PRIMITIVE_LINES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}
}
@@ -2482,7 +2717,7 @@ bool RasterizerCanvasRD::free(RID p_rid) {
light_set_use_shadow(p_rid, false);
canvas_light_owner.free(p_rid);
} else if (occluder_polygon_owner.owns(p_rid)) {
- occluder_polygon_set_shape_as_lines(p_rid, Vector<Vector2>());
+ occluder_polygon_set_shape(p_rid, Vector<Vector2>(), false);
occluder_polygon_owner.free(p_rid);
} else {
return false;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
index b516f63cbf..b09d6578f3 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
@@ -161,12 +161,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
BLEND_MODE_DISABLED,
};
- enum LightMode {
- LIGHT_MODE_NORMAL,
- LIGHT_MODE_UNSHADED,
- LIGHT_MODE_LIGHT_ONLY
- };
-
bool valid;
RID version;
PipelineVariants pipeline_variants;
@@ -181,7 +175,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
String code;
Map<StringName, RID> default_texture_params;
- bool uses_screen_texture;
+ bool uses_screen_texture = false;
+ bool uses_sdf = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
@@ -284,11 +279,19 @@ class RasterizerCanvasRD : public RasterizerCanvas {
struct OccluderPolygon {
RS::CanvasOccluderPolygonCullMode cull_mode;
- int point_count;
+ int line_point_count;
RID vertex_buffer;
RID vertex_array;
RID index_buffer;
RID index_array;
+
+ int sdf_point_count;
+ int sdf_index_count;
+ RID sdf_vertex_buffer;
+ RID sdf_vertex_array;
+ RID sdf_index_buffer;
+ RID sdf_index_array;
+ bool sdf_is_lines;
};
struct LightUniform {
@@ -310,12 +313,25 @@ class RasterizerCanvasRD : public RasterizerCanvas {
RID_Owner<OccluderPolygon> occluder_polygon_owner;
+ enum ShadowRenderMode {
+ SHADOW_RENDER_MODE_SHADOW,
+ SHADOW_RENDER_MODE_SDF,
+ };
+
+ enum {
+ SHADOW_RENDER_SDF_TRIANGLES,
+ SHADOW_RENDER_SDF_LINES,
+ };
+
struct {
CanvasOcclusionShaderRD shader;
RID shader_version;
RID render_pipelines[3];
+ RID sdf_render_pipelines[2];
RD::VertexFormatID vertex_format;
+ RD::VertexFormatID sdf_vertex_format;
RD::FramebufferFormatID framebuffer_format;
+ RD::FramebufferFormatID sdf_framebuffer_format;
} shadow_render;
/***************/
@@ -336,8 +352,14 @@ class RasterizerCanvasRD : public RasterizerCanvas {
float time;
uint32_t use_pixel_snap;
+ float sdf_to_tex[4];
+ float sdf_to_screen[2];
+ float screen_to_sdf[2];
+
uint32_t directional_light_count;
- uint32_t pad[3];
+ float tex_to_sdf;
+ uint32_t pad1;
+ uint32_t pad2;
};
LightUniform *light_uniforms;
@@ -423,11 +445,13 @@ public:
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders);
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders);
+ virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders);
+
RID occluder_polygon_create();
- void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines);
+ void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed);
void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode);
- void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel);
+ void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used);
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
index 97c1e7ba70..df94921652 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -94,7 +94,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use
u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
u.ids.push_back(p_texture);
uniforms.push_back(u);
- //any thing 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;
@@ -718,7 +718,10 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y;
tonemap.push_constant.glow_mode = p_settings.glow_mode;
- TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL;
+ int mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL;
+ if (p_settings.use_1d_color_correction) {
+ mode += 2;
+ }
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
@@ -1423,6 +1426,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
Vector<String> tonemap_modes;
tonemap_modes.push_back("\n");
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.shader.initialize(tonemap_modes);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
index a0bdd59fd2..0b8d3a8f27 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
@@ -167,6 +167,8 @@ class RasterizerEffectsRD {
enum TonemapMode {
TONEMAP_MODE_NORMAL,
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
+ TONEMAP_MODE_1D_LUT,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
TONEMAP_MODE_MAX
};
@@ -198,7 +200,7 @@ class RasterizerEffectsRD {
/* tonemap actually writes to a framebuffer, which is
* better to do using the raster pipeline rather than
- * comptute, as that framebuffer might be in different formats
+ * compute, as that framebuffer might be in different formats
*/
struct Tonemap {
TonemapPushConstant push_constant;
@@ -654,6 +656,7 @@ public:
float saturation = 1.0;
bool use_color_correction = false;
+ bool use_1d_color_correction = false;
RID color_correction_texture;
bool use_fxaa = false;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
index 313188ba87..66561958fc 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -2795,6 +2795,12 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.renames["FOG"] = "custom_fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
+ actions.renames["BONE_INDICES"] = "bone_attrib";
+ actions.renames["BONE_WEIGHTS"] = "weight_attrib";
+ actions.renames["CUSTOM0"] = "custom0_attrib";
+ actions.renames["CUSTOM1"] = "custom1_attrib";
+ actions.renames["CUSTOM2"] = "custom2_attrib";
+ actions.renames["CUSTOM3"] = "custom3_attrib";
//for light
actions.renames["VIEW"] = "view";
@@ -2817,6 +2823,12 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n";
actions.usage_defines["UV"] = "#define UV_USED\n";
actions.usage_defines["UV2"] = "#define UV2_USED\n";
+ actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";
+ actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n";
+ actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n";
+ actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n";
+ actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n";
+ actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n";
actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
index 12fcc6fbb9..d6f08370e0 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -1186,6 +1186,11 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm
LightInstance *li = light_instance_owner.getornull(p_directional_light_instances[j]);
ERR_CONTINUE(!li);
+
+ if (storage->light_directional_is_sky_only(li->light)) {
+ continue;
+ }
+
Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
dir.y *= rb->sdfgi->y_mult;
dir.normalize();
@@ -4392,6 +4397,11 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
RID light = light_instance_get_base_light(light_instance);
l.type = storage->light_get_type(light);
+ if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_is_sky_only(light)) {
+ light_count--;
+ continue;
+ }
+
l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
@@ -5290,8 +5300,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
//tonemap
RasterizerEffectsRD::TonemapSettings tonemap;
- tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-
if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
tonemap.use_auto_exposure = true;
tonemap.exposure_texture = rb->luminance.current;
@@ -5328,6 +5336,22 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
tonemap.exposure = env->exposure;
}
+ tonemap.use_color_correction = false;
+ tonemap.use_1d_color_correction = false;
+ tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::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);
+ }
+ }
+
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
}
@@ -5395,6 +5419,18 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
}
}
+void RasterizerSceneRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
+ Environment *env = environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->adjustments_enabled = p_enable;
+ env->adjustments_brightness = p_brightness;
+ env->adjustments_contrast = p_contrast;
+ env->adjustments_saturation = p_saturation;
+ env->use_1d_color_correction = p_use_1d_color_correction;
+ env->color_correction = p_color_correction;
+}
+
void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -5931,7 +5967,40 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull
RS::LightType type = storage->light_get_type(base);
switch (type) {
case RS::LIGHT_DIRECTIONAL: {
- if (r_directional_light_count >= cluster.max_directional_lights) {
+ // Copy to SkyDirectionalLightData
+ if (r_directional_light_count < sky_scene_state.max_directional_lights) {
+ SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count];
+ Transform light_transform = light_instance_get_base_transform(li);
+ Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
+
+ sky_light_data.direction[0] = world_direction.x;
+ sky_light_data.direction[1] = world_direction.y;
+ sky_light_data.direction[2] = -world_direction.z;
+
+ float sign = storage->light_is_negative(base) ? -1 : 1;
+ sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+
+ Color linear_col = storage->light_get_color(base).to_linear();
+ sky_light_data.color[0] = linear_col.r;
+ sky_light_data.color[1] = linear_col.g;
+ sky_light_data.color[2] = linear_col.b;
+
+ sky_light_data.enabled = true;
+
+ float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ if (angular_diameter > 0.0) {
+ // I know tan(0) is 0, but let's not risk it with numerical precision.
+ // technically this will keep expanding until reaching the sun, but all we care
+ // is expand until we reach the radius of the near plane (there can't be more occluders than that)
+ angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
+ } else {
+ angular_diameter = 0.0;
+ }
+ sky_light_data.size = angular_diameter;
+ sky_scene_state.ubo.directional_light_count++;
+ }
+
+ if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) {
continue;
}
@@ -6074,27 +6143,6 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull
}
}
- // Copy to SkyDirectionalLightData
- if (r_directional_light_count < sky_scene_state.max_directional_lights) {
- SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count];
-
- Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
-
- sky_light_data.direction[0] = world_direction.x;
- sky_light_data.direction[1] = world_direction.y;
- sky_light_data.direction[2] = -world_direction.z;
-
- sky_light_data.energy = light_data.energy / Math_PI;
-
- sky_light_data.color[0] = light_data.color[0];
- sky_light_data.color[1] = light_data.color[1];
- sky_light_data.color[2] = light_data.color[2];
-
- sky_light_data.enabled = true;
- sky_light_data.size = angular_diameter;
- sky_scene_state.ubo.directional_light_count++;
- }
-
r_directional_light_count++;
} break;
case RS::LIGHT_SPOT:
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
index 3d5310bb7e..6aa79208ea 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
@@ -763,6 +763,15 @@ private:
float sdfgi_normal_bias = 1.1;
float sdfgi_probe_bias = 1.1;
RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED;
+
+ /// Adjustments
+
+ bool adjustments_enabled = false;
+ float adjustments_brightness = 1.0f;
+ float adjustments_contrast = 1.0f;
+ float adjustments_saturation = 1.0f;
+ bool use_1d_color_correction = false;
+ RID color_correction = RID();
};
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
@@ -1571,7 +1580,7 @@ public:
RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {}
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
index 5fd8003f8f..819404b316 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -2398,13 +2398,15 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
ERR_FAIL_COND(!mesh);
//ensure blend shape consistency
- ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shapes.size() != (int)mesh->blend_shape_count);
+ ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shape_count != mesh->blend_shape_count);
ERR_FAIL_COND(mesh->blend_shape_count && p_surface.bone_aabbs.size() != mesh->bone_aabbs.size());
#ifdef DEBUG_ENABLED
//do a validation, to catch errors first
{
uint32_t stride = 0;
+ uint32_t attrib_stride = 0;
+ uint32_t skin_stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
if ((p_surface.format & (1 << i))) {
@@ -2418,59 +2420,54 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_NORMAL: {
- if (p_surface.format & RS::ARRAY_COMPRESS_NORMAL) {
- stride += sizeof(int8_t) * 4;
- } else {
- stride += sizeof(float) * 4;
- }
+ stride += sizeof(int32_t);
} break;
case RS::ARRAY_TANGENT: {
- if (p_surface.format & RS::ARRAY_COMPRESS_TANGENT) {
- stride += sizeof(int8_t) * 4;
- } else {
- stride += sizeof(float) * 4;
- }
+ stride += sizeof(int32_t);
} break;
case RS::ARRAY_COLOR: {
- if (p_surface.format & RS::ARRAY_COMPRESS_COLOR) {
- stride += sizeof(int8_t) * 4;
- } else {
- stride += sizeof(float) * 4;
- }
-
+ attrib_stride += sizeof(int16_t) * 4;
} break;
case RS::ARRAY_TEX_UV: {
- if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV) {
- stride += sizeof(int16_t) * 2;
- } else {
- stride += sizeof(float) * 2;
- }
+ attrib_stride += sizeof(float) * 2;
} break;
case RS::ARRAY_TEX_UV2: {
- if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV2) {
- stride += sizeof(int16_t) * 2;
- } else {
- stride += sizeof(float) * 2;
- }
+ attrib_stride += sizeof(float) * 2;
} break;
- case RS::ARRAY_BONES: {
- //assumed weights too
-
- //unique format, internally 16 bits, exposed as single array for 32
-
- stride += sizeof(int32_t) * 4;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ int idx = i - RS::ARRAY_CUSTOM0;
+ uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
+ uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ attrib_stride += fmtsize[fmt];
} break;
+ case RS::ARRAY_WEIGHTS:
+ case RS::ARRAY_BONES: {
+ //uses a separate array
+ bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ skin_stride += sizeof(int16_t) * (use_8 ? 8 : 4);
+ } break;
}
}
}
int expected_size = stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+ ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+ int expected_attrib_size = attrib_stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")");
+
+ if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) {
+ expected_size = skin_stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+ }
}
#endif
@@ -2481,6 +2478,12 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
s->primitive = p_surface.primitive;
s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data);
+ if (p_surface.attribute_data.size()) {
+ s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
+ }
+ if (p_surface.skin_data.size()) {
+ s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data);
+ }
s->vertex_count = p_surface.vertex_count;
if (p_surface.index_count) {
@@ -2504,7 +2507,7 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
-
+#if 0
for (int i = 0; i < p_surface.blend_shapes.size(); i++) {
if (p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()) {
memdelete(s);
@@ -2513,8 +2516,8 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
RID vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.blend_shapes[i].size(), p_surface.blend_shapes[i]);
s->blend_shapes.push_back(vertex_buffer);
}
-
- mesh->blend_shape_count = p_surface.blend_shapes.size();
+#endif
+ mesh->blend_shape_count = p_surface.blend_shape_count;
if (mesh->surface_count == 0) {
mesh->bone_aabbs = p_surface.bone_aabbs;
@@ -2596,6 +2599,12 @@ RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface)
RS::SurfaceData sd;
sd.format = s.format;
sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.attribute_buffer.is_valid()) {
+ sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
+ }
+ if (s.skin_buffer.is_valid()) {
+ sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer);
+ }
sd.vertex_count = s.vertex_count;
sd.index_count = s.index_count;
sd.primitive = s.primitive;
@@ -2613,9 +2622,8 @@ RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface)
sd.bone_aabbs = s.bone_aabbs;
- for (int i = 0; i < s.blend_shapes.size(); i++) {
- Vector<uint8_t> bs = RD::get_singleton()->buffer_get_data(s.blend_shapes[i]);
- sd.blend_shapes.push_back(bs);
+ if (s.blend_shape_buffer.is_valid()) {
+ sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
}
return sd;
@@ -2750,6 +2758,12 @@ void RasterizerStorageRD::mesh_clear(RID p_mesh) {
for (uint32_t i = 0; i < mesh->surface_count; i++) {
Mesh::Surface &s = *mesh->surfaces[i];
RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ if (s.attribute_buffer.is_valid()) {
+ RD::get_singleton()->free(s.attribute_buffer);
+ }
+ if (s.skin_buffer.is_valid()) {
+ RD::get_singleton()->free(s.skin_buffer);
+ }
if (s.versions) {
memfree(s.versions); //reallocs, so free with memfree.
}
@@ -2765,12 +2779,8 @@ void RasterizerStorageRD::mesh_clear(RID p_mesh) {
memdelete_arr(s.lods);
}
- for (int32_t j = 0; j < s.blend_shapes.size(); j++) {
- RD::get_singleton()->free(s.blend_shapes[j]);
- }
-
- if (s.blend_shape_base_buffer.is_valid()) {
- RD::get_singleton()->free(s.blend_shape_base_buffer);
+ if (s.blend_shape_buffer.is_valid()) {
+ RD::get_singleton()->free(s.blend_shape_buffer);
}
memdelete(mesh->surfaces[i]);
@@ -2796,8 +2806,10 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
Vector<RID> buffers;
uint32_t stride = 0;
+ uint32_t attribute_stride = 0;
+ uint32_t skin_stride = 0;
- for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
+ for (int i = 0; i < RS::ARRAY_INDEX; i++) {
RD::VertexAttribute vd;
RID buffer;
vd.location = i;
@@ -2805,6 +2817,7 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
if (!(s->format & (1 << i))) {
// Not supplied by surface, use default value
buffer = mesh_default_rd_buffers[i];
+ vd.stride = 0;
switch (i) {
case RS::ARRAY_VERTEX: {
vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
@@ -2827,20 +2840,31 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
case RS::ARRAY_TEX_UV2: {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
} break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
case RS::ARRAY_BONES: {
//assumed weights too
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
} break;
+ case RS::ARRAY_WEIGHTS: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ } break;
}
} else {
//Supplied, use it
- vd.offset = stride;
- vd.stride = 1; //mark that it needs a stride set
- buffer = s->vertex_buffer;
+ vd.stride = 1; //mark that it needs a stride set (default uses 0)
switch (i) {
case RS::ARRAY_VERTEX: {
+ vd.offset = stride;
+
if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
stride += sizeof(float) * 2;
@@ -2849,71 +2873,80 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
stride += sizeof(float) * 3;
}
+ buffer = s->vertex_buffer;
+
} break;
case RS::ARRAY_NORMAL: {
- if (s->format & RS::ARRAY_COMPRESS_NORMAL) {
- vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
- stride += sizeof(int8_t) * 4;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- stride += sizeof(float) * 4;
- }
+ vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+
+ stride += sizeof(uint32_t);
+ buffer = s->vertex_buffer;
} break;
case RS::ARRAY_TANGENT: {
- if (s->format & RS::ARRAY_COMPRESS_TANGENT) {
- vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
- stride += sizeof(int8_t) * 4;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- stride += sizeof(float) * 4;
- }
+ vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+ stride += sizeof(uint32_t);
+ buffer = s->vertex_buffer;
} break;
case RS::ARRAY_COLOR: {
- if (s->format & RS::ARRAY_COMPRESS_COLOR) {
- vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- stride += sizeof(int8_t) * 4;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- stride += sizeof(float) * 4;
- }
+ vd.offset = attribute_stride;
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ attribute_stride += sizeof(int16_t) * 4;
+ buffer = s->attribute_buffer;
} break;
case RS::ARRAY_TEX_UV: {
- if (s->format & RS::ARRAY_COMPRESS_TEX_UV) {
- vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
- stride += sizeof(int16_t) * 2;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- stride += sizeof(float) * 2;
- }
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ attribute_stride += sizeof(float) * 2;
+ buffer = s->attribute_buffer;
} break;
case RS::ARRAY_TEX_UV2: {
- if (s->format & RS::ARRAY_COMPRESS_TEX_UV2) {
- vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
- stride += sizeof(int16_t) * 2;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- stride += sizeof(float) * 2;
- }
+ vd.offset = attribute_stride;
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ attribute_stride += sizeof(float) * 2;
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ vd.offset = attribute_stride;
+
+ int idx = i - RS::ARRAY_CUSTOM0;
+ uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
+ uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT };
+ vd.format = fmtrd[fmt];
+ attribute_stride += fmtsize[fmt];
+ buffer = s->attribute_buffer;
} break;
case RS::ARRAY_BONES: {
- //assumed weights too
-
- //unique format, internally 16 bits, exposed as single array for 32
+ vd.offset = skin_stride;
- vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
- stride += sizeof(int32_t) * 4;
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
+ skin_stride += sizeof(int16_t) * 4;
+ buffer = s->skin_buffer;
+ } break;
+ case RS::ARRAY_WEIGHTS: {
+ vd.offset = skin_stride;
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
+ skin_stride += sizeof(int16_t) * 4;
+ buffer = s->skin_buffer;
} break;
}
}
if (!(p_input_mask & (1 << i))) {
- continue; // Shader does not need this, skip it
+ continue; // Shader does not need this, skip it (but computing stride was important anyway)
}
attributes.push_back(vd);
@@ -2922,8 +2955,17 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
//update final stride
for (int i = 0; i < attributes.size(); i++) {
- if (attributes[i].stride == 1) {
+ if (attributes[i].stride == 0) {
+ continue; //default location
+ }
+ int loc = attributes[i].location;
+
+ if (loc < RS::ARRAY_COLOR) {
attributes.write[i].stride = stride;
+ } else if (loc < RS::ARRAY_BONES) {
+ attributes.write[i].stride = attribute_stride;
+ } else {
+ attributes.write[i].stride = skin_stride;
}
}
@@ -5120,6 +5162,20 @@ bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const
return light->directional_blend_splits;
}
+void RasterizerStorageRD::light_directional_set_sky_only(RID p_light, bool p_sky_only) {
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_sky_only = p_sky_only;
+}
+
+bool RasterizerStorageRD::light_directional_is_sky_only(RID p_light) const {
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, false);
+
+ return light->directional_sky_only;
+}
+
RS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
@@ -6029,6 +6085,8 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
rt->backbuffer_uniform_set = RID(); //chain deleted
}
+ _render_target_clear_sdf(rt);
+
rt->framebuffer = RID();
rt->color = RID();
}
@@ -6299,6 +6357,275 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
rt->clear_requested = false;
}
+void RasterizerStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
+ return;
+ }
+
+ rt->sdf_oversize = p_size;
+ rt->sdf_scale = p_scale;
+
+ _render_target_clear_sdf(rt);
+}
+
+Rect2i RasterizerStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const {
+ Size2i margin;
+ int scale;
+ switch (rt->sdf_oversize) {
+ case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
+ scale = 100;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
+ scale = 120;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
+ scale = 150;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
+ scale = 200;
+ } break;
+ default: {
+ }
+ }
+
+ margin = (rt->size * scale / 100) - rt->size;
+
+ Rect2i r(Vector2i(), rt->size);
+ r.position -= margin;
+ r.size += margin * 2;
+
+ return r;
+}
+
+Rect2i RasterizerStorageRD::render_target_get_sdf_rect(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, Rect2i());
+
+ return _render_target_get_sdf_rect(rt);
+}
+
+RID RasterizerStorageRD::render_target_get_sdf_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ if (rt->sdf_buffer_read.is_null()) {
+ // no texture, create a dummy one for the 2D uniform set
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tformat.type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ zeromem(pv.ptrw(), 16 * 4);
+ Vector<Vector<uint8_t>> vpv;
+
+ rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ return rt->sdf_buffer_read;
+}
+
+void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
+ ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid());
+ if (rt->sdf_buffer_read.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_read);
+ rt->sdf_buffer_read = RID();
+ }
+
+ Size2i size = _render_target_get_sdf_rect(rt).size;
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8_UNORM;
+ tformat.width = size.width;
+ tformat.height = size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tformat.type = RD::TEXTURE_TYPE_2D;
+
+ rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ Vector<RID> write_fb;
+ write_fb.push_back(rt->sdf_buffer_write);
+ rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
+ }
+
+ int scale;
+ switch (rt->sdf_scale) {
+ case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
+ scale = 100;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+ scale = 50;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+ scale = 25;
+ } break;
+ default: {
+ scale = 100;
+ } break;
+ }
+
+ rt->process_size = size * scale / 100;
+ rt->process_size.x = MAX(rt->process_size.x, 1);
+ rt->process_size.y = MAX(rt->process_size.y, 1);
+
+ tformat.format = RD::DATA_FORMAT_R16G16_UINT;
+ tformat.width = rt->process_size.width;
+ tformat.height = rt->process_size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ tformat.format = RD::DATA_FORMAT_R16_UNORM;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(rt->sdf_buffer_write);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(rt->sdf_buffer_read);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.ids.push_back(rt->sdf_buffer_process[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 4;
+ u.ids.push_back(rt->sdf_buffer_process[1]);
+ uniforms.push_back(u);
+ }
+
+ rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+ SWAP(uniforms.write[2].ids.write[0], uniforms.write[3].ids.write[0]);
+ rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+ }
+}
+
+void RasterizerStorageRD::_render_target_clear_sdf(RenderTarget *rt) {
+ if (rt->sdf_buffer_read.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_read);
+ rt->sdf_buffer_read = RID();
+ }
+ if (rt->sdf_buffer_write_fb.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_write);
+ RD::get_singleton()->free(rt->sdf_buffer_process[0]);
+ RD::get_singleton()->free(rt->sdf_buffer_process[1]);
+ rt->sdf_buffer_write = RID();
+ rt->sdf_buffer_write_fb = RID();
+ rt->sdf_buffer_process[0] = RID();
+ rt->sdf_buffer_process[1] = RID();
+ rt->sdf_buffer_process_uniform_sets[0] = RID();
+ rt->sdf_buffer_process_uniform_sets[1] = RID();
+ }
+}
+
+RID RasterizerStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->sdf_buffer_write_fb.is_null()) {
+ _render_target_allocate_sdf(rt);
+ }
+
+ return rt->sdf_buffer_write_fb;
+}
+void RasterizerStorageRD::render_target_sdf_process(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
+
+ RenderTargetSDF::PushConstant push_constant;
+
+ Rect2i r = _render_target_get_sdf_rect(rt);
+
+ push_constant.size[0] = r.size.width;
+ push_constant.size[1] = r.size.height;
+ push_constant.stride = 0;
+ push_constant.shift = 0;
+ push_constant.base_size[0] = r.size.width;
+ push_constant.base_size[1] = r.size.height;
+
+ bool shrink = false;
+
+ switch (rt->sdf_scale) {
+ case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+ push_constant.size[0] >>= 1;
+ push_constant.size[1] >>= 1;
+ push_constant.shift = 1;
+ shrink = true;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+ push_constant.size[0] >>= 2;
+ push_constant.size[1] >>= 2;
+ push_constant.shift = 2;
+ shrink = true;
+ } break;
+ default: {
+ };
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ /* Load */
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
+
+ /* Process */
+
+ int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ bool swap = false;
+
+ //jumpflood
+ while (stride > 0) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+ push_constant.stride = stride;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
+ stride /= 2;
+ swap = !swap;
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ /* Store */
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
@@ -7978,6 +8305,19 @@ RasterizerStorageRD::RasterizerStorageRD() {
mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
}
+ for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
{ //bones
buffer.resize(sizeof(uint32_t) * 4);
{
@@ -8155,6 +8495,24 @@ RasterizerStorageRD::RasterizerStorageRD() {
particles_shader.copy_pipelines[i] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i));
}
}
+
+ {
+ Vector<String> sdf_modes;
+ sdf_modes.push_back("\n#define MODE_LOAD\n");
+ sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
+ sdf_modes.push_back("\n#define MODE_PROCESS\n");
+ sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
+ sdf_modes.push_back("\n#define MODE_STORE\n");
+ sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
+
+ rt_sdf.shader.initialize(sdf_modes);
+
+ rt_sdf.shader_version = rt_sdf.shader.version_create();
+
+ for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
+ rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
+ }
+ }
}
RasterizerStorageRD::~RasterizerStorageRD() {
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
index b7ad931149..d887f122c9 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
@@ -35,6 +35,7 @@
#include "servers/rendering/rasterizer.h"
#include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h"
#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h"
+#include "servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/particles_copy.glsl.gen.h"
@@ -169,6 +170,10 @@ public:
DEFAULT_RD_BUFFER_COLOR,
DEFAULT_RD_BUFFER_TEX_UV,
DEFAULT_RD_BUFFER_TEX_UV2,
+ DEFAULT_RD_BUFFER_CUSTOM0,
+ DEFAULT_RD_BUFFER_CUSTOM1,
+ DEFAULT_RD_BUFFER_CUSTOM2,
+ DEFAULT_RD_BUFFER_CUSTOM3,
DEFAULT_RD_BUFFER_BONES,
DEFAULT_RD_BUFFER_WEIGHTS,
DEFAULT_RD_BUFFER_MAX,
@@ -377,6 +382,8 @@ private:
uint32_t format = 0;
RID vertex_buffer;
+ RID attribute_buffer;
+ RID skin_buffer;
uint32_t vertex_count = 0;
// A different pipeline needs to be allocated
@@ -413,8 +420,7 @@ private:
Vector<AABB> bone_aabbs;
- Vector<RID> blend_shapes;
- RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed
+ RID blend_shape_buffer;
RID material;
@@ -849,6 +855,7 @@ private:
RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
RS::LightDirectionalShadowDepthRangeMode directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
bool directional_blend_splits = false;
+ bool directional_sky_only = false;
uint64_t version = 0;
RasterizerScene::InstanceDependency instance_dependency;
@@ -1003,6 +1010,15 @@ private:
RID framebuffer_uniform_set;
RID backbuffer_uniform_set;
+ RID sdf_buffer_write;
+ RID sdf_buffer_write_fb;
+ RID sdf_buffer_process[2];
+ RID sdf_buffer_read;
+ RID sdf_buffer_process_uniform_sets[2];
+ RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
+ RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
+ Size2i process_size;
+
//texture generated for this owner (nor RD).
RID texture;
bool was_used;
@@ -1012,11 +1028,38 @@ private:
Color clear_color;
};
- RID_Owner<RenderTarget> render_target_owner;
+ mutable RID_Owner<RenderTarget> render_target_owner;
void _clear_render_target(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
+ void _render_target_allocate_sdf(RenderTarget *rt);
+ void _render_target_clear_sdf(RenderTarget *rt);
+ Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
+
+ struct RenderTargetSDF {
+ enum {
+ SHADER_LOAD,
+ SHADER_LOAD_SHRINK,
+ SHADER_PROCESS,
+ SHADER_PROCESS_OPTIMIZED,
+ SHADER_STORE,
+ SHADER_STORE_SHRINK,
+ SHADER_MAX
+ };
+
+ struct PushConstant {
+ int32_t size[2];
+ int32_t stride;
+ int32_t shift;
+ int32_t base_size[2];
+ int32_t pad[2];
+ };
+
+ CanvasSdfShaderRD shader;
+ RID shader_version;
+ RID pipelines[SHADER_MAX];
+ } rt_sdf;
/* GLOBAL SHADER VARIABLES */
@@ -1500,6 +1543,8 @@ public:
void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode);
void light_directional_set_blend_splits(RID p_light, bool p_enable);
bool light_directional_get_blend_splits(RID p_light) const;
+ void light_directional_set_sky_only(RID p_light, bool p_sky_only);
+ bool light_directional_is_sky_only(RID p_light) const;
void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode);
RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
@@ -1930,6 +1975,12 @@ public:
virtual void render_target_disable_clear_request(RID p_render_target);
virtual void render_target_do_clear_request(RID p_render_target);
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale);
+ RID render_target_get_sdf_texture(RID p_render_target);
+ RID render_target_get_sdf_framebuffer(RID p_render_target);
+ void render_target_sdf_process(RID p_render_target);
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const;
+
Size2 render_target_get_size(RID p_render_target);
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
index 08f4eb6aa0..df5513435a 100644
--- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
@@ -1072,6 +1072,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} else if (onode->op == SL::OP_CONSTRUCT) {
code += String(vnode->name);
} else {
+ if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) {
+ *p_actions.usage_flag_pointers[vnode->name] = true;
+ used_flag_pointers.insert(vnode->name);
+ }
+
if (internal_functions.has(vnode->name)) {
code += vnode->name;
is_texture_func = texture_functions.has(vnode->name);
diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub
index 9d531d63ad..4cddf0f685 100644
--- a/servers/rendering/rasterizer_rd/shaders/SCsub
+++ b/servers/rendering/rasterizer_rd/shaders/SCsub
@@ -5,6 +5,7 @@ Import("env")
if "RD_GLSL" in env["BUILDERS"]:
env.RD_GLSL("canvas.glsl")
env.RD_GLSL("canvas_occlusion.glsl")
+ env.RD_GLSL("canvas_sdf.glsl")
env.RD_GLSL("copy.glsl")
env.RD_GLSL("copy_to_fb.glsl")
env.RD_GLSL("cubemap_roughness.glsl")
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
index 2a0f94e733..7808e7ed52 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
@@ -9,7 +9,8 @@ layout(location = 0) in vec2 vertex_attrib;
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
-layout(location = 6) in uvec4 bones_attrib;
+layout(location = 10) in uvec4 bone_attrib;
+layout(location = 11) in vec4 weight_attrib;
#endif
@@ -61,6 +62,7 @@ void main() {
color = vec4(unpackHalf2x16(draw_data.colors[4]), unpackHalf2x16(draw_data.colors[5]));
}
uvec4 bones = uvec4(0, 0, 0, 0);
+ vec4 bone_weights = vec4(0.0);
#elif defined(USE_ATTRIBUTES)
@@ -68,7 +70,8 @@ void main() {
vec4 color = color_attrib;
vec2 uv = uv_attrib;
- uvec4 bones = bones_attrib;
+ uvec4 bones = bone_attrib;
+ vec4 bone_weights = weight_attrib;
#else
vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
@@ -233,6 +236,30 @@ MATERIAL_UNIFORMS
} material;
#endif
+vec2 screen_uv_to_sdf(vec2 p_uv) {
+ return canvas_data.screen_to_sdf * p_uv;
+}
+
+float texture_sdf(vec2 p_sdf) {
+ vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw;
+ float d = texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv).r;
+ d = d * SDF_MAX_LENGTH - 1.0;
+ return d * canvas_data.tex_to_sdf;
+}
+
+vec2 texture_sdf_normal(vec2 p_sdf) {
+ vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw;
+
+ const float EPSILON = 0.001;
+ return normalize(vec2(
+ texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv + vec2(EPSILON, 0.0)).r - texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv - vec2(EPSILON, 0.0)).r,
+ texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv + vec2(0.0, EPSILON)).r - texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv - vec2(0.0, EPSILON)).r));
+}
+
+vec2 sdf_to_screen_uv(vec2 p_sdf) {
+ return p_sdf * canvas_data.sdf_to_screen;
+}
+
/* clang-format off */
FRAGMENT_SHADER_GLOBALS
/* clang-format on */
@@ -500,8 +527,13 @@ FRAGMENT_SHADER_CODE
color = vec4(0.0); //invisible by default due to using light mask
}
+#ifdef MODE_LIGHT_ONLY
+ color = vec4(0.0);
+#else
color *= canvas_data.canvas_modulation;
-#ifdef USE_LIGHTING
+#endif
+
+#if defined(USE_LIGHTING) && !defined(MODE_UNSHADED)
// Directional Lights
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
index 421282cd4d..5c25235c58 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
@@ -2,6 +2,8 @@
#version 450
+VERSION_DEFINES
+
layout(location = 0) in highp vec3 vertex;
layout(push_constant, binding = 0, std430) uniform Constants {
@@ -13,12 +15,16 @@ layout(push_constant, binding = 0, std430) uniform Constants {
}
constants;
+#ifdef MODE_SHADOW
layout(location = 0) out highp float depth;
+#endif
void main() {
highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
- depth = dot(constants.direction, vtx.xy);
+#ifdef MODE_SHADOW
+ depth = dot(constants.direction, vtx.xy);
+#endif
gl_Position = constants.projection * vtx;
}
@@ -26,6 +32,8 @@ void main() {
#version 450
+VERSION_DEFINES
+
layout(push_constant, binding = 0, std430) uniform Constants {
mat4 projection;
mat2x4 modelview;
@@ -35,9 +43,17 @@ layout(push_constant, binding = 0, std430) uniform Constants {
}
constants;
+#ifdef MODE_SHADOW
layout(location = 0) in highp float depth;
layout(location = 0) out highp float distance_buf;
+#else
+layout(location = 0) out highp float sdf_buf;
+#endif
void main() {
+#ifdef MODE_SHADOW
distance_buf = depth / constants.z_far;
+#else
+ sdf_buf = 1.0;
+#endif
}
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl
new file mode 100644
index 0000000000..302ad03b41
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl
@@ -0,0 +1,135 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(r8, set = 0, binding = 1) uniform restrict readonly image2D src_pixels;
+layout(r16, set = 0, binding = 2) uniform restrict writeonly image2D dst_sdf;
+
+layout(rg16i, set = 0, binding = 3) uniform restrict readonly iimage2D src_process;
+layout(rg16i, set = 0, binding = 4) uniform restrict writeonly iimage2D dst_process;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+ ivec2 size;
+ int stride;
+ int shift;
+ ivec2 base_size;
+ uvec2 pad;
+}
+params;
+
+#define SDF_MAX_LENGTH 16384.0
+
+void main() {
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThanEqual(pos, params.size))) { //too large, do nothing
+ return;
+ }
+
+#ifdef MODE_LOAD
+
+ bool solid = imageLoad(src_pixels, pos).r > 0.5;
+ imageStore(dst_process, pos, solid ? ivec4(pos, 0, 0) : ivec4(ivec2(32767), 0, 0));
+#endif
+
+#ifdef MODE_LOAD_SHRINK
+
+ int s = 1 << params.shift;
+ ivec2 base = pos << params.shift;
+ ivec2 center = base + ivec2(params.shift);
+
+ ivec2 rel = ivec2(32767);
+ float d = 1e20;
+ for (int i = 0; i < s; i++) {
+ for (int j = 0; j < s; j++) {
+ ivec2 src_pos = base + ivec2(i, j);
+ if (any(greaterThanEqual(src_pos, params.base_size))) {
+ continue;
+ }
+ bool solid = imageLoad(src_pixels, src_pos).r > 0.5;
+ if (solid) {
+ float dist = length(vec2(src_pos - center));
+ if (dist < d) {
+ d = dist;
+ rel = src_pos;
+ }
+ }
+ }
+ }
+
+ imageStore(dst_process, pos, ivec4(rel, 0, 0));
+#endif
+
+#ifdef MODE_PROCESS
+
+ ivec2 base = pos << params.shift;
+ ivec2 center = base + ivec2(params.shift);
+
+ ivec2 rel = imageLoad(src_process, pos).xy;
+
+ if (center != rel) {
+ //only process if it does not point to itself
+ const int ofs_table_size = 8;
+ const ivec2 ofs_table[ofs_table_size] = ivec2[](
+ ivec2(-1, -1),
+ ivec2(0, -1),
+ ivec2(+1, -1),
+
+ ivec2(-1, 0),
+ ivec2(+1, 0),
+
+ ivec2(-1, +1),
+ ivec2(0, +1),
+ ivec2(+1, +1));
+
+ float dist = length(vec2(rel - center));
+ for (int i = 0; i < ofs_table_size; i++) {
+ ivec2 src_pos = pos + ofs_table[i] * params.stride;
+ if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, params.size))) {
+ continue;
+ }
+ ivec2 src_rel = imageLoad(src_process, src_pos).xy;
+ float src_dist = length(vec2(src_rel - center));
+ if (src_dist < dist) {
+ dist = src_dist;
+ rel = src_rel;
+ }
+ }
+ }
+
+ imageStore(dst_process, pos, ivec4(rel, 0, 0));
+#endif
+
+#ifdef MODE_STORE
+
+ ivec2 rel = imageLoad(src_process, pos).xy;
+ float d = length(vec2(rel - pos));
+ if (d > 0.01) {
+ d += 1.0; //make it signed
+ }
+ d /= SDF_MAX_LENGTH;
+ d = clamp(d, 0.0, 1.0);
+ imageStore(dst_sdf, pos, vec4(d));
+
+#endif
+
+#ifdef MODE_STORE_SHRINK
+
+ ivec2 base = pos << params.shift;
+ ivec2 center = base + ivec2(params.shift);
+
+ ivec2 rel = imageLoad(src_process, pos).xy;
+ float d = length(vec2(rel - center));
+
+ if (d > 0.01) {
+ d += 1.0; //make it signed
+ }
+ d /= SDF_MAX_LENGTH;
+ d = clamp(d, 0.0, 1.0);
+ imageStore(dst_sdf, pos, vec4(d));
+
+#endif
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
index bb39584cbb..cf7678ea31 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
@@ -3,6 +3,8 @@
#define M_PI 3.14159265359
+#define SDF_MAX_LENGTH 16384.0
+
#define FLAGS_INSTANCING_STRIDE_MASK 0xF
#define FLAGS_INSTANCING_ENABLED (1 << 4)
#define FLAGS_INSTANCING_HAS_COLORS (1 << 5)
@@ -24,6 +26,19 @@
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
+#define SAMPLER_NEAREST_CLAMP 0
+#define SAMPLER_LINEAR_CLAMP 1
+#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
+#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
+#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
+#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
+#define SAMPLER_NEAREST_REPEAT 6
+#define SAMPLER_LINEAR_REPEAT 7
+#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
+#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
+#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
+#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
+
// Push Constant
layout(push_constant, binding = 0, std430) uniform DrawData {
@@ -68,8 +83,12 @@ layout(set = 0, binding = 1, std140) uniform CanvasData {
float time;
bool use_pixel_snap;
+ vec4 sdf_to_tex;
+ vec2 screen_to_sdf;
+ vec2 sdf_to_screen;
+
uint directional_light_count;
- uint pad0;
+ float tex_to_sdf;
uint pad1;
uint pad2;
}
@@ -115,10 +134,11 @@ layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture;
layout(set = 0, binding = 5) uniform sampler shadow_sampler;
layout(set = 0, binding = 6) uniform texture2D screen_texture;
+layout(set = 0, binding = 7) uniform texture2D sdf_texture;
-layout(set = 0, binding = 7) uniform sampler material_samplers[12];
+layout(set = 0, binding = 8) uniform sampler material_samplers[12];
-layout(set = 0, binding = 8, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 285698f060..5d87dec79f 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -24,7 +24,29 @@ layout(location = 4) in vec2 uv_attrib;
layout(location = 5) in vec2 uv2_attrib;
#endif
-layout(location = 6) in uvec4 bone_attrib; // always bound, even if unused
+#if defined(CUSTOM0_USED)
+layout(location = 6) in vec4 custom0_attrib;
+#endif
+
+#if defined(CUSTOM1_USED)
+layout(location = 7) in vec4 custom1_attrib;
+#endif
+
+#if defined(CUSTOM2_USED)
+layout(location = 8) in vec4 custom2_attrib;
+#endif
+
+#if defined(CUSTOM3_USED)
+layout(location = 9) in vec4 custom3_attrib;
+#endif
+
+#if defined(BONES_USED)
+layout(location = 10) in uvec4 bone_attrib;
+#endif
+
+#if defined(WEIGHTS_USED)
+layout(location = 11) in vec4 weight_attrib;
+#endif
/* Varyings */
@@ -116,14 +138,15 @@ void main() {
}
vec3 vertex = vertex_attrib;
- vec3 normal = normal_attrib;
+ vec3 normal = normal_attrib * 2.0 - 1.0;
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz;
- float binormalf = tangent_attrib.a;
+ vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
+ float binormalf = tangent_attrib.a * 2.0 - 1.0;
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
+#if 0
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) {
//multimesh, instances are for it
@@ -147,7 +170,7 @@ void main() {
binormal = (vec4(binormal, 0.0) * m).xyz;
#endif
}
-
+#endif
uv_interp = uv_attrib;
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
index 4cc4fd3f64..7de91fd541 100644
--- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
@@ -23,7 +23,11 @@ layout(location = 0) in vec2 uv_interp;
layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(set = 2, binding = 0) uniform sampler2D source_glow;
-layout(set = 3, binding = 0) uniform sampler3D color_correction;
+#ifdef USE_1D_LUT
+layout(set = 3, binding = 0) uniform sampler2D source_color_correction;
+#else
+layout(set = 3, binding = 0) uniform sampler3D source_color_correction;
+#endif
layout(push_constant, binding = 1, std430) uniform Params {
vec3 bcs;
@@ -35,9 +39,9 @@ layout(push_constant, binding = 1, std430) uniform Params {
uint tonemapper;
uvec2 glow_texture_size;
-
float glow_intensity;
uint pad3;
+
uint glow_mode;
float glow_levels[7];
@@ -255,10 +259,18 @@ vec3 apply_bcs(vec3 color, vec3 bcs) {
return color;
}
-
-vec3 apply_color_correction(vec3 color, sampler3D correction_tex) {
- return texture(correction_tex, color).rgb;
+#ifdef USE_1D_LUT
+vec3 apply_color_correction(vec3 color) {
+ color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r;
+ color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g;
+ color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b;
+ return color;
+}
+#else
+vec3 apply_color_correction(vec3 color) {
+ return textureLod(source_color_correction, color, 0.0).rgb;
}
+#endif
vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_REDUCE_MIN = (1.0 / 128.0);
@@ -367,7 +379,7 @@ void main() {
}
if (params.use_color_correction) {
- color = apply_color_correction(color, color_correction);
+ color = apply_color_correction(color);
}
frag_color = vec4(color, 1.0f);
diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp
index 364839c5d7..0e61d53866 100644
--- a/servers/rendering/rendering_server_canvas.cpp
+++ b/servers/rendering/rendering_server_canvas.cpp
@@ -68,7 +68,11 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can
RENDER_TIMESTAMP("Render Canvas Items");
- RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
+ bool sdf_flag;
+ RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, sdf_flag);
+ if (sdf_flag) {
+ sdf_used = true;
+ }
}
void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) {
@@ -301,6 +305,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) {
RENDER_TIMESTAMP(">Render Canvas");
+ sdf_used = false;
snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel;
if (p_canvas->children_order_dirty) {
@@ -347,6 +352,10 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas,
RENDER_TIMESTAMP("<End Render Canvas");
}
+bool RenderingServerCanvas::was_sdf_used() {
+ return sdf_used;
+}
+
RID RenderingServerCanvas::canvas_create() {
Canvas *canvas = memnew(Canvas);
ERR_FAIL_COND_V(!canvas, RID());
@@ -531,59 +540,64 @@ void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_fro
}
}
-void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
ERR_FAIL_COND(p_points.size() < 2);
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
+ Color color = Color(1, 1, 1, 1);
+
+ Vector<int> indices;
+ int pc = p_points.size();
+ int pc2 = pc * 2;
+
+ Vector2 prev_t;
+ int j2;
+
Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
ERR_FAIL_COND(!pline);
- if (true || p_width <= 1) {
-#define TODO make thick lines possible
- Vector<int> indices;
- int pc = p_points.size();
- indices.resize((pc - 1) * 2);
- {
- int *iptr = indices.ptrw();
- for (int i = 0; i < (pc - 1); i++) {
- iptr[i * 2 + 0] = i;
- iptr[i * 2 + 1] = i + 1;
- }
- }
+ PackedColorArray colors;
+ PackedVector2Array points;
- pline->primitive = RS::PRIMITIVE_LINES;
- pline->polygon.create(indices, p_points, p_colors);
- } else {
-#if 0
- //make a trianglestrip for drawing the line...
- Vector2 prev_t;
- pline->triangles.resize(p_points.size() * 2);
- if (p_antialiased) {
- pline->lines.resize(p_points.size() * 2);
- }
+ colors.resize(pc2);
+ points.resize(pc2);
- if (p_colors.size() == 0) {
- pline->triangle_colors.push_back(Color(1, 1, 1, 1));
- if (p_antialiased) {
- pline->line_colors.push_back(Color(1, 1, 1, 1));
- }
- } else if (p_colors.size() == 1) {
- pline->triangle_colors = p_colors;
- pline->line_colors = p_colors;
- } else {
- if (p_colors.size() != p_points.size()) {
- pline->triangle_colors.push_back(p_colors[0]);
- pline->line_colors.push_back(p_colors[0]);
- } else {
- pline->triangle_colors.resize(pline->triangles.size());
- pline->line_colors.resize(pline->lines.size());
- }
- }
+ Vector2 *points_ptr = points.ptrw();
+ Color *colors_ptr = colors.ptrw();
- for (int i = 0; i < p_points.size(); i++) {
+ if (p_antialiased) {
+ Color color2 = Color(1, 1, 1, 0);
+
+ PackedColorArray colors_top;
+ PackedVector2Array points_top;
+
+ colors_top.resize(pc2);
+ points_top.resize(pc2);
+
+ PackedColorArray colors_bottom;
+ PackedVector2Array points_bottom;
+
+ colors_bottom.resize(pc2);
+ points_bottom.resize(pc2);
+
+ Item::CommandPolygon *pline_top = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_top);
+
+ Item::CommandPolygon *pline_bottom = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_bottom);
+
+ //make three trianglestrip's for drawing the antialiased line...
+
+ Vector2 *points_top_ptr = points_top.ptrw();
+ Vector2 *points_bottom_ptr = points_bottom.ptrw();
+
+ Color *colors_top_ptr = colors_top.ptrw();
+ Color *colors_bottom_ptr = colors_bottom.ptrw();
+
+ for (int i = 0, j = 0; i < pc; i++, j += 2) {
Vector2 t;
- if (i == p_points.size() - 1) {
+ if (i == pc - 1) {
t = prev_t;
} else {
t = (p_points[i + 1] - p_points[i]).normalized().tangent();
@@ -592,29 +606,77 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Po
}
}
+ j2 = j + 1;
+
Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
+ 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[j2] = pos + tangent;
+
+ points_bottom_ptr[j] = pos - tangent;
+ points_bottom_ptr[j2] = pos - tangent - tangent;
+
+ if (i < p_colors.size()) {
+ color = p_colors[i];
+ color2 = Color(color.r, color.g, color.b, 0);
+ }
+
+ colors_ptr[j] = color;
+ colors_ptr[j2] = color;
+
+ colors_top_ptr[j] = color2;
+ colors_top_ptr[j2] = color;
+
+ colors_bottom_ptr[j] = color;
+ colors_bottom_ptr[j2] = color2;
- if (p_antialiased) {
- pline->lines.write[i] = p_points[i] + tangent;
- pline->lines.write[p_points.size() * 2 - i - 1] = p_points[i] - tangent;
- if (pline->line_colors.size() > 1) {
- pline->line_colors.write[i] = p_colors[i];
- pline->line_colors.write[p_points.size() * 2 - i - 1] = p_colors[i];
+ prev_t = t;
+ }
+
+ pline_top->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_top->polygon.create(indices, points_top, colors_top);
+
+ pline_bottom->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_bottom->polygon.create(indices, points_bottom, colors_bottom);
+ } else {
+ //make a trianglestrip for drawing the line...
+
+ for (int i = 0, j = 0; i < pc; i++, j += 2) {
+ Vector2 t;
+ if (i == pc - 1) {
+ t = prev_t;
+ } else {
+ t = (p_points[i + 1] - p_points[i]).normalized().tangent();
+ if (i == 0) {
+ prev_t = t;
}
}
- pline->triangles.write[i * 2 + 0] = p_points[i] + tangent;
- pline->triangles.write[i * 2 + 1] = p_points[i] - tangent;
+ j2 = j + 1;
+
+ Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
+ Vector2 pos = p_points[i];
+
+ points_ptr[j] = pos + tangent;
+ points_ptr[j2] = pos - tangent;
- if (pline->triangle_colors.size() > 1) {
- pline->triangle_colors.write[i * 2 + 0] = p_colors[i];
- pline->triangle_colors.write[i * 2 + 1] = p_colors[i];
+ if (i < p_colors.size()) {
+ color = p_colors[i];
}
+ colors_ptr[j] = color;
+ colors_ptr[j2] = color;
+
prev_t = t;
}
-#endif
}
+
+ pline->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline->polygon.create(indices, points, colors);
}
void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
@@ -1266,6 +1328,11 @@ void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RI
}
}
+void RenderingServerCanvas::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) {
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
+ ERR_FAIL_COND(!occluder);
+}
+
void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
ERR_FAIL_COND(!occluder);
@@ -1287,53 +1354,24 @@ RID RenderingServerCanvas::canvas_occluder_polygon_create() {
}
void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
- if (p_shape.size() < 3) {
- canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape);
- return;
- }
-
- Vector<Vector2> lines;
- int lc = p_shape.size() * 2;
-
- lines.resize(lc - (p_closed ? 0 : 2));
- {
- Vector2 *w = lines.ptrw();
- const Vector2 *r = p_shape.ptr();
-
- int max = lc / 2;
- if (!p_closed) {
- max--;
- }
- for (int i = 0; i < max; i++) {
- Vector2 a = r[i];
- Vector2 b = r[(i + 1) % (lc / 2)];
- w[i * 2 + 0] = a;
- w[i * 2 + 1] = b;
- }
- }
-
- canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines);
-}
-
-void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
- ERR_FAIL_COND(p_shape.size() & 1);
- int lc = p_shape.size();
+ uint32_t pc = p_shape.size();
+ ERR_FAIL_COND(pc < 2);
+
occluder_poly->aabb = Rect2();
- {
- const Vector2 *r = p_shape.ptr();
- for (int i = 0; i < lc; i++) {
- if (i == 0) {
- occluder_poly->aabb.position = r[i];
- } else {
- occluder_poly->aabb.expand_to(r[i]);
- }
+ const Vector2 *r = p_shape.ptr();
+ for (uint32_t i = 0; i < pc; i++) {
+ if (i == 0) {
+ occluder_poly->aabb.position = r[i];
+ } else {
+ occluder_poly->aabb.expand_to(r[i]);
}
}
- RSG::canvas_render->occluder_polygon_set_shape_as_lines(occluder_poly->occluder, p_shape);
+ RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed);
+
for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) {
E->get()->aabb_cache = occluder_poly->aabb;
}
diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h
index 36e2f77e95..89f511a8fb 100644
--- a/servers/rendering/rendering_server_canvas.h
+++ b/servers/rendering/rendering_server_canvas.h
@@ -153,6 +153,7 @@ public:
RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner;
bool disable_scale;
+ bool sdf_used = false;
bool snapping_2d_transforms_to_pixel = false;
private:
@@ -165,6 +166,8 @@ private:
public:
void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel);
+ bool was_sdf_used();
+
RID canvas_create();
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
void canvas_set_modulate(RID p_canvas, const Color &p_color);
@@ -189,7 +192,7 @@ public:
void canvas_item_set_update_when_visible(RID p_item, bool p_update);
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0);
- void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
+ void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
@@ -247,12 +250,12 @@ public:
void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas);
void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled);
void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon);
+ void canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable);
void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
RID canvas_occluder_polygon_create();
void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed);
- void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape);
void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode);
diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h
index 60b25f1b94..76ceccb3c5 100644
--- a/servers/rendering/rendering_server_raster.h
+++ b/servers/rendering/rendering_server_raster.h
@@ -336,6 +336,7 @@ public:
BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
BIND2(light_directional_set_blend_splits, RID, bool)
+ BIND2(light_directional_set_sky_only, RID, bool)
BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */
@@ -536,6 +537,7 @@ public:
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
BIND2(viewport_set_shadow_atlas_size, RID, int)
+ BIND3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
@@ -592,7 +594,7 @@ public:
BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
- BIND6(environment_set_adjustment, RID, bool, float, float, float, RID)
+ BIND7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
BIND9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter)
@@ -716,7 +718,7 @@ public:
BIND2(canvas_item_set_draw_behind_parent, RID, bool)
BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
- BIND4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float)
+ BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
BIND4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
@@ -776,12 +778,12 @@ public:
BIND2(canvas_light_occluder_attach_to_canvas, RID, RID)
BIND2(canvas_light_occluder_set_enabled, RID, bool)
BIND2(canvas_light_occluder_set_polygon, RID, RID)
+ BIND2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &)
BIND2(canvas_light_occluder_set_light_mask, RID, int)
BIND0R(RID, canvas_occluder_polygon_create)
BIND3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
- BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &)
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp
index ae6786090a..b933a550e2 100644
--- a/servers/rendering/rendering_server_scene.cpp
+++ b/servers/rendering/rendering_server_scene.cpp
@@ -2169,7 +2169,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
//check shadow..
if (light) {
- if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base)) {
+ if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) {
lights_with_shadow[directional_shadow_count++] = E->get();
}
//add to list
@@ -2595,7 +2595,8 @@ void RenderingServerScene::render_probes() {
cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
- cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
+ cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
+ cache->sky_only != RSG::storage->light_directional_is_sky_only(instance->base)) {
cache_dirty = true;
}
}
@@ -2664,6 +2665,7 @@ void RenderingServerScene::render_probes() {
cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ cache->sky_only = RSG::storage->light_directional_is_sky_only(instance->base);
idx++;
}
diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h
index 646b2a666f..eb438be273 100644
--- a/servers/rendering/rendering_server_scene.h
+++ b/servers/rendering/rendering_server_scene.h
@@ -350,6 +350,7 @@ public:
float spot_angle;
float spot_attenuation;
bool has_shadow;
+ bool sky_only;
};
Vector<LightCache> light_cache;
diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp
index c6682b1fcd..c048aa381f 100644
--- a/servers/rendering/rendering_server_viewport.cpp
+++ b/servers/rendering/rendering_server_viewport.cpp
@@ -146,6 +146,36 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
RasterizerCanvas::Light *directional_lights = nullptr;
RasterizerCanvas::Light *directional_lights_with_shadow = nullptr;
+ if (p_viewport->sdf_active) {
+ //process SDF
+
+ Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target);
+
+ RasterizerCanvas::LightOccluderInstance *occluders = nullptr;
+
+ //make list of occluders
+ for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
+ RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+
+ for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
+ if (!F->get()->enabled) {
+ continue;
+ }
+ F->get()->xform_cache = xf * F->get()->xform;
+
+ if (sdf_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) {
+ F->get()->next = occluders;
+ occluders = F->get();
+ }
+ }
+ }
+
+ RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
+
+ p_viewport->sdf_active = false; // if used, gets set active again
+ }
+
Rect2 shadow_rect;
int light_count = 0;
@@ -195,7 +225,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
}
//guess this is not needed, but keeping because it may be
- //RSG::canvas_render->light_internal_update(cl->light_internal, cl);
}
}
@@ -256,7 +285,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
light = light->shadows_next_ptr;
}
- //RSG::canvas_render->reset_canvas();
RENDER_TIMESTAMP("<End rendering 2D Shadows");
}
@@ -340,7 +368,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
light = light->shadows_next_ptr;
}
- //RSG::canvas_render->reset_canvas();
RENDER_TIMESTAMP("<Render Directional 2D Shadows");
}
@@ -380,6 +407,9 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
}
RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel);
+ if (RSG::canvas->was_sdf_used()) {
+ p_viewport->sdf_active = true;
+ }
i++;
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
@@ -400,8 +430,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
_draw_3d(p_viewport, p_eye);
}
}
-
- //RSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow);
}
if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) {
@@ -925,6 +953,13 @@ void RenderingServerViewport::viewport_set_default_canvas_item_texture_repeat(RI
viewport->texture_repeat = p_repeat;
}
+void RenderingServerViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
+}
+
bool RenderingServerViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.getornull(p_rid);
diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h
index 081f63690b..ba55b2e66e 100644
--- a/servers/rendering/rendering_server_viewport.h
+++ b/servers/rendering/rendering_server_viewport.h
@@ -82,6 +82,8 @@ public:
RID shadow_atlas;
int shadow_atlas_size;
+ bool sdf_active;
+
uint64_t last_pass = 0;
int render_info[RS::VIEWPORT_RENDER_INFO_MAX];
@@ -146,6 +148,7 @@ public:
render_info[i] = 0;
}
use_xr = false;
+ sdf_active = false;
time_cpu_begin = 0;
time_cpu_end = 0;
@@ -232,6 +235,8 @@ public:
void viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter);
void viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat);
+ void viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_over_size, RS::ViewportSDFScale p_scale);
+
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
void set_default_clear_color(const Color &p_color);
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index d27b851d1d..2c230aaee4 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -244,6 +244,7 @@ public:
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
+ FUNC2(light_directional_set_sky_only, RID, bool)
FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */
@@ -440,6 +441,8 @@ public:
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
FUNC2(viewport_set_shadow_atlas_size, RID, int)
+ FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
+
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
@@ -504,7 +507,7 @@ public:
FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
- FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID)
+ FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
@@ -616,7 +619,7 @@ public:
FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
- FUNC4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float)
+ FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
@@ -676,12 +679,12 @@ public:
FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
FUNC2(canvas_light_occluder_set_enabled, RID, bool)
FUNC2(canvas_light_occluder_set_polygon, RID, RID)
+ FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
FUNC2(canvas_light_occluder_set_light_mask, RID, int)
FUNCRID(canvas_occluder_polygon)
FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
- FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &)
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 4d21807735..0c9b2ddf2f 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -67,6 +67,12 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_INDICES"] = ShaderLanguage::TYPE_UVEC4;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_WEIGHTS"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM0"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM1"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM2"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM3"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].can_discard = false;
//builtins
@@ -252,6 +258,27 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true;
+ {
+ ShaderLanguage::StageFunctionInfo func;
+ func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("sdf_pos", ShaderLanguage::TYPE_VEC2));
+ func.return_type = ShaderLanguage::TYPE_FLOAT; //whether it could emit
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf"] = func;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["texture_sdf"] = func;
+ func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["sdf_to_screen_uv"] = func;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["sdf_to_screen_uv"] = func;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf_normal"] = func;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["texture_sdf_normal"] = func;
+ }
+
+ {
+ ShaderLanguage::StageFunctionInfo func;
+ func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("uv", ShaderLanguage::TYPE_VEC2));
+ func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["screen_uv_to_sdf"] = func;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["screen_uv_to_sdf"] = func;
+ }
+
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);