BlendAdd

At first I searched for a way to implement the Blend Mode mentioned in the talk. As it turns out, it is very easy to do and should be one of the default blend modes available in every larger engine.

1

Blend One OneMinusSrcAlpha

Per-Particle Offset

After having the blend mode done in a custom Unity shader I went on to search for a way to realize the per-particle UV offset that was also mentioned in the GDC talk. Even though Unity has no way of doing per-particle UV offsets with the default particle system, my goal was, to find a solution that works without 3rd party plugins and using solely the default particles.

This workaroung for this problem is absolutely not the best one and I do not recommend using it for anything else than experimentation!

The only way I came up with, without having access to the Unity engine source code and using only the default particle system, was a simple script and a custom shader.

PerParticleOffset.cs

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

usingUnityEngine;

usingSystem.Collections;

publicclassPerParticleOffset:MonoBehaviour{

ParticleSystem psys;

ParticleSystem.Particle[]particles_S;

// Use this for initialization

voidStart(){

psys=gameObject.GetComponent<ParticleSystem>();

particles_S=newParticleSystem.Particle[psys.maxParticles];

}

// Update is called once per frame

voidLateUpdate(){

intpartNUM=psys.GetParticles(particles_S);

for(inti=0;i<partNUM;i++)

{

//Calculate the current lifetime of the particle.

floatpLifeTime=particles_S[i].startLifetime-particles_S[i].lifetime;

floatpRealLifeTime=1/particles_S[i].startLifetime*pLifeTime;

Color32 newcolor=newColor32(255,255,255,255);

//R is used for gradient over lifetime.

newcolor.r=(byte)(pRealLifeTime*255);

//G maybe used for color by speed.

newcolor.g=(byte)(255);

//B is used for random uv offset in x.

if(particles_S[i].startColor.b==(byte)255)

{

newcolor.b=(byte)(Random.Range(0,254));

}

else

{

newcolor.b=particles_S[i].startColor.b;

}

//A is used for random uv offset in y.

if(particles_S[i].startColor.a==(byte)255)

{

newcolor.a=(byte)(Random.Range(0,254));

}

else

{

newcolor.a=particles_S[i].startColor.a;

}

particles_S[i].startColor=newcolor;

}

psys.SetParticles(particles_S,partNUM);

}

}

It uses the Blue and Alpha channel of the initial color to offset along U and V for each particle individually. This on the other hand makes the particle Color over Lifetime and Color by Speed unusable as anything else than values of 1 would change the offsets. To compensate this I created the shader with two additional color parameters. One for a lifetime of 0 and one for a lifetime of 1 and used the Red channel of the initial color as lifetime input, to have at least a linear transition between a start and end color. The same could be done for Color by Speed which would use the Green channel of the initial color and another two color parameters in the shader.