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.
This commit is contained in:
Hugo Locurcio 2024-09-29 02:22:20 +02:00
parent b2b13d46c2
commit 84098ab72f
No known key found for this signature in database
GPG key ID: 39E8F8BE30B0A49C
9 changed files with 80 additions and 5 deletions

View file

@ -58,9 +58,12 @@
</methods>
<members>
<member name="albedo_color" type="Color" setter="set_albedo" getter="get_albedo" default="Color(1, 1, 1, 1)" keywords="albedo_colour, diffuse_color, diffuse_colour">
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.
</member>
<member name="albedo_energy" type="float" setter="set_albedo_energy" getter="get_albedo_energy" default="1.0">
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.
</member>
<member name="albedo_texture" type="Texture2D" setter="set_texture" getter="get_texture" keywords="diffuse_texture">
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].

View file

@ -82,7 +82,11 @@
Vertical space between lines in multiline [Label3D].
</member>
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)" keywords="color, colour">
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.
</member>
<member name="modulate_energy" type="float" setter="set_modulate_energy" getter="get_modulate_energy" default="1.0">
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.
</member>
<member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
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).
</member>
<member name="outline_modulate" type="Color" setter="set_outline_modulate" getter="get_outline_modulate" default="Color(0, 0, 0, 1)">
The tint of text outline.
The tint of text outline. See also [member modulate] and [member modulate_energy].
</member>
<member name="outline_render_priority" type="int" setter="set_outline_render_priority" getter="get_outline_render_priority" default="-1">
Sets the render priority for the text outline. Higher priority objects will be sorted in front of lower priority objects.

View file

@ -77,9 +77,12 @@
</member>
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)" keywords="color, colour">
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.
</member>
<member name="modulate_energy" type="float" setter="set_modulate_energy" getter="get_modulate_energy" default="1.0">
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.
</member>
<member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], depth testing is disabled and the object will be drawn in render order.
</member>

View file

@ -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;

View file

@ -119,6 +119,7 @@ private:
Ref<Font> font_override;
mutable Ref<Font> 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;

View file

@ -250,6 +250,8 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> 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);

View file

@ -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;

View file

@ -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);

View file

@ -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;