summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp32
-rw-r--r--servers/rendering/renderer_canvas_cull.h1
-rw-r--r--servers/rendering/renderer_canvas_render.h3
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h4
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp2
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp6
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp16
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp14
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp12
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp105
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp31
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl64
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp41
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp12
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h4
-rw-r--r--servers/rendering/renderer_scene_cull.cpp8
-rw-r--r--servers/rendering/renderer_viewport.cpp52
-rw-r--r--servers/rendering/renderer_viewport.h15
-rw-r--r--servers/rendering/rendering_device.cpp1
-rw-r--r--servers/rendering/rendering_device.h1
-rw-r--r--servers/rendering/rendering_device_binds.h6
-rw-r--r--servers/rendering/rendering_server_default.h1
-rw-r--r--servers/rendering/shader_compiler.cpp43
-rw-r--r--servers/rendering/shader_compiler.h1
-rw-r--r--servers/rendering/shader_language.cpp50
-rw-r--r--servers/rendering/shader_language.h6
-rw-r--r--servers/rendering/shader_preprocessor.cpp325
-rw-r--r--servers/rendering/shader_preprocessor.h36
38 files changed, 749 insertions, 212 deletions
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 86e5e4802b..aa9772a483 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -1183,6 +1183,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
rect->px_range = p_px_range;
}
+void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
+ ERR_FAIL_COND(!rect);
+ rect->modulate = p_modulate;
+ rect->rect = p_rect;
+
+ rect->texture = p_texture;
+
+ rect->source = p_src_rect;
+ rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD;
+
+ if (p_rect.size.x < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->rect.size.x = -rect->rect.size.x;
+ }
+ if (p_src_rect.size.x < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->source.size.x = -rect->source.size.x;
+ }
+ if (p_rect.size.y < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->rect.size.y = -rect->rect.size.y;
+ }
+ if (p_src_rect.size.y < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->source.size.y = -rect->source.size.y;
+ }
+}
+
void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index e8c54310c9..0d6a4006f8 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -225,6 +225,7 @@ public:
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0);
+ void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID());
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 11a7d34291..6791ed9626 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -46,6 +46,7 @@ public:
CANVAS_RECT_CLIP_UV = 32,
CANVAS_RECT_IS_GROUP = 64,
CANVAS_RECT_MSDF = 128,
+ CANVAS_RECT_LCD = 256,
};
struct Light {
@@ -193,7 +194,7 @@ public:
Rect2 rect;
Color modulate;
Rect2 source;
- uint8_t flags;
+ uint16_t flags;
float outline;
float px_range;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 17ca1986c6..ef17ceb98c 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -269,7 +269,7 @@ public:
//spot
radius *= shared->cone_overfit; // overfit icosphere
- real_t len = Math::tan(Math::deg2rad(p_spot_aperture)) * radius;
+ real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius;
//approximate, probably better to use a cone support function
float max_d = -1e20;
float min_d = 1e20;
@@ -293,7 +293,7 @@ public:
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
//inside, check angle
- float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
+ float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit
} else {
e.touches_near = false;
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 0f896a8aa7..874409b885 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -1604,7 +1604,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
ScreenSpaceReflectionFilterPushConstant push_constant;
push_constant.view_index = v;
push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
+ push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]);
push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index eaef5ba39c..66e984174c 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -1924,7 +1924,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
@@ -2362,7 +2362,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
@@ -2800,7 +2800,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
l.color[1] = color.g;
l.color[2] = color.b;
- l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 6433a39863..1d6b158d65 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -114,12 +114,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- // print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
@@ -1228,7 +1232,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh
// 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));
+ angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
} else {
angular_diameter = 0.0;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 556db086b2..0911ee595f 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -150,6 +150,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
#if 0
print_line("**compiling shader:");
@@ -158,11 +159,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element *el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -396,7 +396,11 @@ void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<Prope
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index fa9ebde1b2..d6b526fa4a 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -174,6 +174,7 @@ public:
bool uses_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
+ bool uses_screen_texture_mipmaps = false;
Cull cull_mode = CULL_DISABLED;
uint64_t last_pass = 0;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 01b54607bc..85c9e1db2a 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -158,11 +158,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element * el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -353,7 +352,10 @@ void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<Property
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
continue;
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index c1b08ee4c9..67c929b724 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
//bind pipeline
- {
+ if (rect->flags & CANVAS_RECT_LCD) {
+ RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
+ RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate);
+ } else {
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
}
@@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.msdf[1] = rect->outline; // Outline size.
push_constant.msdf[2] = 0.f; // Reserved.
push_constant.msdf[3] = 0.f; // Reserved.
+ } else if (rect->flags & CANVAS_RECT_LCD) {
+ push_constant.flags |= FLAGS_USE_LCD;
}
push_constant.modulation[0] = rect->modulate.r * base_color.r;
@@ -1361,6 +1367,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Item *ci = p_item_list;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ bool backbuffer_gen_mipmaps = false;
Item *canvas_group_owner = nullptr;
@@ -1389,6 +1396,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -1474,9 +1482,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false;
+ backbuffer_gen_mipmaps = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
}
@@ -1591,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
real_t farp = p_far;
real_t aspect = 1.0;
- real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5));
+ real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
real_t ymin = -ymax;
real_t xmin = ymin * aspect;
real_t xmax = ymax * aspect;
@@ -1980,6 +1989,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
+ uses_screen_texture_mipmaps = false;
uses_sdf = false;
uses_time = false;
@@ -1990,7 +2000,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
- uses_screen_texture = false;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
@@ -2015,6 +2024,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
}
@@ -2025,12 +2036,16 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
@@ -2104,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::PipelineColorBlendState blend_state;
blend_state.attachments.push_back(attachment);
+ RD::PipelineColorBlendState::Attachment attachment_lcd;
+ attachment_lcd.enable_blend = true;
+ attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ RD::PipelineColorBlendState blend_state_lcd;
+ blend_state_lcd.attachments.push_back(attachment_lcd);
+
//update pipelines
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
@@ -2119,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- { //non lit
+ {
+ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
@@ -2132,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS },
- { //lit
+ SHADER_VARIANT_ATTRIBUTES_POINTS,
+ SHADER_VARIANT_QUAD,
+ },
+ {
+ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
@@ -2143,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
+ SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
+ SHADER_VARIANT_QUAD_LIGHT,
+ },
};
RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]);
- pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
+ pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
+ } else {
+ pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
}
}
@@ -2175,7 +2213,11 @@ void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<Prop
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
if (E.value.texture_order >= 0) {
@@ -2350,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
blend_state.attachments.push_back(blend_attachment);
+ RD::PipelineColorBlendState::Attachment attachment_lcd;
+ attachment_lcd.enable_blend = true;
+ attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ RD::PipelineColorBlendState blend_state_lcd;
+ blend_state_lcd.attachments.push_back(attachment_lcd);
+
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
@@ -2363,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- { //non lit
+ {
+ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
@@ -2376,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS },
- { //lit
+ SHADER_VARIANT_ATTRIBUTES_POINTS,
+ SHADER_VARIANT_QUAD,
+ },
+ {
+ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
@@ -2387,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
+ SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
+ SHADER_VARIANT_QUAD_LIGHT,
+ },
};
RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
+ } else {
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
}
}
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 5eb4cee4c6..54077a5b9a 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
FLAGS_USE_MSDF = (1 << 28),
+ FLAGS_USE_LCD = (1 << 29),
};
enum {
@@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
PIPELINE_VARIANT_ATTRIBUTE_LINES,
PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
PIPELINE_VARIANT_ATTRIBUTE_POINTS,
+ PIPELINE_VARIANT_QUAD_LCD_BLEND,
PIPELINE_VARIANT_MAX
};
enum PipelineLightMode {
@@ -174,6 +176,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
+ bool uses_screen_texture_mipmaps = false;
bool uses_sdf = false;
bool uses_time = false;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 6c219933b0..7adc36c57c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2459,6 +2459,19 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
p_internal_width = p_width;
}
+ if (p_use_taa) {
+ // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
+ // This restores sharpness in still images to be roughly at the same level as without TAA,
+ // but moving scenes will still be blurrier.
+ p_texture_mipmap_bias -= 0.5;
+ }
+
+ if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
+ // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
+ // If both TAA and FXAA are enabled, combine their negative LOD biases together.
+ p_texture_mipmap_bias -= 0.25;
+ }
+
material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
update_uniform_sets();
@@ -2862,20 +2875,22 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
- light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
+ light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
}
- light_data.shadow_opacity = p_using_shadows && light_storage->light_has_shadow(base) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0;
+ light_data.shadow_opacity = (p_using_shadows && light_storage->light_has_shadow(base))
+ ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY)
+ : 0.0;
float angular_diameter = light_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));
+ angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) {
// Only enable PCSS-like soft shadows if blurring is enabled.
// Otherwise, performance would decrease with no visual difference.
@@ -3090,7 +3105,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
- light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
+ light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle));
light_data.mask = light_storage->light_get_cull_mask(base);
@@ -3122,7 +3137,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.projector_rect[3] = 0;
}
- const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
+ const bool needs_shadow =
+ shadow_atlas &&
+ shadow_atlas->shadow_owners.has(li->self) &&
+ p_using_shadows &&
+ light_storage->light_has_shadow(base);
bool in_shadow_range = true;
if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
@@ -3187,7 +3206,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// Only enable PCSS-like soft shadows if blurring is enabled.
// Otherwise, performance would decrease with no visual difference.
Projection cm = li->shadow_transform[0].camera;
- float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
+ float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle));
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
} else {
light_data.soft_shadow_size = 0.0;
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index f8e9020f9f..459d798a80 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -509,7 +509,13 @@ void main() {
float a = clamp(d * px_size + 0.5, 0.0, 1.0);
color.a = a * color.a;
}
-
+ } else if (bool(draw_data.flags & FLAGS_USE_LCD)) {
+ vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv);
+ if (lcd_sample.a == 1.0) {
+ color.rgb = lcd_sample.rgb * color.a;
+ } else {
+ color = vec4(0.0, 0.0, 0.0, 0.0);
+ }
} else {
#else
{
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 2ea6965c09..1b627a3e81 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -25,6 +25,7 @@
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
#define FLAGS_USE_MSDF (1 << 28)
+#define FLAGS_USE_LCD (1 << 29)
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0438671dd2..0b43af7738 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
@@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a3b3938ee9..a06cacfabe 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index e9515c7670..6b4e4a5a16 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) out vec3 vertex_interp;
@@ -231,12 +238,13 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 6548793bee..0960533917 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) highp out vec3 vertex_interp;
@@ -229,12 +236,13 @@ void main() {
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec3 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index a893a66c94..75bea9300b 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -54,14 +54,54 @@ layout(push_constant, std430) uniform Params {
}
params;
-vec4 decode_abgr_2_10_10_10(uint base) {
- uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3);
- return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0;
+vec2 uint_to_vec2(uint base) {
+ uvec2 decode = (uvec2(base) >> uvec2(0, 16)) & uvec2(0xFFFF, 0xFFFF);
+ return vec2(decode) / vec2(65535.0, 65535.0) * 2.0 - 1.0;
}
-uint encode_abgr_2_10_10_10(vec4 base) {
- uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30);
- return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w;
+vec3 oct_to_vec3(vec2 oct) {
+ vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
+vec3 decode_uint_oct_to_norm(uint base) {
+ return oct_to_vec3(uint_to_vec2(base));
+}
+
+vec4 decode_uint_oct_to_tang(uint base) {
+ vec2 oct_sign_encoded = uint_to_vec2(base);
+ // Binormal sign encoded in y component
+ vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0);
+ return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y));
+}
+
+vec2 signNotZero(vec2 v) {
+ return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0)));
+}
+
+uint vec2_to_uint(vec2 base) {
+ uvec2 enc = uvec2(clamp(ivec2(base * vec2(65535, 65535)), ivec2(0), ivec2(0xFFFF, 0xFFFF))) << uvec2(0, 16);
+ return enc.x | enc.y;
+}
+
+vec2 vec3_to_oct(vec3 e) {
+ e /= abs(e.x) + abs(e.y) + abs(e.z);
+ vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy);
+ return oct * 0.5f + 0.5f;
+}
+
+uint encode_norm_to_uint_oct(vec3 base) {
+ return vec2_to_uint(vec3_to_oct(base));
+}
+
+uint encode_tang_to_uint_oct(vec4 base) {
+ vec2 oct = vec3_to_oct(base.xyz);
+ // Encode binormal sign in y component
+ oct.y = oct.y * 0.5f + 0.5f;
+ oct.y = base.w >= 0.0f ? oct.y : 1 - oct.y;
+ return vec2_to_uint(oct);
}
void main() {
@@ -131,12 +171,12 @@ void main() {
src_offset += 3;
if (params.has_normal) {
- normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb;
+ normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]);
src_offset++;
}
if (params.has_tangent) {
- tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]);
+ tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]);
}
if (params.has_blend_shape) {
@@ -155,12 +195,12 @@ void main() {
base_offset += 3;
if (params.has_normal) {
- blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w;
base_offset++;
}
if (params.has_tangent) {
- blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w;
}
blend_total += w;
@@ -234,12 +274,12 @@ void main() {
dst_offset += 3;
if (params.has_normal) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0));
+ dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal);
dst_offset++;
}
if (params.has_tangent) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent);
+ dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent);
}
#endif
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 882afdfa54..7b58cc08dd 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -352,7 +352,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
switch (light->type) {
case RS::LIGHT_SPOT: {
float len = light->param[RS::LIGHT_PARAM_RANGE];
- float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+ float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
};
case RS::LIGHT_OMNI: {
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 41dd1ccc40..fa8406e7a1 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -941,6 +941,12 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa
continue; //instance uniforms don't appear in the buffer
}
+ if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
@@ -1052,6 +1058,12 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
Vector<RID> textures;
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
@@ -1307,7 +1319,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
}
- if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) {
// This material does not require an uniform set, so don't create it.
return false;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index dc3f35f942..49d7198ec2 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -327,8 +327,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
- s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
- s->vertex_buffer_size = p_surface.vertex_data.size();
+ if (p_surface.vertex_data.size()) {
+ s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
+ s->vertex_buffer_size = p_surface.vertex_data.size();
+ }
if (p_surface.attribute_data.size()) {
s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
@@ -345,7 +347,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
+ bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
s->index_count = p_surface.index_count;
@@ -364,6 +366,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
}
+ ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
@@ -377,7 +381,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s->vertex_buffer);
+ if (s->vertex_buffer.is_valid()) {
+ u.append_id(s->vertex_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
uniforms.push_back(u);
}
{
@@ -416,7 +424,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
}
for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
+ const AABB &bone = p_surface.bone_aabbs[i];
+ if (!bone.has_no_volume()) {
+ mesh->bone_aabbs.write[i].merge_with(bone);
+ }
}
mesh->aabb.merge_with(p_surface.aabb);
}
@@ -467,6 +478,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null());
uint64_t data_size = p_data.size();
const uint8_t *r = p_data.ptr();
@@ -524,7 +536,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.vertex_buffer.is_valid()) {
+ 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);
}
@@ -702,7 +716,9 @@ void MeshStorage::mesh_clear(RID p_mesh) {
ERR_FAIL_COND(!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.vertex_buffer.is_valid()) {
+ 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);
}
@@ -848,7 +864,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
}
MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
+ if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
//surface warrants transform
s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
@@ -1057,10 +1073,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_NORMAL: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
@@ -1069,9 +1084,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_TANGENT: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index ba644e7eb9..022b027644 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -134,7 +134,7 @@ void process() {
material_storage->material_initialize(particles_shader.default_material);
material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
- ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
+ ParticleProcessMaterialData *md = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -1072,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
- ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES));
+ ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES));
if (!m) {
- m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
+ m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
}
ERR_FAIL_COND(!m);
@@ -1696,16 +1696,16 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() {
return shader_data;
}
-bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
}
-ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() {
+ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() {
free_parameters_uniform_set(uniform_set);
}
MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
- ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
+ ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 97d100e2da..299fdc6ec8 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -354,14 +354,14 @@ private:
return ParticlesStorage::get_singleton()->_create_particles_shader_func();
}
- struct ParticlesMaterialData : public MaterialStorage::MaterialData {
+ struct ParticleProcessMaterialData : public MaterialStorage::MaterialData {
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~ParticlesMaterialData();
+ virtual ~ParticleProcessMaterialData();
};
MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 0b20bb372a..80c4ecea2d 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -506,7 +506,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
if (instance->mesh_instance.is_valid()) {
- RSG::mesh_storage->mesh_free(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(instance->mesh_instance);
instance->mesh_instance = RID();
// no need to set instance data flag here, as it was freed above
}
@@ -2146,7 +2146,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
if (soft_shadow_angle > 0.0) {
float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
- soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range;
+ soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range;
x_max += soft_shadow_expand;
y_max += soft_shadow_expand;
@@ -3125,8 +3125,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- float w = radius * Math::sin(Math::deg2rad(angle));
- float d = radius * Math::cos(Math::deg2rad(angle));
+ float w = radius * Math::sin(Math::deg_to_rad(angle));
+ float d = radius * Math::cos(Math::deg_to_rad(angle));
Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 73b03966c5..bfb81925bc 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -72,6 +72,41 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
+Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() {
+ // We need to sort the viewports in a "topological order",
+ // children first and parents last, we use the Kahn's algorithm to achieve that.
+
+ Vector<Viewport *> result;
+ List<Viewport *> nodes;
+
+ for (Viewport *viewport : active_viewports) {
+ if (viewport->parent.is_valid()) {
+ continue;
+ }
+
+ nodes.push_back(viewport);
+ }
+
+ while (!nodes.is_empty()) {
+ Viewport *node = nodes[0];
+ nodes.pop_front();
+
+ result.insert(0, node);
+
+ for (Viewport *child : active_viewports) {
+ if (child->parent != node->self) {
+ continue;
+ }
+
+ if (!nodes.find(child)) {
+ nodes.push_back(child);
+ }
+ }
+ }
+
+ return result;
+}
+
void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->render_buffers.is_valid()) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
@@ -548,8 +583,10 @@ void RendererViewport::draw_viewports() {
set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
}
- //sort viewports
- active_viewports.sort_custom<ViewportSort>();
+ if (sorted_active_viewports_dirty) {
+ sorted_active_viewports = _sort_active_viewports();
+ sorted_active_viewports_dirty = false;
+ }
HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
@@ -558,9 +595,9 @@ void RendererViewport::draw_viewports() {
//determine what is visible
draw_viewports_pass++;
- for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
+ for (int i = sorted_active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
- Viewport *vp = active_viewports[i];
+ Viewport *vp = sorted_active_viewports[i];
if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) {
continue;
@@ -621,8 +658,8 @@ void RendererViewport::draw_viewports() {
int objects_drawn = 0;
int draw_calls_used = 0;
- for (int i = 0; i < active_viewports.size(); i++) {
- Viewport *vp = active_viewports[i];
+ for (int i = 0; i < sorted_active_viewports.size(); i++) {
+ Viewport *vp = sorted_active_viewports[i];
if (vp->last_pass != draw_viewports_pass) {
continue; //should not draw
@@ -814,6 +851,8 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
} else {
active_viewports.erase(viewport);
}
+
+ sorted_active_viewports_dirty = true;
}
void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
@@ -1243,6 +1282,7 @@ bool RendererViewport::free(RID p_rid) {
viewport_set_scenario(p_rid, RID());
active_viewports.erase(viewport);
+ sorted_active_viewports_dirty = true;
if (viewport->use_occlusion_culling) {
RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid);
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 5e37c96336..ab4893a908 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -185,25 +185,16 @@ public:
mutable RID_Owner<Viewport, true> viewport_owner;
- struct ViewportSort {
- _FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
- bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2();
- bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2();
-
- if (left_to_screen == right_to_screen) {
- return p_right->parent == p_left->self;
- }
- return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1);
- }
- };
-
Vector<Viewport *> active_viewports;
+ Vector<Viewport *> sorted_active_viewports;
+ bool sorted_active_viewports_dirty = false;
int total_objects_drawn = 0;
int total_vertices_drawn = 0;
int total_draw_calls_used = 0;
private:
+ Vector<Viewport *> _sort_active_viewports();
void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
void _draw_viewport(Viewport *p_viewport);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index c07a783302..2fefdbff52 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -429,6 +429,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants);
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index a864cfa74c..6dadcab383 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1129,6 +1129,7 @@ public:
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
+ virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0;
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0;
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0;
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index 8bdd3deea1..a56b7eb241 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -443,8 +443,8 @@ public:
void add_id(const RID &p_id) { base.append_id(p_id); }
void clear_ids() { base.clear_ids(); }
- Array get_ids() const {
- Array ids;
+ TypedArray<RID> get_ids() const {
+ TypedArray<RID> ids;
for (uint32_t i = 0; i < base.get_id_count(); i++) {
ids.push_back(base.get_id(i));
}
@@ -452,7 +452,7 @@ public:
}
protected:
- void _set_ids(const Array &p_ids) {
+ void _set_ids(const TypedArray<RID> &p_ids) {
base.clear_ids();
for (int i = 0; i < p_ids.size(); i++) {
RID id = p_ids[i];
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index cc79d09503..9b174d5879 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -831,6 +831,7 @@ public:
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
+ FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index c2cf08812c..f14350305a 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -498,6 +498,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
if (SL::is_sampler_type(E.value.type)) {
+ if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
max_texture_uniforms++;
} else {
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
@@ -537,6 +542,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
p_actions.uniforms->insert(uniform_name, uniform);
continue; // Instances are indexed directly, don't need index uniforms.
}
+
+ if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
+
if (SL::is_sampler_type(uniform.type)) {
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
if (!RS::get_singleton()->is_low_end()) {
@@ -892,12 +904,39 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
+ if (vnode->name == "SCREEN_TEXTURE") {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
} else {
if (shader->uniforms.has(vnode->name)) {
//its a uniform!
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
if (u.texture_order >= 0) {
- code = _mkid(vnode->name); //texture, use as is
+ StringName name = vnode->name;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ name = "SCREEN_TEXTURE";
+ if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ name = "NORMAL_ROUGHNESS_TEXTURE";
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ name = "DEPTH_TEXTURE";
+ } else {
+ name = _mkid(vnode->name); //texture, use as is
+ }
+
+ if (p_default_actions.renames.has(name)) {
+ code = p_default_actions.renames[name];
+ } else {
+ code = name;
+ }
+
+ if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) {
+ *p_actions.usage_flag_pointers[name] = true;
+ used_flag_pointers.insert(name);
+ }
+
} else {
//a scalar or vector
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
@@ -1155,6 +1194,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
if (correct_texture_uniform) {
+ //TODO Needs to detect screen_texture hint as well
is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@@ -1404,6 +1444,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
r_gen_code.uses_fragment_time = false;
r_gen_code.uses_vertex_time = false;
r_gen_code.uses_global_textures = false;
+ r_gen_code.uses_screen_texture_mipmaps = false;
used_name_defines.clear();
used_rmode_defines.clear();
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index 06f42e9f0f..1ad43daf5f 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -80,6 +80,7 @@ public:
bool uses_global_textures;
bool uses_fragment_time;
bool uses_vertex_time;
+ bool uses_screen_texture_mipmaps;
};
struct DefaultIdentifierActions {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 81e4d5e217..2bbc5e4dfb 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -200,6 +200,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_ANISOTROPY_TEXTURE",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
+ "HINT_SCREEN_TEXTURE",
+ "HINT_NORMAL_ROUGHNESS_TEXTURE",
+ "HINT_DEPTH_TEXTURE",
"FILTER_NEAREST",
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
@@ -363,6 +366,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} },
+
{ TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} },
{ TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} },
@@ -1096,6 +1103,15 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
case ShaderNode::Uniform::HINT_ANISOTROPY: {
result = "hint_anisotropy";
} break;
+ case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: {
+ result = "hint_screen_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ result = "hint_normal_roughness_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: {
+ result = "hint_depth_texture";
+ } break;
default:
break;
}
@@ -5361,6 +5377,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
_set_tkpos(prev_pos);
+ ShaderNode::Varying &var = shader->varyings[identifier];
String error;
if (is_token_operator_assign(next_token.type)) {
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
@@ -5368,8 +5385,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
} else {
- ShaderNode::Varying &var = shader->varyings[identifier];
-
switch (var.stage) {
case ShaderNode::Varying::STAGE_VERTEX:
if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
@@ -5385,6 +5400,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
}
+
+ if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) {
+ _set_tkpos(var.tkpos);
+ _set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier."));
+ return nullptr;
+ }
}
if (ident_type == IDENTIFIER_FUNCTION) {
@@ -8283,8 +8304,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
- if (!is_uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
- _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed."));
+ if (!is_uniform && type > TYPE_MAT4) {
+ _set_error(RTR("Invalid data type for varying."));
return ERR_PARSE_ERROR;
}
@@ -8605,6 +8626,15 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
} break;
+ case TK_HINT_SCREEN_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE;
+ } break;
+ case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE;
+ } break;
+ case TK_HINT_DEPTH_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE;
+ } break;
case TK_FILTER_NEAREST: {
new_filter = FILTER_NEAREST;
} break;
@@ -8629,6 +8659,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_REPEAT_ENABLE: {
new_repeat = REPEAT_ENABLE;
} break;
+
default:
break;
}
@@ -8653,9 +8684,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (new_filter != FILTER_DEFAULT) {
if (uniform.filter != FILTER_DEFAULT) {
if (uniform.filter == new_filter) {
- _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter)));
+ _set_error(vformat(RTR("Duplicated filter mode: '%s'."), get_texture_filter_name(new_filter)));
} else {
- _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
+ _set_error(vformat(RTR("Redefinition of filter mode: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
}
return ERR_PARSE_ERROR;
} else {
@@ -8666,9 +8697,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (new_repeat != REPEAT_DEFAULT) {
if (uniform.repeat != REPEAT_DEFAULT) {
if (uniform.repeat == new_repeat) {
- _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat)));
+ _set_error(vformat(RTR("Duplicated repeat mode: '%s'."), get_texture_repeat_name(new_repeat)));
} else {
- _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
+ _set_error(vformat(RTR("Redefinition of repeat mode: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
}
return ERR_PARSE_ERROR;
} else {
@@ -10309,6 +10340,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_roughness_gray");
options.push_back("hint_roughness_normal");
options.push_back("hint_roughness_r");
+ options.push_back("hint_screen_texture");
+ options.push_back("hint_normal_roughness_texture");
+ options.push_back("hint_depth_texture");
options.push_back("source_color");
options.push_back("repeat_enable");
options.push_back("repeat_disable");
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index bfec6e1df6..75b713d167 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -176,6 +176,9 @@ public:
TK_HINT_SOURCE_COLOR,
TK_HINT_RANGE,
TK_HINT_INSTANCE_INDEX,
+ TK_HINT_SCREEN_TEXTURE,
+ TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
+ TK_HINT_DEPTH_TEXTURE,
TK_FILTER_NEAREST,
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
@@ -667,6 +670,9 @@ public:
HINT_DEFAULT_WHITE,
HINT_DEFAULT_TRANSPARENT,
HINT_ANISOTROPY,
+ HINT_SCREEN_TEXTURE,
+ HINT_NORMAL_ROUGHNESS_TEXTURE,
+ HINT_DEPTH_TEXTURE,
HINT_MAX
};
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
index d118c73c4a..3766477070 100644
--- a/servers/rendering/shader_preprocessor.cpp
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -349,6 +349,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) {
process_ifdef(p_tokenizer);
} else if (directive == "ifndef") {
process_ifndef(p_tokenizer);
+ } else if (directive == "elif") {
+ process_elif(p_tokenizer);
} else if (directive == "else") {
process_else(p_tokenizer);
} else if (directive == "endif") {
@@ -415,10 +417,67 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) {
}
}
+void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ if (state->current_branch == nullptr || state->current_branch->else_defined) {
+ set_error(RTR("Unmatched elif."), line);
+ return;
+ }
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = line - 1;
+ }
+
+ String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ if (body.is_empty()) {
+ set_error(RTR("Missing condition."), line);
+ return;
+ }
+
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ Expression expression;
+ Vector<String> names;
+ error = expression.parse(body, names);
+ if (error != OK) {
+ set_error(expression.get_error_text(), line);
+ return;
+ }
+
+ Variant v = expression.execute(Array(), nullptr, false);
+ if (v.get_type() == Variant::NIL) {
+ set_error(RTR("Condition evaluation error."), line);
+ return;
+ }
+
+ bool skip = false;
+ for (int i = 0; i < state->current_branch->conditions.size(); i++) {
+ if (state->current_branch->conditions[i]) {
+ skip = true;
+ break;
+ }
+ }
+
+ bool success = !skip && v.booleanize();
+ start_branch_condition(p_tokenizer, success, true);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region->parent);
+ }
+}
+
void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line();
- if (state->skip_stack_else.is_empty()) {
+ if (state->current_branch == nullptr || state->current_branch->else_defined) {
set_error(RTR("Unmatched else."), line);
return;
}
@@ -428,17 +487,14 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
p_tokenizer->advance('\n');
- bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1];
- state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1);
-
- Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_filename];
- int index = vec.size() - 1;
- if (index >= 0) {
- SkippedCondition *cond = vec[index];
- if (cond->end_line == -1) {
- cond->end_line = p_tokenizer->get_line();
+ bool skip = false;
+ for (int i = 0; i < state->current_branch->conditions.size(); i++) {
+ if (state->current_branch->conditions[i]) {
+ skip = true;
+ break;
}
}
+ state->current_branch->else_defined = true;
if (state->save_regions) {
add_region(line + 1, !skip, state->previous_region->parent);
@@ -462,16 +518,10 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
state->previous_region = state->previous_region->parent;
}
- Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_filename];
- int index = vec.size() - 1;
- if (index >= 0) {
- SkippedCondition *cond = vec[index];
- if (cond->end_line == -1) {
- cond->end_line = p_tokenizer->get_line();
- }
- }
-
p_tokenizer->advance('\n');
+
+ state->current_branch = state->current_branch->parent;
+ state->branches.pop_back();
}
void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
@@ -483,7 +533,12 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
return;
}
- Error error = expand_macros(body, line, body);
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
if (error != OK) {
return;
}
@@ -703,24 +758,19 @@ void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent
state->previous_region = &state->regions[region.file].push_back(region)->get();
}
-void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) {
- state->condition_depth++;
-
- if (p_success) {
- state->skip_stack_else.push_back(true);
+void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue) {
+ if (!p_continue) {
+ state->condition_depth++;
+ state->current_branch = &state->branches.push_back(Branch(p_success, state->current_branch))->get();
} else {
- SkippedCondition *cond = memnew(SkippedCondition());
- cond->start_line = p_tokenizer->get_line();
- state->skipped_conditions[state->current_filename].push_back(cond);
-
+ state->current_branch->conditions.push_back(p_success);
+ }
+ if (!p_success) {
Vector<String> ends;
+ ends.push_back("elif");
ends.push_back("else");
ends.push_back("endif");
- if (next_directive(p_tokenizer, ends) == "else") {
- state->skip_stack_else.push_back(false);
- } else {
- state->skip_stack_else.push_back(true);
- }
+ next_directive(p_tokenizer, ends);
}
}
@@ -737,47 +787,173 @@ void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) {
add_to_output(line);
}
-Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
- Vector<Pair<String, Define *>> active_defines;
- active_defines.resize(state->defines.size());
- int index = 0;
- for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
- active_defines.set(index++, Pair<String, Define *>(E->key(), E->get()));
+Error ShaderPreprocessor::expand_condition(const String &p_string, int p_line, String &r_expanded) {
+ // Checks bracket count to be even + check the cursor position.
+ {
+ int bracket_start_count = 0;
+ int bracket_end_count = 0;
+
+ for (int i = 0; i < p_string.size(); i++) {
+ switch (p_string[i]) {
+ case CURSOR:
+ state->completion_type = COMPLETION_TYPE_CONDITION;
+ break;
+ case '(':
+ bracket_start_count++;
+ break;
+ case ')':
+ bracket_end_count++;
+ break;
+ }
+ }
+ if (bracket_start_count > bracket_end_count) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (bracket_end_count > bracket_start_count) {
+ _set_expected_error("(", p_line);
+ return FAILED;
+ }
}
- return expand_macros(p_string, p_line, active_defines, r_expanded);
+ String result = p_string;
+
+ int index = 0;
+ int index_start = 0;
+ int index_end = 0;
+
+ while (find_match(result, "defined", index, index_start)) {
+ bool open_bracket = false;
+ bool found_word = false;
+ bool word_completed = false;
+
+ LocalVector<char32_t> text;
+ int post_bracket_index = -1;
+ int size = result.size();
+
+ for (int i = (index_start - 1); i < size; i++) {
+ char32_t c = result[i];
+ if (c == 0) {
+ if (found_word) {
+ word_completed = true;
+ }
+ break;
+ }
+ char32_t cs[] = { c, '\0' };
+ String s = String(cs);
+ bool is_space = is_char_space(c);
+
+ if (word_completed) {
+ if (c == ')') {
+ continue;
+ }
+ if (c == '|' || c == '&') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ break;
+ } else if (!is_space) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ } else if (is_space) {
+ if (found_word && !open_bracket) {
+ index_end = i;
+ word_completed = true;
+ }
+ } else if (c == '(') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = true;
+ } else if (c == ')') {
+ if (open_bracket) {
+ if (!found_word) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = false;
+ post_bracket_index = i + 1;
+ } else {
+ index_end = i;
+ }
+ word_completed = true;
+ } else if (is_char_word(c)) {
+ text.push_back(c);
+ found_word = true;
+ } else {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ }
+
+ if (word_completed) {
+ if (open_bracket) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (post_bracket_index != -1) {
+ index_end = post_bracket_index;
+ }
+
+ String body = state->defines.has(vector_to_string(text)) ? "true" : "false";
+ String temp = result;
+
+ result = result.substr(0, index) + body;
+ index_start = result.length();
+ if (index_end > 0) {
+ result += temp.substr(index_end);
+ }
+ } else {
+ set_error(RTR("Invalid macro name."), p_line);
+ return FAILED;
+ }
+ }
+ r_expanded = result;
+ return OK;
}
-Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) {
- r_expanded = p_string;
- // When expanding macros we must only evaluate them once.
- // Later we continue expanding but with the already
- // evaluated macros removed.
- for (int i = 0; i < p_defines.size(); i++) {
- Pair<String, Define *> define_pair = p_defines[i];
-
- Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded);
- if (error != OK) {
- return error;
+Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
+ String iterative = p_string;
+ int pass_count = 0;
+ bool expanded = true;
+
+ while (expanded) {
+ expanded = false;
+
+ // As long as we find something to expand, keep going.
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ if (expand_macros_once(iterative, p_line, E, iterative)) {
+ expanded = true;
+ }
}
- // Remove expanded macro and recursively replace remaining.
- p_defines.remove_at(i);
- return expand_macros(r_expanded, p_line, p_defines, r_expanded);
+ pass_count++;
+ if (pass_count > 50) {
+ set_error(RTR("Macro expansion limit exceeded."), p_line);
+ break;
+ }
}
+ r_expanded = iterative;
+
+ if (!state->error.is_empty()) {
+ return FAILED;
+ }
return OK;
}
-Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) {
+bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded) {
String result = p_line;
- const String &key = p_define_pair.first;
- const Define *define = p_define_pair.second;
+ const String &key = p_define_pair->key();
+ const Define *define = p_define_pair->value();
int index_start = 0;
int index = 0;
- while (find_match(result, key, index, index_start)) {
+ if (find_match(result, key, index, index_start)) {
String body = define->body;
if (define->arguments.size() > 0) {
// Complex macro with arguments.
@@ -785,14 +961,14 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu
int args_end = p_line.find(")", args_start);
if (args_start == -1 || args_end == -1) {
set_error(RTR("Missing macro argument parenthesis."), p_line_number);
- return FAILED;
+ return false;
}
String values = result.substr(args_start + 1, args_end - (args_start + 1));
Vector<String> args = values.split(",");
if (args.size() != define->arguments.size()) {
set_error(RTR("Invalid macro argument count."), p_line_number);
- return FAILED;
+ return false;
}
// Insert macro arguments into the body.
@@ -814,11 +990,13 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu
// Manually reset index_start to where the body value of the define finishes.
// This ensures we don't skip another instance of this macro in the string.
index_start = index + body.length() + 1;
- break;
}
+
+ r_expanded = result;
+ return true;
}
- r_expanded = result;
- return OK;
+
+ return false;
}
bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) {
@@ -909,12 +1087,6 @@ void ShaderPreprocessor::clear() {
memdelete(E->get());
}
- for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) {
- for (SkippedCondition *condition : E->get()) {
- memdelete(condition);
- }
- }
-
memdelete(state);
}
state_owner = false;
@@ -1030,7 +1202,7 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
switch (pp_state.completion_type) {
case COMPLETION_TYPE_DIRECTIVE: {
List<String> options;
- get_keyword_list(&options, true);
+ get_keyword_list(&options, true, true);
for (const String &E : options) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
@@ -1049,6 +1221,11 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
}
} break;
+ case COMPLETION_TYPE_CONDITION: {
+ ScriptLanguage::CodeCompletionOption option("defined", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+
+ } break;
case COMPLETION_TYPE_INCLUDE_PATH: {
if (p_include_completion_func && r_completion_options) {
p_include_completion_func(r_completion_options);
@@ -1062,8 +1239,12 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
return err;
}
-void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) {
+void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords) {
r_keywords->push_back("define");
+ if (!p_ignore_context_keywords) {
+ r_keywords->push_back("defined");
+ }
+ r_keywords->push_back("elif");
if (p_include_shader_keywords) {
r_keywords->push_back("else");
}
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
index 41b574298d..b4e7c7199f 100644
--- a/servers/rendering/shader_preprocessor.h
+++ b/servers/rendering/shader_preprocessor.h
@@ -50,6 +50,7 @@ public:
COMPLETION_TYPE_DIRECTIVE,
COMPLETION_TYPE_PRAGMA_DIRECTIVE,
COMPLETION_TYPE_PRAGMA,
+ COMPLETION_TYPE_CONDITION,
COMPLETION_TYPE_INCLUDE_PATH,
};
@@ -130,14 +131,23 @@ private:
String body;
};
- struct SkippedCondition {
- int start_line = -1;
- int end_line = -1;
+ struct Branch {
+ Vector<bool> conditions;
+ Branch *parent = nullptr;
+ bool else_defined = false;
+
+ Branch() {}
+
+ Branch(bool p_condition, Branch *p_parent) :
+ parent(p_parent) {
+ conditions.push_back(p_condition);
+ }
};
struct State {
RBMap<String, Define *> defines;
- Vector<bool> skip_stack_else;
+ List<Branch> branches;
+ Branch *current_branch = nullptr;
int condition_depth = 0;
RBSet<String> includes;
List<uint64_t> cyclic_include_hashes; // Holds code hash of includes.
@@ -149,7 +159,6 @@ private:
bool save_regions = false;
RBMap<String, List<Region>> regions;
Region *previous_region = nullptr;
- RBMap<String, Vector<SkippedCondition *>> skipped_conditions;
bool disabled = false;
CompletionType completion_type = COMPLETION_TYPE_NONE;
HashSet<Ref<ShaderInclude>> shader_includes;
@@ -167,8 +176,17 @@ private:
static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1);
static String tokens_to_string(const LocalVector<Token> &p_tokens);
+ void _set_expected_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Expected a '%s'."), p_what), p_line);
+ }
+
+ void _set_unexpected_token_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line);
+ }
+
void process_directive(Tokenizer *p_tokenizer);
void process_define(Tokenizer *p_tokenizer);
+ void process_elif(Tokenizer *p_tokenizer);
void process_else(Tokenizer *p_tokenizer);
void process_endif(Tokenizer *p_tokenizer);
void process_if(Tokenizer *p_tokenizer);
@@ -179,12 +197,12 @@ private:
void process_undef(Tokenizer *p_tokenizer);
void add_region(int p_line, bool p_enabled, Region *p_parent_region);
- void start_branch_condition(Tokenizer *p_tokenizer, bool p_success);
+ void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false);
+ Error expand_condition(const String &p_string, int p_line, String &r_result);
void expand_output_macros(int p_start, int p_line);
Error expand_macros(const String &p_string, int p_line, String &r_result);
- Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result);
- Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded);
+ bool expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded);
bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start);
String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives);
@@ -202,7 +220,7 @@ public:
Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr);
- static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords);
+ static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords = false);
static void get_pragma_list(List<String> *r_pragmas);
ShaderPreprocessor();