Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GradientTexture2D #2 #53234

Merged
merged 1 commit into from
Oct 29, 2021
Merged

Conversation

Geometror
Copy link
Member

@Geometror Geometror commented Sep 29, 2021

Co-authored-by:
Mariano Suligoy marianognu.easyrpg@gmail.com
Andrii Doroshenko xrayez@gmail.com

This PR is essentially rebased version of #42855 slightly modified. Thanks to @Xrayez and @MarianoGnu for their awesome work!
I created a new icon for the GradientTexture2D which fits better in the current icon style and ported goostengine/goost@c9ff44d over. In addition, high dynamic range is now supported via the use_hdr property (like with GradientTexture).
Although this is already implemented in Goost I believe this should be a part of the vanilla engine since it is really nice to work with and accelerates the workflow immensely in many cases/makes some things possible which couldn't be achieved without high efforts before. (useful for Light2D, backgrounds, particles, etc.)

Implements godotengine/godot-proposals#1677, closes godotengine/godot-proposals#3240 (discussed via chat that the texture is enough)

Some examples/use cases:

grafik
grafik

Here is an animated example (the text infill is also dynamic):

main

Feedback is welcome :)
Also: Any thoughts on whether GradientTexture should be renamed to GradientTexture1D?

Copy link
Member

@groud groud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not go into the details of the implementation, but the API looks fine and the feature seems a good addition to me.

Comment on lines 1936 to 1939
wd8[(x + (y * width)) * 4 + 0] = uint8_t(CLAMP(c.r * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 1] = uint8_t(CLAMP(c.g * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 2] = uint8_t(CLAMP(c.b * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 3] = uint8_t(CLAMP(c.a * 255.0, 0, 255));
Copy link
Member

@kleonc kleonc Sep 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Casting like uint8_t(...) will trim the fractional part which means that with the current implementation only values >= 1.0 would result in 255 value (so for example 0.999 would result in 254). I doubt that's desired. So probably it should be (using round() as mentioned in the comment below would be better):

Suggested change
wd8[(x + (y * width)) * 4 + 0] = uint8_t(CLAMP(c.r * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 1] = uint8_t(CLAMP(c.g * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 2] = uint8_t(CLAMP(c.b * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 3] = uint8_t(CLAMP(c.a * 255.0, 0, 255));
wd8[(x + (y * width)) * 4 + 0] = uint8_t(CLAMP(c.r * 256.0, 0, 255));
wd8[(x + (y * width)) * 4 + 1] = uint8_t(CLAMP(c.g * 256.0, 0, 255));
wd8[(x + (y * width)) * 4 + 2] = uint8_t(CLAMP(c.b * 256.0, 0, 255));
wd8[(x + (y * width)) * 4 + 3] = uint8_t(CLAMP(c.a * 256.0, 0, 255));

It would divide <0.0, 1.0> range into 256 equal length ranges (up to the precision errors) so for example values from range (more or less) <0.99609375, 1.0> would result in 255 value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but this is how Image does it currently.

Perhaps have to use round() in those cases?: #47022 (comment) (it would be less efficient I presume).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep it like that at least for now since it is consistent with Image and GradientTexture(1D) and discuss/tackle this problem in a future PR (for all occurrences).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but this is how Image does it currently.

Hmm, then maybe it's indeed a desired behavior? Not sure. But yeah, in this PR it can be made consistent with the rest of the code base then (and potential change could be made in a different PR).

Perhaps have to use round() in those cases?: #47022 (comment) (it would be less efficient I presume).

After rethinking using round() would indeed be better then what I proposed here, it would result in a smaller average absolute "conversion error". And performance wise I guess it shouldn't be a big difference, it's probably just an additional + 0.5 instruction before the truncation (but it probably should be benchmarked).

Anyway, I agree with both of you, it's out of scope of this PR.

Copy link
Member

@fire fire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not go into details, but previous versions were approved by me.

@fire
Copy link
Member

fire commented Sep 29, 2021

Your code/doc changes are incomplete and you should update the class reference with --doctool.

@Geometror
Copy link
Member Author

Added the use_hdr property to allow for high dynamic range gradients (and for consistency, since GradientTexture (1D) has it).

grafik

Comment on lines 1917 to 1924
image->create(width, height, false, (use_hdr) ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8);
Color color;
if (gradient->get_points_count() == 1) {
color = gradient->get_color(0);
} else {
color = Color(0, 0, 0, 1);
}
image->fill(color);
Copy link
Contributor

@AaronRecord AaronRecord Oct 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
image->create(width, height, false, (use_hdr) ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8);
Color color;
if (gradient->get_points_count() == 1) {
color = gradient->get_color(0);
} else {
color = Color(0, 0, 0, 1);
}
image->fill(color);
image->create(width, height, false, use_hdr ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8);
if (gradient->get_points_count() == 1) {
image->fill(gradient->get_color(0));
}

Or if black is preferred over transparent:

Suggested change
image->create(width, height, false, (use_hdr) ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8);
Color color;
if (gradient->get_points_count() == 1) {
color = gradient->get_color(0);
} else {
color = Color(0, 0, 0, 1);
}
image->fill(color);
image->create(width, height, false, use_hdr ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8);
image->fill(gradient->get_points_count() == 1 ? gradient->get_color(0) : Color(0, 0, 0, 1));

Just a suggestion

Copy link
Member Author

@Geometror Geometror Oct 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to your two-line-approach, however I kept the braces around the condition of the ternary operator since that seems to be an unwritten rule of Godot's code style guidelines.

@Geometror Geometror force-pushed the gradient-texture-2d branch 3 times, most recently from 7920eaa to 72944fe Compare October 12, 2021 14:02
Co-authored-by: Mariano Javier Suligoy <marianognu.easyrpg@gmail.com>
Co-authored-by: Andrii Doroshenko <xrayez@gmail.com>
@Chaosus
Copy link
Member

Chaosus commented Oct 29, 2021

Thanks!

@kleonc
Copy link
Member

kleonc commented Nov 3, 2021

Anything against backporting it to 3.x?

@AaronRecord
Copy link
Contributor

Anything against backporting it to 3.x?

Probably not, it doesn't change any existing code and I don't think it relies on any 4.0 exclusive features

@TackerTacker
Copy link

Would it be possible to have textured gradients?
A gradient where you use textures instead of a colors.

@Xrayez
Copy link
Contributor

Xrayez commented Jan 14, 2022

You can use GradientTexture2D to apply a color gradient over a texture by blending them (via shaders or built-in materials), apart from that the GradientTexture2D handles color gradients only.

If you have a concrete example to show, feel free to create a discussion at https://github.com/godot-extended-libraries/godot-ideas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a Gradient2D resource
9 participants