Fading strokes in Unity
Hello! Iโm running into an issue with alpha clip/cutoff issues with the Open Brush shaders. Adding a fade effect to the shader results in jumpy/pop-in behavior when trying to control the alpha. Assistance getting this to be a smoother transition without the pop-in would be greatly appreciated ๐
Alternatively, help with replicating the stroke replay effect that appears when loading any Open Brush sketch would be fantastic ๐ This is the preferred effect but I figure troubleshooting the fade effect would be easier
7 Replies
Actually - i think the intro effect might be easier.
Strokes have a timestamp stored in one of the UV channels and you can use this to "replay" the stroke. I've got some test code somewhere
There are a few gotchas but I've seen it work
In fact - I've been intending to tidy this up and add it officially to the SDK. This might be a good time to do that if you want to assist?
That sounds perfect! Curious what the gotchas are? I wasnโt able to dig into the UV channels to see the timestamps though my shader knowledge isnโt as extensive as Iโd like it to be.
I can't remember off the top of my head. I'll dig out some code tomorrow am and post it here.
So - I looked at the code and getting the timestamp of the stroke is trivial. It's just uv2's x component.
You can use that to group parts of the mesh into individual strokes.
And then use the vertexId to sequentially step through the stroke
Maybe set the alpha clip threshold based on whether (strokeId + vertexId) < counter ?
This doesn't immediately help you @nullreality but I've added a new feature to the #plugins-api-scripting branch. The ability to modify shader parameters from a script:
@animtree โ๏ธ
My plan was also to add a "stroke completion" parameter to all shaders so that you can animate the strokes drawing in over time.
There's a few tricky parts to this however:
1. All strokes of a given brush type on a layer share the same instanced material so they all change
2. Mapping a single 0 to 1 value for completion to strokes isn't simple because of the way timestamps are stored. For some brush types I could use UV0.x but they don't all use this in the same way
I could solve (1) by storing a strokeId in the mesh - this is also helps solve some other unrelated issues but comes at a cost. I think it's probably worth it.
I think (2) is solvable directly in the shader but I need to dig a bit deeper.
The shader changes should work nicely in the Unity SDK/Toolkit as well.
OK. More findings.
Timestamps are only available in the mesh in exports. If we're doing this in Open Brush itself we can either just use uv0.x (but this is the same for all strokes so you'd have to activate/deactivate batch subsets)
Or we could add more info into the mesh uv channels. If we added timestamps like in exports we might be able to infer stroke ids from this as well.
For the SDK/Toolkit - uv2 is used as follows
x contains the start timestamp
y contains the end
z contains the interpolated value
So an inverse lerp between these would give you a value of 0 to 1 for every vertex that indicated how far along the length it was.
This timestamp can also be used to (hopefully) uniquely determine a stroke. i.e. if you split the mesh every time uv0.x changes you'll end up with one mesh per stroke.
Here's an example shader for the Unity SDK that allows you to clip any stroke based on completion from either end:
@nullreality โ๏ธ
And here's an editor script to write a unique id to each stroke across all selected gameobjects:
This is perfect with the models I tested! I'm still extremely new to shaders but it does end up working with the StandardDoubleSided shader.
Going to keep at it and see if I can get it to look cleaner but honestly already really happy with this. I'm hoping this kind of combination isn't needed for all 45 brush types
Nope. It would be "one per shader" but as you can see from this spreadsheet - the top 6 shaders account for 53 brushes (including experimental)
https://docs.google.com/spreadsheets/d/12fHPnMNhpGGdR1mzFeCjXbg1Nv1PO1LZGcHwgp3S1Og/edit#gid=2118656876
@nullreality Also see https://discord.com/channels/783806589991780412/1134844284403720272
This is potentially a way to animate stroke completion inside Open Brush itself. I need to modify each shader to support this but I've done some tests and it works fine once you split strokes into separate gameobjects.
I've gone with using SV_VertexID - it's not quite as smooth as it tends to jump between triangles but it's good enough. UV coordinates weren't viable as they currently are applied in consistently. And the stroke timestamp is only set during export at the moment.
@andybak had an awesome graphics guru help out with the shaders! Got a large portion of them to work as intended for the experience we were designing. Thank you so much for your help on this!
I've made all the modified shader files we used in the experience available on GitHub, crediting you & the Open Brush Team, of course.
https://github.com/CultureVerse/open-brush-stroke-shaders
While this does work for the experience we were crafting, these scripts were most definitely thrown together in the shortest amount of time possible. So there is probably lots of cleanup & potential issues but it's a fantastic foundation.
These shaders work as intended using Unity 2021.3.4f1 with the built-in render pipeline.
GitHub
GitHub - CultureVerse/open-brush-stroke-shaders: All the shaders in...
All the shaders in Open Brush now with stroke controls! - GitHub - CultureVerse/open-brush-stroke-shaders: All the shaders in Open Brush now with stroke controls!
Wow this is awesome. Would it be easy to add the experimentals as well?