Any idea on what I may be doing wrong? My particles are neither clipped nor coloured from the generated clip mask Texture2D, but it works if I use a pre-rendered Texture2D.
My guess is that copying from RenderTexture to Texture2D doesn’t actually get the pixel data onto the CPU, which is where the particle system needs it. Probably you just end up with GPU data. Might need to call GetPixels or something to read it back into the cpu cache of the Texture2D. Google may be able to help with the specifics of how to do this - sorry I’m not sure.
(code monkey, the copy is because the particle system can’t use render textures, due to wanting the data on the cpu)
The efficient solution here is to use Visual Effect Graph, if you can, because then everything will be happening on the GPU with no need to copy back to the CPU.
Actually, I do already have ReadPixels in my code as well (switching based on a RTToTexture support check), but ended up with the same results (and issue) when I was testing to see if that made a difference.
Speed won’t be an issue in my use-case (well, hasn’t been so far), and I can use a much smaller texture if that would help. I’m trying to dynamically control the mask and was hoping to avoid something like a hacked-in flipbook, as that would force me to pre-render the mask animation rather than a CustomRenderTexture shader.
Unfortunately, this project is in the built-in pipeline, so VFX Graph is a no-go for me.
I’m willing to sacrifice some performance to keep this within the context of Shuriken.
If not, as a last resort, I’ll move the demo to URP just to see what’s possible.
By the way, this seems like a “bug” of sorts if there’s no warning to indicate why things aren’t working, despite everything in the editor being okay.
If you were able to submit a bug report with an example project, mentioning me/this thread, QA will process it and make sure it reaches me. Then I could debug it to be sure what’s gone wrong.
To be sure, you’re doing this?
It would also be interesting to call GetPixels and see if that gives you what you expect…
I can see the mask change as I adjust the custom render texture material, so it’s working on that front.
— UPDATE (while I was writing this post, before even submitting…) —
It’s working now!
I did some more tests, and moving the shape.texture assign to after the texture.Apply() every frame resolved the issue. Note in the screencap above I correctly assigned it after creating a new texture, but this was once in Start.
So in the editor, the texture still updated on the particle system shape module whenever I double-clicked it, indicating it was updating as expected, but internally in the PS I’m assuming it’s not actually checking for the updated data.
Here’s a video of the above code to show what I mean.
You’ll see the tiny red texture preview in the Shape module’s Texture slot update as I move the slider, which I confirm by clicking through. The method being used (CopyTexture/ReadPixels) shows in the console. Until I reassign every frame, ReadPixels doesn’t work.
@richardkettlewell , I’ll make that bug report with a reference to this thread as you suggested. Thanks again.
For reference, here’s the effect I’m trying to improve using this technique in BiRP. Right now the particles won’t clip in the areas where there’s no opacity. Using a custom render texture I can force them to emit correctly as the effect would scroll using a slider.
Summary: Graphics.CopyTexture doesn’t work, but Texture.ReadPixels does so long as I reassign the texture to the shape module after every texture.Apply(). If this is the expected behaviour, it’s not clear because the editor shows the texture updating.
I will take a look at this when the bug report reaches me.
My gut feeling is that the order of the assign/Apply shouldn’t matter (Ie you found a bug) Maybe we cache the pixel data when the texture is assigned. So it misses the changes done by the Apply. but I wonder if there is a way for us to detect that the cached pixel data is dirty. In theory you should only need to assign once, and then any calls to Apply with new data should be picked up. Whether there is a way for me to detect this… I’m not sure but I’ll look into it!
Good news - I was able to fix this. It’ll probably only go into Unity 2023 though, as it’s a minor issue and not a regression.
(Please let me know if that’s a problem and I can try to get backports)