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

Fix stroke widths and hairline strokes in wgpu and webgl #9981

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

Dinnerbone
Copy link
Contributor

@Dinnerbone Dinnerbone commented Mar 11, 2023

This fixes #751 (and probably a lot of other issues that should be tested)

This will come at a performance cost, but the size of that isn't known yet (I can't benchmark right now, PC is unhappy with me).

@Dinnerbone Dinnerbone force-pushed the strokes branch 2 times, most recently from 68c2449 to 5be3335 Compare March 11, 2023 01:41
@MrCheeze
Copy link
Contributor

Can confirm it fixes #1955 !

@SN902
Copy link

SN902 commented Mar 11, 2023

Problems with outlines in next games:
Rainbow Dash Shooter Project.zip Intro screen: pony and griffon
sponge_fall_game.zip gameplay, medusa outline
bloons-tower-defense-5.zip monkey on Login screen
Boxhead_Rooms.zip crazy monkey logo broken

Animations:
Beep Beep like a sheep.zip text lyrics: Beep Beep
hakurei_reimu_kirisame_marisa_yakumo.zip bow on girls head and body outlines
02. Поттер.zip animation of the mouth, eyes, outlines (note: old Russian animation with specific humor)

@Toad06
Copy link
Member

Toad06 commented Mar 11, 2023

Thanks a lot for your work on this. 😉

This PR is a great improvement for all of the Steppenwolf games, for instance Steppenwolf 2-1. There are still some issues that I'm mentioning below.


Regression on the canvas renderer - looks wild now:
canvas


This one is less important but strokes look a bit smoother in Flash Player and in Nightly Ruffle using the canvas renderer:

fp
rpr
rcan

@torokati44
Copy link
Member

torokati44 commented Mar 11, 2023

This one is less important but strokes look a bit smoother in Flash Player and in Nightly Ruffle using the canvas renderer:

What's strange is that the overhead baggage shelf is missing on canvas backend... :D

@Toad06
Copy link
Member

Toad06 commented Mar 11, 2023

What's strange is that the overhead baggage shelf is missing on canvas backend... :D

Yeah, I noticed that too while posting, seems to be a very old bug (I tried with a release from November 2020 and the issue was already there).

@Dinnerbone Dinnerbone marked this pull request as draft March 14, 2023 09:08
@Herschel
Copy link
Member

Herschel commented Mar 16, 2023

Thanks so much for your work on this!

Some thoughts so far:

  • The code is assuming that all fills are drawn first, and then strokes, but this isn't necessarily the case. A ChangeStyle record with new styles basically indicates a "flush", where new fills will draw on top of previous strokes. This is how the Flash IDE exports raw vector art containing layers.

Example SWF
FP vs this PR:
image

So the idea of splitting into one stroke part and one fill part doesn't handle all cases; you'd need to at least allow for multiple stroke shapes between multiple fill shapes.

  • Because only strokes get re-tessellated, this can produce some unsightly gaps between the stroke and a jaggy fill:

Example SWF
FP vs this PR
image

Naturally this is a pathological case, but just pointing out the obvious.

  • In a perfect world we would also re-tessellate fills if they contain curves, to avoid jaggies on zoom even for stroke-less shapes. Obviously, this is even huger performance hazard, but I believe we'll need to do it at some point. Instead of of "re-tessellate anytime scale changes" like strokes, I picture a stroke-less shape could be more coarse and only re-tessellate on some large threshold of change. And I'm sure this PR is only concerned about strokes at the moment.

  • RenderBackend::register_shape_fills/register_stroke_fills seems like leaking implementation details into the renderer API. In a perfect world, core wouldn't care about retessellating at all, and only the tessellation backend itself would manage this, but I understand that this is probably the only sane way to do this at the moment, and we are focusing on WGPU for the near future. I point it out because a Vello/other-fancy-vector-rendering is always in the back of my mind.

  • Given all of the above, I think I'd want to edge a bit more towards an API that is "re-tessellate the entire shape" vs. "re-tessellate strokes and shapes separately", since we'd want to re-tessellate fills eventually, and it seems a little simpler to manage assuming the performance isn't awful. This would help us deal with both the layered-stroke and the jaggy-fills cases above. But I could be wrong here, and simply allowing for multiple stroke-layers in the shape is good enough.

This is PR is a huge improvement and the above is me thinking out loud. Sorry if this has already been discussed ad nauseum on Discord, and I'm just out of the loop or completely off-base. 😄

@Dinnerbone
Copy link
Contributor Author

Dinnerbone commented Mar 16, 2023

@Herschel you're absolutely right and I realized that a while ago which is why I put this back to draft, sorry to make you type all that out 😅 I'm going to redo this with lessons learnt shortly, but trying to make more tests too.

Most likely it's going to redo the entire shape but only if there's non scaling strokes involved, otherwise the shape can stay static. And it still only needs to redo the shape once a scale changed, I believe. I think there's room to optimise further after that but we need a lot more tests before I'd feel comfortable, and that feels right to me for a basic start

@Herschel
Copy link
Member

Most likely it's going to redo the entire shape but only if there's non scaling strokes involved, otherwise the shape can stay static.

This should probably also consider hairline strokes as non-scaling, as these act like non-scaling until the shape is scaled >20x, so I think they'd show the above artifacts as well.

Here's a good worst-case example for testing scaled strokes and shapes: Dad 'n Me used some weirdo optimizer to scale the assets way down and then back up, so huge strokes and jaggies in shapes will be very obvious here. (Tom has since fixed this in the SWF on Newgrounds, but this is the original SWF.) DadNMeNg.zip

@danielhjacobs danielhjacobs added A-rendering Area: Rendering & Graphics render-webgl Issues relating to the WebGL renderer render-wgpu Issues relating to the wgpu renderer T-fix Type: Bug fix (in something that's supposed to work already) labels Sep 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rendering Area: Rendering & Graphics render-webgl Issues relating to the WebGL renderer render-wgpu Issues relating to the wgpu renderer T-fix Type: Bug fix (in something that's supposed to work already)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Mini-Putt 2] Differences with the Flash version
7 participants