Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Custom Particle Data in Shader

Discussion in '5.5 Beta' started by Superxwolf, Sep 5, 2016.

  1. Superxwolf

    Superxwolf

    Joined:
    Nov 21, 2014
    Posts:
    12
    Accessing custom particle data in shaders is one of the advertised features of the particle system improvements, but it's only been mentioned, I haven't been able to find an example or explanation on how to. Can anyone provide a simple shader using custom particle data?

    A bit of a side question in C#, does GetCustomParticleData return the list in the same order for particles in GetParticles?
     
  2. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    To answer the side question: yes, the order is the same.

    I dont have a great example handy, but here is a shader that uses custom data to do some custom flipbook stuff. hope it helps. i can post a better example later in the week but im not in the office right now :)

    Code (CSharp):
    1. Shader "VertexStreams/Custom 1" {
    2. Properties {
    3.     _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    4.     _MainTex ("Particle Texture", 2D) = "white" {}
    5.     _OffsetValue("Offset Value", float ) = 1
    6. }
    7.  
    8. Category {
    9.     Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    10.     Blend SrcAlpha OneMinusSrcAlpha
    11.     ColorMask RGB
    12.     Cull Off Lighting Off ZWrite Off
    13.     //#pragma target 5.0
    14.  
    15.     SubShader {
    16.         Pass {
    17.        
    18.             CGPROGRAM
    19.             #pragma vertex vert
    20.             #pragma fragment frag
    21.             #pragma multi_compile_particles
    22.             #pragma multi_compile_fog
    23.            
    24.             #include "UnityCG.cginc"
    25.  
    26.             sampler2D _MainTex;
    27.             fixed4 _TintColor;
    28.             float _OffsetValue;
    29.            
    30.             struct appdata_t {
    31.                 float4 vertex : POSITION;
    32.                 float4 normal : NORMAL;
    33.                 float4 tangent : TANGENT;
    34.                 fixed4 color : COLOR;
    35.                 float2 texcoord : TEXCOORD0;
    36.                 float4 customData : TEXCOORD1;
    37.             };
    38.  
    39.             struct v2f {
    40.                 float4 vertex : SV_POSITION;
    41.                 fixed4 color : COLOR;
    42.                 float2 texcoord : TEXCOORD0;
    43.                 float4 customData : TEXCOORD1;
    44.                 UNITY_FOG_COORDS(2)
    45.             };
    46.            
    47.             float4 _MainTex_ST;
    48.  
    49.             v2f vert (appdata_t v)
    50.             {
    51.                 v2f o;
    52.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    53.                 o.vertex *= v.customData.x;
    54.                 o.color = v.color;
    55.                 o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
    56.                 o.texcoord.x += v.customData.y;
    57.                 o.customData = v.customData;
    58.                 UNITY_TRANSFER_FOG(o,o.vertex);
    59.  
    60.                 return o;
    61.             }
    62.            
    63.             fixed4 frag (v2f i) : SV_Target
    64.             {
    65.                 fixed4 col = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
    66.                 UNITY_APPLY_FOG(i.fogCoord, col);
    67.                 fixed4 col2 = fixed4(i.customData.x, i.customData.y, i.customData.z, 1);
    68.                
    69.                 return col;
    70.             }
    71.             ENDCG
    72.         }
    73.     }  
    74. }
    75. }
    76.  
     
  3. Superxwolf

    Superxwolf

    Joined:
    Nov 21, 2014
    Posts:
    12
    Thanks for the shader!
    This works great for billboard, however I am using mesh particles, sorry for not stating that before. I noticed you can only modify vertex streams for billboards, does that mean custom data for mesh particles is unsupported?
     
  4. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Ah, yes, currently custom vertex streams for mesh particles are unsupported.
     
  5. Superxwolf

    Superxwolf

    Joined:
    Nov 21, 2014
    Posts:
    12
    Thank you for the support, wanted to test GPU Instancing vs mesh particles on a project of mine, but seems like GPU Instancing is the way to go.
     
  6. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    We are working on integrating the GPU instancing with mesh particle rendering, but it's not ready yet :)
     
  7. Superxwolf

    Superxwolf

    Joined:
    Nov 21, 2014
    Posts:
    12
    That's fantastic news, can't wait to get my hands on that!
     
    richardkettlewell likes this.
  8. Jean-Moreno

    Jean-Moreno

    Joined:
    Jul 23, 2012
    Posts:
    590
    Speaking of custom data, if I understood correctly currently we can only pass that data from a script using SetCustomParticleData.

    Are there any plans to add "custom data" modules?
    So that we can control the custom data like any other vertex-based data through the UI. It would also allow more flexbility than a script-based approach I think.
    Here's a small mockup to illustrate the idea:
    Unity55-Particle-Custom-Data-Modules.png
    (the vector type would also have a W curve here)

    Also would like to know the reason behind "no vertex streams for mesh particles", is it technical? Are you hoping to eventually support it?

    Anyway, love the VFX-related improvements lately, thanks for that! :)
     
  9. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Hey,

    We don't currently have any plans to support the custom data via the UI, though it's an interesting idea, so I will add it to our roadmap, thanks.

    Regarding the mesh particle thing - it would be very expensive to add to mesh particles, due to the way we build mesh particle vertex data all on the CPU. However, there is no technical limitation to adding it, so perhaps we will expose it and then it is up to the user's if their performance budget allows using it ;)

    We are also working on adding GPU instancing support to the mesh particles at the moment. It would be very easy to and efficient to expose the custom vertex stream data to the GPU instancing implementation.

    Thanks for the feedback!
     
  10. pnyx

    pnyx

    Joined:
    Apr 13, 2014
    Posts:
    8
    this is whats missing to make the feature really usable I think.
    Using scripts to add your own data is all fine and good. But it can not be properly tweaked or previewed ( not that i know of anyway) without starting the game. And while running the game you can't really tweak your parameters because they are just lost...
    I think anyone working with vfx would appreciate that feature being bumped to the very top of the roadmap :) I know I would.
    Great work on the improvements on the whole though, love the trails.
     
    richardkettlewell likes this.
  11. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Out of curiosity, what kind of custom data would you imagine setting up via the Inspector? Any kind of example?
    I ask because we imagined it being a mechanism to assign dynamic game-logic-based values to particles, i.e. the kind of data that is only known from scripts during gameplay.

    Thanks!
     
  12. Jean-Moreno

    Jean-Moreno

    Joined:
    Jul 23, 2012
    Posts:
    590
    For me it'd mainly be to control custom shaders arbitrarily.

    For example a particle shader that has an erosion value (which smoothsteps() based on the texture alpha), and I want to control that value precisely.
    The current workaround would be to either use vertex colors (but then you lose the per-particle color ability for at least one channel), or lifetime in 5.5 but then the value would be linearly tied to the particle lifetime.

    Another basic usage would be to have an easy interface to get random values per particle (with a "random between two constant" property for example).
    Although this might be doable with the script interface? I haven't tested it in-depth yet, but I saw you have to supply a List<Vector4>, so what happens to newly created particles if they are outside this list's range? Does it get a zero Vector4 or it cycles back to the start of the list?

    Also updating that list every frame sounds way slower to me than the ParticleSystem's interface that automatically updates values based on curves and lifetimes for example. But maybe that's my imagination?
     
  13. GWiebe

    GWiebe

    Joined:
    Feb 25, 2015
    Posts:
    3
    As a VFX artist, I agree with Jean-Moreno. His recommended custom data interface modules was the behavior I was expecting when you announced the feature. I was sad when I found out that this is not in fact the case. It would be way more useful for VFX artists if you implement Jean's suggestion, as we otherwise need to set up arbitrary scripts per fx. Myself and many great VFX artists that I work with use unity daily, but cant code at all. A visual interface embedded in the particle system would be indispensable for us.
     
    Last edited: Sep 18, 2016
    chrismarch and JonSWEDEN like this.
  14. Jesus

    Jesus

    Joined:
    Jul 12, 2010
    Posts:
    501
    Obviously that's one clever way to use it, but for the most part particle Jean and Weibe hit the nail on the head.

    I've previously used vertex colors as a way to pass a value to the material. Because you can change color based on (whatever) and set it to some random value nicely, it's sort of an ideal way to get some information to a shader. Obviously, that means using vertex colors and fade-in/fade-out normally then goes out the window.

    If you guys just copy all the [color by....] sections and just cross out color and replace it with [custom value 1 (or 2)] that'd probably be perfect.
     
  15. Ryan-Gatts

    Ryan-Gatts

    Joined:
    Sep 27, 2012
    Posts:
    54
    I strongly agree with Jean-Moreno, GWiebe, and Jesus. I currently control most of the dynamic properties of my particles by hijacking particle color. This is a problem for two reason:

    1. It's unintuitive if I hand the effect off to anyone else. I regularly use the Red channel as a random value in shaders to randomize UV offsets, Green to control heat values in blackbody shaders, Blue to control the strength of UV warp textures, or Alpha to control the minClip value in an alpha erosion shader -- just to name a few. It makes my particle color values hard to edit and only barely human-readable (for an actual example/use case see the FXVille Blood FX Pack that I made, and its associated documentation).

    2. Particle Color in unity seems to be tracked in some bit depth lower than float (I suspect it's 8 bit), because I often see what looks like 255 discrete steps between 0 and 1 values. This stops me from using my techniques on longer-lived particles, since it would make the steps more obvious. In my testing so far, custom data seems to pass 16 bit floats, which is super useful for me!

    It would be really nice to have a UI interface like Jean-Moreno mocked up (excepting that the vector example should have a W graph too, since it's for authoring a float4). I love unity's curve editor and it would be a really pleasant way to author data for particle shaders. I use this kind of interface all the time when I'm working in Unreal (but their curve editor is terrible).

    When I read that custom particle data was on its way, this is the implementation I was excited for.
     
  16. varfare

    varfare

    Joined:
    Feb 12, 2013
    Posts:
    227
    I agree with the predecessors. Without a dedicated module the whole idea of sending custom particle data will be very limited and rarely useful. What we, VFX artist, tent to do is we use custom shader data to additionally animate particles over its lifetime. For example, for a fire shader it is very common to have additional parameter which distorts the UV. The strength of the distortion needs to be precisely defined over particle's/emitter's lifetime (otherwise you cannot achieve a proper visual quality). For explosion shader, we usually simulate smoke and fire and save them into separate textures. Then, you can create a shader which combines both textures taking smoke as a diffuse and fire as an emissive. Via custom parameter we set fire's color, intensity (preferably in high dynamic range), you can then use "color over lifetime" module to set smoke's opacity&color. These are just some common uses. There are a lot more examples. If you need additional information on the use cases, plase let me know - I will provide you with all the information that I've got.
    VFX in general are very specific and they require a lot of precise tweaking.

    If you need some direct references you should definitely dig into Unreal Engine so called "dynamic parameter" feature built-in into Cascade. Essentially, they have a special dedicated module which allows you to set custom shader data and drive it over particle's lifetime, set the value once or drive it over emitter's lifetime. I know that you've probably heard a lot of "unreal this, unreal that" but "dynamic parameter" approach is the best I have even encountered and fits Unity's semi-modular approach.
     
  17. Jean-Moreno

    Jean-Moreno

    Joined:
    Jul 23, 2012
    Posts:
    590
    @richardkettlewell Any news on this? Is it being considered or at least discussed internally?
    I'm sure we can find lots more of other VFX Artists who would be very interested in this!
     
  18. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Hey, yes, sorry been on vacation ;) Thanks for the feedback, it's good to know that this would be useful. We will add it to our roadmap!

    Right now, you can do a workaround by adding an AnimationCurve to a script, and setting the custom particle data based on the particle age and by evaluating that curve yourself.

    I know this approach isn't as good as a native implementation where we provide the UI, and support all the particle curve modes, but maybe it's better than nothing, depending on your use case :)
     
    Ryan-Gatts and varfare like this.
  19. Jean-Moreno

    Jean-Moreno

    Joined:
    Jul 23, 2012
    Posts:
    590
    Cool, thanks for the heads up!

    Just curious, how would you expect this workaround to perform compared to a native implementation?
    It sounds really slow having to get each particle lifetime to sample the curve every frame.
     
  20. Alesk

    Alesk

    Joined:
    Jul 15, 2010
    Posts:
    339
    Hi,

    Welcome back Richard ;)

    I agree with all previous suggestions about the UI for custom data, because for now assigning custom data in a vertex stream is not really optimal :

    When a particle is emited, its custom data value is always Vector4(0,0,0,0).
    So we have to identify somehow (by script) which particles were emitted since the last update, and then set the custom values for these particles.
    In this configuration the custom values can only be processed one frame after the particles birth, I'm not sure of it, but this can be a problem in some cases.
    Also, each time, the full array of custom data has to be retrieved, modified, and set back to the stream, all by script.

    I don't know how difficult it is, but in addition to the UI for custom vertex stream, would it be possible to add a native function to the Monobehavior class, something like "OnParticleBirth(Particle[] particles)", where programmers could define some arbitrary values to all new particles (or tweak the existing ones).
     
  21. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Yeah, very slow by comparison. Probably something crazy like 2 orders of magnitude! But if you only have a few particles, it could be useful.

    I agree this would be useful. I'll add it to our roadmap. It would probably be a new function.. GetParticlesBornThisFrame, or something. That's admittedly not a very catchy name ;)
     
  22. Ryan-Gatts

    Ryan-Gatts

    Joined:
    Sep 27, 2012
    Posts:
    54
    There's a cool feature in the material editor for Insomniac's Luna Engine. They have a "random per particle" value and a "random per instance" value that are both very useful in writing vfx shaders. Both values are random 0-1 values. Particle Random is unique for each particle and is consistent over the life of the particle (very useful for randomizing UV coordinates in particle noise textures). Instance Random is unique for each actor (so all particles of an emitter would get the same value); this is also very useful for randomizing static mesh effects, and I used it extensively when making fire in Feral Rites.

    These are achievable by other means in Unity, so they're obviously low priority, but I have found them quite useful in the past. (At the moment I'm on an Unreal 3 project and I've never missed Unity more.)
     
    richardkettlewell and mh114 like this.
  23. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    5.5 will soon be getting a new custom stream called Random, which has 3 "random-per-particle" values, plus one random value that changes as a particle simulates. So that last one would be useful for any kind of flickering (maybe multiplied into the size, color, etc).

    I'd not thought about "random-per-instance" so much.. I guess this is quite easy to do via script if you have the programming knowledge. And if we are talking about users who are capable of writing custom shaders, I guess those same users will be comfortable enough with setting up some script to do a SetFloat on the system with a random number generated from the randomSeed property.
     
    Last edited: Oct 14, 2016
    Jean-Moreno likes this.
  24. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Hi guys, just a quick post to let you know that we are developing a UI for the custom data streams. Here is what we have so far:

     
  25. Jean-Moreno

    Jean-Moreno

    Joined:
    Jul 23, 2012
    Posts:
    590
    Heh, I didn't even think about having a separate curve type for each component at first.
    This looks awesome! And thanks for the reactivity! :)
    I'm guessing this would ship in at least 5.6?
     
  26. varfare

    varfare

    Joined:
    Feb 12, 2013
    Posts:
    227
    Yea, that's what I'm talking about! My Unity VFX dreams came true!
     
  27. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,281
    Glad you like it! Yeah, 5.6 should be realistic, because we're past the cutoff for accepting anything new to 5.5 now.. it's bugfixes only.

    Another interesting addition here, is, because the custom data streams are floats, and not bytes, I'm also trying to add support for a HDR Gradient Editor, so you can define HDR colors here.

    We'd love to enable HDR for all particle color curves, but it's tricky for a few reasons:
    * Performance
    * Extra memory requirements
    * Requires a texcoord stream instead of the 8 bit color vertex input stream, which would prevent it working with the existing shaders

    So this feels like an easy way to give you HDR colors in custom situations where you want them, without imposing their downsides on the whole system.
     
  28. Ryan-Gatts

    Ryan-Gatts

    Joined:
    Sep 27, 2012
    Posts:
    54
    That's too bad about the hdr color, but I understand. Really, the implementation of a frontend for custom data streams will make this much less necessary, since I can fit my brightness value in the data stream. People are much less sensitive to changes in hue than changes in brightness, so it's fine to keep the hue/saturation-relevant data in 8-bit rgb and then use a higher precision number to control hdr brightness (and with a nice curve interface no less!).

    I'm really excited for this addition/change. I've always loved working in unity, and this will fill one of the few remaining gaps in Unity's VFX tools (especially when it's integrated into shaderforge). Thanks for your hard work!
     
    richardkettlewell likes this.
  29. Phantom_X

    Phantom_X

    Joined:
    Jul 11, 2013
    Posts:
    313
    Nice to see to progress on this, exactly what I am looking for!
     
    Ryan-Gatts and richardkettlewell like this.