Passing extra vertex data to a shader

In UDK there is a thing called “Dynamic Parameter” for particles which acts as a second
vertex color: It’s generated by the particle system and passed down to the vertex and fragment
shaders where it can be used freely. Can I do something similar in Unity? I’m generating a mesh
with this extra vertex data but I’m not sure how to pass it to a custom shader. ShaderLab’s
appdata_full seems to have a fixed set of parameters.

You can define whatever structure you need but you are limited to what you can pass in via the Mesh class which is vertex position, 2 texture coordinates and 1 set of vertex colors.

Would tangents work?

So I must use the existing dataset… As I see it these are the options:

  • Encode two float values in each vertex color channel. (Lost precision in both vertex color and dynamic parameter data.)
  • Encode two float values in each UV2 coordinate. (Lost dyna param precision and no second UV.)
  • Store data in vertex tangent. (Shader has to calculate tangents if necessary.)

I guess I can implement all of them and use the one best fit to a given situation.

Thanks guys!

You shouldn’t lose precision with UV2, just you’re down to 2 channels.

Indeed, #2 is either lossless RG or lossy RGBA or lossy UV2 and lossy RG… and I thought I had no options… :slight_smile:
Btw, it’s a shame that the UVs arrive at the shader as float4’s with the last two components left unused.

I am trying to pass data to a shader using either the normal or tangent but it seems like Unity is altering these values before I get to read them in the Shader. Is there a way to get this data into the Shader but to not have Unity somehow alters these values?

1 Like

Are you generating the geometry yourself or trying to change an imported asset?
My use case was creating a mesh from scratch and I had no trouble setting normals
and tangents to anything I wanted.

I discovered that Unity alters the values in the normal / tangent channel when Dynamic Batching is enabled. If I disable dynamic batching, then my values are not altered.

Right now my Shader doesn’t use normal or tangents (yet) so I was hoping to be able to pass some value to the shader inside of those and then strip that value inside and put that back to zero.

In addition, since the mesh I create is only (X, Y), I was hoping that alternatively I could use Z and then similarly get that value in the shader and then reset it to zero but again Unity alters this value. I realize in the case of this Z, my Z inside the script is zero but that is in local space vs. that vertex.z inside the shader is now in worldspace but even (I think) I account for that, Unity seems to be altering the values (i suspect this is also related to dynamic batching).

Maybe I am doing something wrong.

1 Like

I am looking for a way to get exactly this: the [dynamic parameters ](http://udn.epicgames.com/Three/ParticleSystemReference.html#Parameter Modules)of the UDK Cascade (particle) editor inside Unity’s Shuriken ParticleSystem.
How on earth can I get to the core of a particle - its quad mesh and inject additional data?
Is that even possible? Or is this stuff hidden and locked away?
Can we expand the Shuriken editor with custom modules that control the additional data with curves/constants/randoms?

The thread above seems to have nothing more to do with Cascade than the initial idea of adding a secondary vertex color set to an arbitrary mesh - not to particles in the first place as the term “dynamic parameters” implies.

So the question still stands: what can be done in terms of mimicing UDK Cascade’s dynamic Parameters inside Shuriken?

edit:
This question apparantly pops up from time to time.

edit2:
Since the particle quads seem to be hidden inside the core I am going another route now. I use the individual channels of the color property to drive the information needed inside the custom particle shader. And I use one channel to make a lookup inside a color gradient texture.
While this is not ideal it should work. Sadly Shuriken offers no method to modifiy the individual color channels via curves. That would be an awesome addition - as would be a set of 4 additional dynamic parameters.

I know this is a necro. But it seems stupid to state exactly this in a new thread. I’ve hit the same road block. Everyone says that you can use the tangents channel. Yet, my values go out of wack. Curiously, the shader works in the scene view, but has awful artifacts in the game view.

Turning off batching is simply not an option. I can’t force my customers to disable such important features.

Am I missing something? Is it just impossible until Unity 5.0 ships?

In order for objects to batch, the need to have uniform scale. So you can tweak the scale (slighly) in order to break batching and I believe that may result in your values passing in Tangent channel to not be modified by Unity.

Would be nice to have a new property on the renderer like renderer.isBatching = false; That way we could specify which mesh are to be excluded instead of having to resort to funky stuff.

I am certainly looking forward to having more per vertex streams in 5.0.

1 Like

Thanks for the little hack. I’ll check it out.

Can anyone explain why the data gets mangled in the dynamic batching case? I really want to put some data in the tangent but I just can’t. I was packing data into floats, but with tangent and normal I can’t even use regular floats. It’s like those data slots are basically useless for me. Incredibly frustrating.

bump!

same issue. how to reliably prevent unity from updating the tangents/normals?

As of Unity 5.3, the UV channels can be a float2, float3, or float4 type, allowing you to pack far more information into them than in previous versions.

3 Likes

I had not notices the changes to the Mesh.SetUVs() function. I wish it made it possible to also use something like Mesh.SetUVs(int channel, Vector4[ ] uvs);

There might be something like this for particle systems in 5.5, see here: Unity Blog . Look for Vertex Streams in the comments. This will make me happy! \o/

It’d be great to just completely configure the whole structure, and mark various streams as being normalised or saturated or whatever you need by the time the data hits the shader.

3 Likes

A couple of pointers that may resolve some of the issues you guys are facing.

Firstly, dynamic batching combines mesh into a “super” mesh where any previous object space data (eg vertex) is lost as it’s translated into world space based on the sum of all the other meshes it combines with. This is particularly noticeable when batching things like billboards. If you wish to disable batching however, there’s no need for fancy workarounds such as offset scaling. This can be achieved with the DisableBatching tag.

Tags{ "DisableBatching"="True" }

Secondly, for those working with older versions of Unity (<5) and targeting IOS, normals and tangents may be automatically normalized. To prevent this you’ll need to add the following pragma to your CG block.

#pragma glsl_no_auto_normalization

And lastly, by default Unity is set to automatically compress vertex data. This optimization can adjusted under the “Edit > Project Settings > Player > Other Settings > Vertex Compression” menu.

2 Likes