From 84098ab72fcb8071c85a54498954518ead9cd891 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sun, 29 Sep 2024 02:22:20 +0200 Subject: [PATCH] Add Modulate/Albedo Energy property to SpriteBase3D, Label3D and BaseMaterial3D For SpriteBase3D and Label3D, this restores the ability to use overbright colors that was available in 3.x. This can be used to make certain elements of the scene glow without having to reduce the glow's HDR threshold. For all 3 nodes, this allows adjusting brightness independently of color, which is useful for animation/VFX purposes. --- doc/classes/BaseMaterial3D.xml | 5 ++++- doc/classes/Label3D.xml | 8 ++++++-- doc/classes/SpriteBase3D.xml | 5 ++++- scene/3d/label_3d.cpp | 16 ++++++++++++++++ scene/3d/label_3d.h | 4 ++++ scene/3d/sprite_3d.cpp | 20 ++++++++++++++++++++ scene/3d/sprite_3d.h | 4 ++++ scene/resources/material.cpp | 18 +++++++++++++++++- scene/resources/material.h | 5 +++++ 9 files changed, 80 insertions(+), 5 deletions(-) diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fc8af02869e..9210eb3c687 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -58,9 +58,12 @@ - The material's base color. + The material's base color. See also [member albedo_energy]. [b]Note:[/b] If [member detail_enabled] is [code]true[/code] and a [member detail_albedo] texture is specified, [member albedo_color] will [i]not[/i] modulate the detail texture. This can be used to color partial areas of a material by not specifying an albedo texture and using a transparent [member detail_albedo] texture instead. + + The brightness multiplier for [member albedo_color]. This can be used to achieve [i]overbright[/i] colors to make specific materials glow (when [member Environment.glow_enabled] is [code]true[/code]), or to adjust brightness independently of color. + Texture to multiply by [member albedo_color]. Used for basic texturing of objects. If the texture appears unexpectedly too dark or too bright, check [member albedo_texture_force_srgb]. diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index ff26c5490dd..2387b0111f4 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -82,7 +82,11 @@ Vertical space between lines in multiline [Label3D]. - Text [Color] of the [Label3D]. + Text [Color] of the [Label3D]. See also [member outline_modulate] and [member modulate_energy]. + [b]Note:[/b] Unlike [member CanvasItem.modulate] for 2D, colors with values above [code]1.0[/code] (overbright) are not supported using [member modulate] alone. Use [member modulate_energy] instead. + + + The brightness multiplier for [member modulate] and [member outline_modulate]. This can be used to achieve [i]overbright[/i] colors to make specific materials glow (when [member Environment.glow_enabled] is [code]true[/code]), or to adjust brightness independently of color. If [code]true[/code], depth testing is disabled and the object will be drawn in render order. @@ -91,7 +95,7 @@ The text drawing offset (in pixels). - The tint of text outline. + The tint of text outline. See also [member modulate] and [member modulate_energy]. Sets the render priority for the text outline. Higher priority objects will be sorted in front of lower priority objects. diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index d6f8a519db7..fb9be3325c2 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -77,9 +77,12 @@ A color value used to [i]multiply[/i] the texture's colors. Can be used for mood-coloring or to simulate the color of ambient light. - [b]Note:[/b] Unlike [member CanvasItem.modulate] for 2D, colors with values above [code]1.0[/code] (overbright) are not supported. + [b]Note:[/b] Unlike [member CanvasItem.modulate] for 2D, colors with values above [code]1.0[/code] (overbright) are not supported using [member modulate] alone. Use [member modulate_energy] instead. [b]Note:[/b] If a [member GeometryInstance3D.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the color defined in [member modulate] will be ignored. For a [BaseMaterial3D], [member BaseMaterial3D.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. + + The brightness multiplier for [member modulate]. This can be used to achieve [i]overbright[/i] colors to make specific materials glow (when [member Environment.glow_enabled] is [code]true[/code]), or to adjust brightness independently of color. + If [code]true[/code], depth testing is disabled and the object will be drawn in render order. diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 6b3510a72a1..6cfcf29a285 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -44,6 +44,9 @@ void Label3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &Label3D::set_modulate); ClassDB::bind_method(D_METHOD("get_modulate"), &Label3D::get_modulate); + ClassDB::bind_method(D_METHOD("set_modulate_energy", "energy"), &Label3D::set_modulate_energy); + ClassDB::bind_method(D_METHOD("get_modulate_energy"), &Label3D::get_modulate_energy); + ClassDB::bind_method(D_METHOD("set_outline_modulate", "modulate"), &Label3D::set_outline_modulate); ClassDB::bind_method(D_METHOD("get_outline_modulate"), &Label3D::get_outline_modulate); @@ -145,6 +148,7 @@ void Label3D::_bind_methods() { ADD_GROUP("Text", ""); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_modulate"), "set_outline_modulate", "get_outline_modulate"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "modulate_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_modulate_energy", "get_modulate_energy"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size"); @@ -363,6 +367,7 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, surf.material = RenderingServer::get_singleton()->material_create(); // Set defaults for material, names need to match up those in StandardMaterial3D RS::get_singleton()->material_set_param(surf.material, "albedo", Color(1, 1, 1, 1)); + RS::get_singleton()->material_set_param(surf.material, "albedo_energy", modulate_energy); RS::get_singleton()->material_set_param(surf.material, "specular", 0.5); RS::get_singleton()->material_set_param(surf.material, "metallic", 0.0); RS::get_singleton()->material_set_param(surf.material, "roughness", 1.0); @@ -867,6 +872,17 @@ Color Label3D::get_modulate() const { return modulate; } +void Label3D::set_modulate_energy(float p_energy) { + if (modulate_energy != p_energy) { + modulate_energy = p_energy; + _queue_update(); + } +} + +float Label3D::get_modulate_energy() const { + return modulate_energy; +} + void Label3D::set_outline_modulate(const Color &p_color) { if (outline_modulate != p_color) { outline_modulate = p_color; diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h index 332eaac18dd..4f7661a7b1c 100644 --- a/scene/3d/label_3d.h +++ b/scene/3d/label_3d.h @@ -119,6 +119,7 @@ private: Ref font_override; mutable Ref theme_font; Color modulate = Color(1, 1, 1, 1); + float modulate_energy = 1.0f; Point2 lbl_offset; int outline_render_priority = -1; int render_priority = 0; @@ -210,6 +211,9 @@ public: void set_modulate(const Color &p_color); Color get_modulate() const; + void set_modulate_energy(float p_energy); + float get_modulate_energy() const; + void set_outline_modulate(const Color &p_color); Color get_outline_modulate() const; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 42460eec4cf..f6e5824ead4 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -250,6 +250,8 @@ void SpriteBase3D::draw_texture_rect(Ref p_texture, Rect2 p_dst_rect, RS::get_singleton()->mesh_set_custom_aabb(mesh_new, aabb_new); set_aabb(aabb_new); + RS::get_singleton()->material_set_param(get_material(), "albedo_energy", modulate_energy); + RS::get_singleton()->material_set_param(get_material(), "alpha_scissor_threshold", alpha_scissor_threshold); RS::get_singleton()->material_set_param(get_material(), "alpha_hash_scale", alpha_hash_scale); RS::get_singleton()->material_set_param(get_material(), "alpha_antialiasing_edge", alpha_antialiasing_edge); @@ -350,6 +352,19 @@ Color SpriteBase3D::get_modulate() const { return modulate; } +void SpriteBase3D::set_modulate_energy(float p_energy) { + if (modulate_energy == p_energy) { + return; + } + + modulate_energy = p_energy; + _queue_redraw(); +} + +float SpriteBase3D::get_modulate_energy() const { + return modulate_energy; +} + void SpriteBase3D::set_render_priority(int p_priority) { ERR_FAIL_COND(p_priority < RS::MATERIAL_RENDER_PRIORITY_MIN || p_priority > RS::MATERIAL_RENDER_PRIORITY_MAX); @@ -603,6 +618,9 @@ void SpriteBase3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &SpriteBase3D::set_modulate); ClassDB::bind_method(D_METHOD("get_modulate"), &SpriteBase3D::get_modulate); + ClassDB::bind_method(D_METHOD("set_modulate_energy", "energy"), &SpriteBase3D::set_modulate_energy); + ClassDB::bind_method(D_METHOD("get_modulate_energy"), &SpriteBase3D::get_modulate_energy); + ClassDB::bind_method(D_METHOD("set_render_priority", "priority"), &SpriteBase3D::set_render_priority); ClassDB::bind_method(D_METHOD("get_render_priority"), &SpriteBase3D::get_render_priority); @@ -644,6 +662,7 @@ void SpriteBase3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "modulate_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_modulate_energy", "get_modulate_energy"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "axis", PROPERTY_HINT_ENUM, "X-Axis,Y-Axis,Z-Axis"), "set_axis", "get_axis"); ADD_GROUP("Flags", ""); @@ -682,6 +701,7 @@ SpriteBase3D::SpriteBase3D() { material = RenderingServer::get_singleton()->material_create(); // Set defaults for material, names need to match up those in StandardMaterial3D. RS::get_singleton()->material_set_param(material, "albedo", Color(1, 1, 1, 1)); + RS::get_singleton()->material_set_param(material, "albedo_energy", 1.0); RS::get_singleton()->material_set_param(material, "specular", 0.5); RS::get_singleton()->material_set_param(material, "metallic", 0.0); RS::get_singleton()->material_set_param(material, "roughness", 1.0); diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 8f50a528ccf..e256da7e9b6 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -73,6 +73,7 @@ private: bool vflip = false; Color modulate = Color(1, 1, 1, 1); + float modulate_energy = 1.0f; int render_priority = 0; Vector3::Axis axis = Vector3::AXIS_Z; @@ -138,6 +139,9 @@ public: void set_modulate(const Color &p_color); Color get_modulate() const; + void set_modulate_energy(float p_energy); + float get_modulate_energy() const; + void set_pixel_size(real_t p_amount); real_t get_pixel_size() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index ab25aabb81d..5172e99ace4 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -536,6 +536,7 @@ void BaseMaterial3D::init_shaders() { shader_names = memnew(ShaderNames); shader_names->albedo = "albedo"; + shader_names->albedo_energy = "albedo_energy"; shader_names->specular = "specular"; shader_names->roughness = "roughness"; shader_names->metallic = "metallic"; @@ -827,6 +828,7 @@ void BaseMaterial3D::_update_shader() { // Generate list of uniforms. code += vformat(R"( uniform vec4 albedo : source_color; +uniform float albedo_energy : hint_range(0.0, 100.0, 0.01); uniform sampler2D texture_albedo : source_color, %s; )", texfilter_str); @@ -1492,7 +1494,7 @@ void fragment() {)"; )"; } - code += " ALBEDO = albedo.rgb * albedo_tex.rgb;\n"; + code += " ALBEDO = albedo.rgb * albedo_energy * albedo_tex.rgb;\n"; if (!orm) { if (flags[FLAG_UV1_USE_TRIPLANAR]) { @@ -1903,6 +1905,15 @@ Color BaseMaterial3D::get_albedo() const { return albedo; } +void BaseMaterial3D::set_albedo_energy(float p_albedo_energy) { + albedo_energy = p_albedo_energy; + RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo_energy, p_albedo_energy); +} + +float BaseMaterial3D::get_albedo_energy() const { + return albedo_energy; +} + void BaseMaterial3D::set_specular(float p_specular) { specular = p_specular; RS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); @@ -2862,6 +2873,9 @@ void BaseMaterial3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &BaseMaterial3D::set_albedo); ClassDB::bind_method(D_METHOD("get_albedo"), &BaseMaterial3D::get_albedo); + ClassDB::bind_method(D_METHOD("set_albedo_energy", "albedo_energy"), &BaseMaterial3D::set_albedo_energy); + ClassDB::bind_method(D_METHOD("get_albedo_energy"), &BaseMaterial3D::get_albedo_energy); + ClassDB::bind_method(D_METHOD("set_transparency", "transparency"), &BaseMaterial3D::set_transparency); ClassDB::bind_method(D_METHOD("get_transparency"), &BaseMaterial3D::get_transparency); @@ -3087,6 +3101,7 @@ void BaseMaterial3D::_bind_methods() { ADD_GROUP("Albedo", "albedo_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_albedo_energy", "get_albedo_energy"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ALBEDO); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_texture_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_texture_msdf"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_MSDF); @@ -3370,6 +3385,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) : orm = p_orm; // Initialize to the same values as the shader set_albedo(Color(1.0, 1.0, 1.0, 1.0)); + set_albedo_energy(1.0); set_specular(0.5); set_roughness(1.0); set_metallic(0.0); diff --git a/scene/resources/material.h b/scene/resources/material.h index 25c4450682f..db4e35b7103 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -404,6 +404,7 @@ private: struct ShaderNames { StringName albedo; + StringName albedo_energy; StringName specular; StringName metallic; StringName roughness; @@ -471,6 +472,7 @@ private: bool orm; Color albedo; + float albedo_energy = 1.0f; float specular = 0.0f; float metallic = 0.0f; float roughness = 0.0f; @@ -568,6 +570,9 @@ public: void set_albedo(const Color &p_albedo); Color get_albedo() const; + void set_albedo_energy(float p_albedo_energy); + float get_albedo_energy() const; + void set_specular(float p_specular); float get_specular() const;