(Particles) Some targets do not anything, inluding comments before the version line
[platform/core/uifw/dali-demo.git] / examples / particles / shaders / particle-view.vert
1 #version 300 es
2 // Shader for billboarded particles, where the vertices of the particles
3 // are supplied as vec3 position (particle position) + vec2 sub-position.
4
5 precision lowp float;
6 uniform mat4 uModelView; // DALi
7 uniform mat4 uProjection; // DALi
8 uniform vec3 uSize; // DALi
9 uniform vec4 uColor; // DALi
10
11 uniform vec3 uSecondaryColor;
12 uniform vec2 uDepthRange; // x is zNear, y is 1.f / (zFar - zNear)
13 uniform float uTwinkleFrequency;
14 uniform float uTwinkleSizeScale;
15 uniform float uTwinkleOpacityWeight;
16 uniform float uTime;
17 uniform float uFocalLength;
18 uniform float uAperture;
19 uniform float uPopulation;
20
21 struct Scatter
22 {
23   float radiusSqr;
24   float amount;
25   vec3 ray;
26 };
27
28 const int SCATTER_VARS = 6; // Must match ParticleView::mScatterProps' size.
29 uniform Scatter uScatter[SCATTER_VARS];
30
31 const int POPULATION_GRANULARITY = 128;
32 uniform float uOrderLookUp[POPULATION_GRANULARITY];
33
34 in vec3 aPosition;
35 in float aSeed;
36 in vec4 aPath;
37 in vec2 aSubPosition;
38 in float aSize;
39
40 flat out float vDepth;
41 flat out float vFocalDistance;
42 out vec2 vUvUnit;
43 flat out float vOpacity;
44 flat out vec3 vColor; // ignore alpha
45
46 float bezier(vec3 control, float alpha)
47 {
48   return mix(mix(control.x, control.y, alpha), mix(control.y, control.z, alpha), alpha);
49 }
50
51 void main() {
52   // Get random order from the look-up table, based on particle ID.
53   int particleId = gl_VertexID / 6;
54   float order = uOrderLookUp[particleId & (POPULATION_GRANULARITY - 1)];
55
56   // Get twinkle scalar
57   float twinkle = sin(uTime * floor(uTwinkleFrequency * aSeed) + fract(aSeed * 1.17137));
58
59   // Add Motion
60   float s = sin(uTime + aSeed) * .5f + .5f;     // different phase for all
61   // NOTE: you'd think that taking the bezier() calls apart would save 4 mix() calls, since
62   // the mix()es (of xy / yz / zw / wx) are all calculated twice. It turns out that the MALI
63   // compiler is already doing this; leaving it as is for readability.
64   float bx0 = bezier(aPath.xyz, s);
65   float bx1 = bezier(aPath.zwx, s);
66   float by0 = bezier(aPath.yzw, s);
67   float by1 = bezier(aPath.wxy, s);
68   vec3 motion = vec3(mix(bx0, bx1, s), mix(by0, by1, s), 0.f);
69
70   // Model to view position
71   vec3 position3 = aPosition * uSize + motion;
72
73   vec4 position = uModelView * vec4(position3, 1.f);
74
75   // Add scatter - calculated in view space, using view ray
76   vec3 normalizedPos = position.xyz / uSize;
77   for (int i = 0; i < SCATTER_VARS; ++i)
78   {
79     vec2 scatterDist = (normalizedPos - uScatter[i].ray * dot(uScatter[i].ray, normalizedPos)).xy;
80
81     // NOTE: replacing the division with a multiplication (by inverse) oddly results in more instructions (MALI).
82     float scatter = max(0.f, uScatter[i].radiusSqr - dot(scatterDist, scatterDist)) *
83       uScatter[i].amount / aSize;
84     position.xy += scatter * normalize(scatterDist) * uSize.xy;
85   }
86
87   // Calculate normalised depth and distance from focal plane
88   float depth = (position.z - uDepthRange.x) * uDepthRange.y;
89   vDepth = depth;
90
91   float focalDist = (uFocalLength - depth) * uAperture;
92   focalDist *= focalDist;
93   vFocalDistance = max(focalDist, 1e-6f);       // NOTE: was clamp(..., 1.f); side effect: out of focus particles get squashed at higher aperture values.
94
95   // Calculate expiring scale - for size and opacity.
96   float expiringScale = smoothstep(order + 1.f, order, uPopulation);
97
98   // Calculate billboard position and size
99   vec2 subPosition = aSubPosition * aSize *
100     (1.f + twinkle * aSeed * uTwinkleSizeScale) *
101     expiringScale;
102
103   // Insist on hacking the size? Do it here...
104   float sizeHack = depth + .5f;
105   // NOTE: sizeHack *= sizeHack looked slightly better.
106   subPosition *= sizeHack;
107
108   vec3 subPositionView = vec3(subPosition, 0.);
109
110   // Add billboards to view position.
111   position += vec4(subPositionView, 0.f);
112
113   // subPosition doubles as normalized (-1..1) UV.
114   vUvUnit = aSubPosition;
115
116   // Vary opacity (actor alpha) by time as well as expiring scale.
117   vOpacity = uColor.a * expiringScale *
118     (1.0f + aSeed + twinkle * uTwinkleOpacityWeight) / (2.0f + uTwinkleOpacityWeight);
119
120   // Randomize RGB using seed.
121   vec3 mixColor = vec3(fract(aSeed), fract(aSeed * 16.f), fract(aSeed * 256.f));
122   vColor = mix(uColor.rgb, uSecondaryColor, mixColor);
123
124   gl_Position = uProjection * position;
125 }