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

Line2D doesn't draw full gradient if it doesn't have enough points #50076

Open
KoBeWi opened this issue Jul 2, 2021 · 9 comments
Open

Line2D doesn't draw full gradient if it doesn't have enough points #50076

KoBeWi opened this issue Jul 2, 2021 · 9 comments

Comments

@KoBeWi
Copy link
Member

KoBeWi commented Jul 2, 2021

Godot version

3.3 / 6ef0b8f

System information

W10

Issue description

ndlJcQAFvJ
It would maybe make sense if the offsets were ignored and instead it used only the colors, but it's not the case.

Steps to reproduce

  1. Add Line2D
  2. Add 2 points to it
  3. Add a gradient to gradient property, with 3 colors

Minimal reproduction project

No response

@Calinou
Copy link
Member

Calinou commented Jul 2, 2021

We could add a node configuration warning for this purpose.

@kleonc
Copy link
Member

kleonc commented Jul 3, 2021

Line2D doesn't draw full gradient if it doesn't have enough points

In fact, Gradient is being drawn accurately in Line2D only in some simple cases, even if there are more points in Line2D than color points in the Gradient. In most cases it's really just an approximation of the used Gradient. Iterpolation is not being done accurately because what's interpolated in the end are vertex colors and even though vertex colors are properly assigned according to the Gradient, everything in between vertices might be color-wise "desynchronized" with the Gradient.

8hH2F7W4uX

There's kinda the same issue with the width curve of Line2D.

@timcode77
Copy link

I get exactly the same problem in v3.4.4.stable.official [419e713].

@Calinou
Copy link
Member

Calinou commented Jul 24, 2022

Fixing this probably involves automatically creating "subdivision" points behind the scenes, and ensuring the line is made of at least as many points as the gradient.

It may not be worth the added complexity, so maybe we should just document that you have to create enough points for the gradient's color to be accurately represented.

@timcode77
Copy link

Fixing this probably involves automatically creating "subdivision" points behind the scenes, and ensuring the line is made of at least as many points as the gradient.

It may not be worth the added complexity, so maybe we should just document that you have to create enough points for the gradient's color to be accurately represented.

I think the problem runs deeper. See the series of screen grabs below. In these examples, the line always has 3 points and it has the same gradient with 3 colors. Yet only the first (leftmost, black) and last (rightmost, white) color get properly rendered. The middle color (red) doesn't always get properly rendered in the line. Therefore, just adding the same amount of points in the line as there are colors in the gradient are not sufficient to fix this problem.

image

image

image

image

@Calinou
Copy link
Member

Calinou commented Jul 24, 2022

@timcode77 What I mean is that the subdivided points should also be created at the same offset as the gradient. This should make it possible to render any gradient correctly, no matter how many points your line is actually made of.

@timcode77
Copy link

@timcode77 What I mean is that the subdivided points should also be created at the same offset as the gradient. This should make it possible to render any gradient correctly, no matter how many points your line is actually made of.

Ah ok. I misunderstood you. I was confusing "points": the things Line2D is comprised of in the editor and that are accessible to the user. Whereas you are talking about "subdivided points" which you are proposing get calculated behind the scenes and are not accessible to the user. Is that right?

@Calinou
Copy link
Member

Calinou commented Jul 25, 2022

Whereas you are talking about "subdivided points" which you are proposing get calculated behind the scenes and are not accessible to the user. Is that right?

Yes 🙂

@kleonc
Copy link
Member

kleonc commented Jul 25, 2022

What I mean is that the subdivided points should also be created at the same offset as the gradient. This should make it possible to render any gradient correctly, no matter how many points your line is actually made of.

Note that this would work for a linear gradient. In 3.5+/4.0 there are also constant and cubic interpolation modes (added in #60982/#53321). Constant interpolation could be easily handled by doubling the "gradient points" within the line. Cubic interpolation based only on the vertex colors would be possible in a dedicated shader, which I'd guess is unlikely to be done (so I'd assume it won't be supported for Line2D.gradient property).

But the thing is... there are gradient textures. Applying gradient with a texture is trivial and it works already (it of course has its own quirks):

  • 3.4.4.stable, Gradient:

rq1qE5Shvl

  • 3.4.4.stable, GradientTexture using the same Gradient:
    Godot_v3 4 4-stable_win64_6lAgCRhZiA
    Example of visible uneven UVs interpolation (that's probably unavoidable because of uneven line borders' lengths? 🤔):
    epuMzFGi1N

I guess using the Gradient directly to assign vertex colors for the line mesh (that's what happens for Line2D.gradient property) is supposed to be cheaper than the texture gradient and that's the reason it exists in the first place? If so then I wonder if making gradients be correctly rendered by increasing the line mesh vertex count wouldn't neglect the benefits of this solution over using the gradient textures.

Also note that currently there's only one texture in the Line2D so by design you can't apply some Texture and a GradientTexture on top of it. Nonetheless it's not hard to work around that:
9bbUmTpHXT

shader_type canvas_item;

uniform sampler2D gradient_texture: hint_albedo;
uniform vec2 default_texture_tiling_factor = vec2(1.0);

void fragment() {
	COLOR = texture(TEXTURE, UV * default_texture_tiling_factor) * texture(gradient_texture, UV);
}

BTW this example perfectly shows that texture UVs are kinda bugged and this for sure could be improved? 🤔


To sum up: not really sure what should be done about this issue. 🙂

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

No branches or pull requests

4 participants