Add an use_hdr
property to GradientTexture to allow storing HDR colors
This is disabled by default to save some memory and preserve the existing behavior of clamping colors.
This commit is contained in:
parent
761eb7e06a
commit
1d257d02db
3 changed files with 62 additions and 18 deletions
|
@ -14,6 +14,9 @@
|
|||
<member name="gradient" type="Gradient" setter="set_gradient" getter="get_gradient">
|
||||
The [Gradient] that will be used to fill the texture.
|
||||
</member>
|
||||
<member name="use_hdr" type="bool" setter="set_use_hdr" getter="is_using_hdr" default="false">
|
||||
If [code]true[/code], the generated texture will support high dynamic range ([constant Image.FORMAT_RGBAF] format). This allows for glow effects to work if [member Environment.glow_enabled] is [code]true[/code]. If [code]false[/code], the generated texture will use low dynamic range; overbright colors will be clamped ([constant Image.FORMAT_RGBA8] format).
|
||||
</member>
|
||||
<member name="width" type="int" setter="set_width" getter="get_width" default="2048">
|
||||
The number of color samples that will be obtained from the [Gradient].
|
||||
</member>
|
||||
|
|
|
@ -1758,11 +1758,16 @@ void GradientTexture::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_gradient"), &GradientTexture::get_gradient);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture::set_width);
|
||||
// The `get_width()` method is already exposed by the parent class Texture2D.
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_hdr", "enabled"), &GradientTexture::set_use_hdr);
|
||||
ClassDB::bind_method(D_METHOD("is_using_hdr"), &GradientTexture::is_using_hdr);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
|
||||
}
|
||||
|
||||
void GradientTexture::set_gradient(Ref<Gradient> p_gradient) {
|
||||
|
@ -1800,30 +1805,49 @@ void GradientTexture::_update() {
|
|||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> data;
|
||||
data.resize(width * 4);
|
||||
{
|
||||
uint8_t *wd8 = data.ptrw();
|
||||
if (use_hdr) {
|
||||
// High dynamic range.
|
||||
Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBAF));
|
||||
Gradient &g = **gradient;
|
||||
|
||||
// `create()` isn't available for non-uint8_t data, so fill in the data manually.
|
||||
for (int i = 0; i < width; i++) {
|
||||
float ofs = float(i) / (width - 1);
|
||||
Color color = g.get_color_at_offset(ofs);
|
||||
|
||||
wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255));
|
||||
wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255));
|
||||
wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255));
|
||||
wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255));
|
||||
image->set_pixel(i, 0, g.get_color_at_offset(ofs));
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data));
|
||||
|
||||
if (texture.is_valid()) {
|
||||
RID new_texture = RS::get_singleton()->texture_2d_create(image);
|
||||
RS::get_singleton()->texture_replace(texture, new_texture);
|
||||
if (texture.is_valid()) {
|
||||
RID new_texture = RS::get_singleton()->texture_2d_create(image);
|
||||
RS::get_singleton()->texture_replace(texture, new_texture);
|
||||
} else {
|
||||
texture = RS::get_singleton()->texture_2d_create(image);
|
||||
}
|
||||
} else {
|
||||
texture = RS::get_singleton()->texture_2d_create(image);
|
||||
// Low dynamic range. "Overbright" colors will be clamped.
|
||||
Vector<uint8_t> data;
|
||||
data.resize(width * 4);
|
||||
{
|
||||
uint8_t *wd8 = data.ptrw();
|
||||
Gradient &g = **gradient;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
float ofs = float(i) / (width - 1);
|
||||
Color color = g.get_color_at_offset(ofs);
|
||||
|
||||
wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255));
|
||||
wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255));
|
||||
wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255));
|
||||
wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data));
|
||||
|
||||
if (texture.is_valid()) {
|
||||
RID new_texture = RS::get_singleton()->texture_2d_create(image);
|
||||
RS::get_singleton()->texture_replace(texture, new_texture);
|
||||
} else {
|
||||
texture = RS::get_singleton()->texture_2d_create(image);
|
||||
}
|
||||
}
|
||||
|
||||
emit_changed();
|
||||
|
@ -1839,6 +1863,19 @@ int GradientTexture::get_width() const {
|
|||
return width;
|
||||
}
|
||||
|
||||
void GradientTexture::set_use_hdr(bool p_enabled) {
|
||||
if (p_enabled == use_hdr) {
|
||||
return;
|
||||
}
|
||||
|
||||
use_hdr = p_enabled;
|
||||
_queue_update();
|
||||
}
|
||||
|
||||
bool GradientTexture::is_using_hdr() const {
|
||||
return use_hdr;
|
||||
}
|
||||
|
||||
Ref<Image> GradientTexture::get_image() const {
|
||||
if (!texture.is_valid()) {
|
||||
return Ref<Image>();
|
||||
|
|
|
@ -686,6 +686,7 @@ private:
|
|||
bool update_pending = false;
|
||||
RID texture;
|
||||
int width = 2048;
|
||||
bool use_hdr = false;
|
||||
|
||||
void _queue_update();
|
||||
void _update();
|
||||
|
@ -700,6 +701,9 @@ public:
|
|||
void set_width(int p_width);
|
||||
int get_width() const override;
|
||||
|
||||
void set_use_hdr(bool p_enabled);
|
||||
bool is_using_hdr() const;
|
||||
|
||||
virtual RID get_rid() const override { return texture; }
|
||||
virtual int get_height() const override { return 1; }
|
||||
virtual bool has_alpha() const override { return true; }
|
||||
|
|
Loading…
Reference in a new issue