OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
update.cs
Go to the documentation of this file.
1 #version 310 es
2 
3 /* Copyright (c) 2014-2017, ARM Limited and Contributors
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 layout (local_size_x = 64) in;
24 layout (std140, binding = 0) buffer SpawnBuffer {
25  vec4 SpawnInfo[];
26 };
27 layout (std140, binding = 1) buffer PositionBuffer {
28  vec4 Position[];
29 };
30 
31 uniform float dt;
32 uniform float time;
37 const vec2 eps = vec2(0.002, 0.0);
38 const vec3 dx = eps.xyy;
39 const vec3 dy = eps.yxy;
40 const vec3 dz = eps.yyx;
41 const float regionLength = 2.0;
42 
43 //#define HIGHQ_NOISE
44 #define LOWQ_NOISE
45 
46 // Forward declarations
47 void Simplex3D_GetCornerVectors(vec3 P, out vec3 Pi, out vec3 Pi_1, out vec3 Pi_2, out vec4 v1234_x, out vec4 v1234_y, out vec4 v1234_z);
48 void FAST32_hash_3D(vec3 gridcell, vec3 v2_mask, out vec4 hash_0, out vec4 hash_1, out vec4 hash_2);
50 
51 float ramp(float r)
52 {
53  r = clamp(r, -1.0, 1.0);
54  float r2 = r * r;
55  return r * (1.875 - 1.25 * r2 + 0.375 * r2 * r2);
56 }
57 
58 // Source potential function
59 float phi(vec3 p)
60 {
61  vec3 q = p - spherePos;
62  return (3.1415) * log(dot(q, q) + eps.x);
63 }
64 
65 // The analytic gradient of the above function
67 {
68  vec3 q = p - spherePos;
69  float m = (2.0 * 3.1415) / (dot(q, q) + eps.x);
70  return m * q;
71 }
72 
73 void main()
74 {
76  vec4 status = Position[index];
77  float lifetime = status.w;
78  if (lifetime < 0.0)
79  {
80  // Respawn particle (note that lifetime is stored in w-component)
81  Position[index] = SpawnInfo[index];
82  }
83  else
84  {
85  // Update particle
86  vec3 p = status.xyz;
87 
88  // This uses a different noise sample for each axis
89  // The curl is correct in this case
90  #ifdef HIGHQ_NOISE
91  vec3 scale = vec3(2.0, 4.2, 3.5);
92  vec3 q1 = scale.x * p + seed.xyx + vec3(time) * 0.05;
93  vec3 q2 = scale.y * p + seed.xyz + vec3(time) * 0.07;
94  vec3 q3 = scale.z * p + seed.zxy + vec3(time) * 0.09;
95  vec3 dN1 = SimplexPerlin3D_Deriv(q1).xyz;
96  vec3 dN2 = SimplexPerlin3D_Deriv(q2).xyz;
97  vec3 dN3 = SimplexPerlin3D_Deriv(q3).xyz;
98 
99  // Calculate the curl of the noise field
100  vec3 v1 = vec3(dN3.y - dN2.z, dN1.z - dN3.x, dN2.x - dN1.y);
101  #endif
102 
103  // Approximates the field with a single component
104  // Not mathematically correct, but it still looks decent
105  // We sum a low-frequency and a high-frequency noise pattern
106  // to get a more interesting result
107  #ifdef LOWQ_NOISE
108  vec3 scale = vec3(2.0, 2.01, 2.05);
109  vec3 q = scale * p + seed + vec3(time) * vec3(0.05, 0.07, 0.09);
110  vec3 dN = SimplexPerlin3D_Deriv(q).xyz + 0.7 * SimplexPerlin3D_Deriv(q * 5.01).xyz;
111  vec3 v1 = vec3(dN.y - dN.z, dN.z - dN.x, dN.x - dN.y);
112  #endif
113 
114  // Calculate the gradient of the potential function
115  vec3 v2 = gradphi(p);
116 
117  // We introduce turbulence after the particle has lived for a while
118  float a1 = 1.0 - 0.6 * clamp(0.6 * lifetime / particleLifetime, 0.0, 1.0);
119 
120  // The particle is less affected by the sphere when it's far away
121  float a2 = 1.0 - ramp(length(p - spherePos) / regionLength);
122 
123  // Superposition still gives an incompressible field
124  vec3 v = 0.2 * a1 * v1 + 0.14 * a2 * v2;
125 
126  // Euler integration
127  p += v * dt;
128  Position[index] = vec4(p, status.w - dt);
129  }
130 }
131 
132 // The following code implements functions for calculating
133 // analytic derivatives of simplex noise.
134 // Author: Brian Sharpe
135 // Homepage: http://briansharpe.wordpress.com
136 // Code: https://github.com/BrianSharpe/GPU-Noise-Lib/blob/master/gpu_noise_lib.glsl
137 //
138 // The code also borrows from the work of Stefan Gustavson and Ian McEwan at
139 // http://github.com/ashima/webgl-noise
140 void Simplex3D_GetCornerVectors(vec3 P, // input point
141  out vec3 Pi, // integer grid index for the origin
142  out vec3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )
143  out vec3 Pi_2,
144  out vec4 v1234_x, // vectors from the 4 corners to the intput point
145  out vec4 v1234_y,
146  out vec4 v1234_z)
147 {
148  // Simplex math from Stefan Gustavson's and Ian McEwan's work at...
149  // http://github.com/ashima/webgl-noise
150 
151  // simplex math constants
152  const float SKEWFACTOR = 1.0/3.0;
153  const float UNSKEWFACTOR = 1.0/6.0;
154  const float SIMPLEX_CORNER_POS = 0.5;
155  const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.
156 
157  P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )
158 
159  // Find the vectors to the corners of our simplex pyramid
160  Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );
161  vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );
162  vec3 g = step(x0.yzx, x0.xyz);
163  vec3 l = 1.0 - g;
164  Pi_1 = min( g.xyz, l.zxy );
165  Pi_2 = max( g.xyz, l.zxy );
166  vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
167  vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
168  vec3 x3 = x0 - SIMPLEX_CORNER_POS;
169 
170  // pack them into a parallel-friendly arrangement
171  v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );
172  v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );
173  v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );
174 }
175 
176 void FAST32_hash_3D(vec3 gridcell,
177  vec3 v1_mask, // user definable v1 and v2. ( 0's and 1's )
178  vec3 v2_mask,
179  out vec4 hash_0,
180  out vec4 hash_1,
181  out vec4 hash_2) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable
182 {
183  // gridcell is assumed to be an integer coordinate
184 
185  // TODO: these constants need tweaked to find the best possible noise.
186  // probably requires some kind of brute force computational searching or something....
187  const vec2 OFFSET = vec2( 50.0, 161.0 );
188  const float DOMAIN = 69.0;
189  const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
190  const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
191 
192  // truncate the domain
193  gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
194  vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
195 
196  // compute x*x*y*y for the 4 corners
197  vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
198  P *= P;
199  vec4 V1xy_V2xy = mix( P.xyxy, P.zwzw, vec4( v1_mask.xy, v2_mask.xy ) ); // apply mask for v1 and v2
200  P = vec4( P.x, V1xy_V2xy.xz, P.z ) * vec4( P.y, V1xy_V2xy.yw, P.w );
201 
202  // get the lowz and highz mods
203  vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
204  vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
205 
206  // apply mask for v1 and v2 mod values
207  v1_mask = ( v1_mask.z < 0.5 ) ? lowz_mods : highz_mods;
208  v2_mask = ( v2_mask.z < 0.5 ) ? lowz_mods : highz_mods;
209 
210  // compute the final hash
211  hash_0 = fract( P * vec4( lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x ) );
212  hash_1 = fract( P * vec4( lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y ) );
213  hash_2 = fract( P * vec4( lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z ) );
214 }
215 
217 {
218  // calculate the simplex vector and index math
219  vec3 Pi;
220  vec3 Pi_1;
221  vec3 Pi_2;
222  vec4 v1234_x;
223  vec4 v1234_y;
224  vec4 v1234_z;
225  Simplex3D_GetCornerVectors( P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z );
226 
227  // generate the random vectors
228  vec4 hash_0;
229  vec4 hash_1;
230  vec4 hash_2;
231  FAST32_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
232  hash_0 -= 0.49999;
233  hash_1 -= 0.49999;
234  hash_2 -= 0.49999;
235 
236  // normalize random gradient vectors
237  vec4 norm = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 );
238  hash_0 *= norm;
239  hash_1 *= norm;
240  hash_2 *= norm;
241 
242  // evaluate gradients
243  vec4 grad_results = hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z;
244 
245  // evaluate the surflet f(x)=(0.5-x*x)^3
246  vec4 m = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
247  m = max(0.5 - m, 0.0); // The 0.5 here is SIMPLEX_PYRAMID_HEIGHT^2
248  vec4 m2 = m*m;
249  vec4 m3 = m*m2;
250 
251  // calc the deriv
252  vec4 temp = -6.0 * m2 * grad_results;
253  float xderiv = dot( temp, v1234_x ) + dot( m3, hash_0 );
254  float yderiv = dot( temp, v1234_y ) + dot( m3, hash_1 );
255  float zderiv = dot( temp, v1234_z ) + dot( m3, hash_2 );
256 
257  const float FINAL_NORMALIZATION = 37.837227241611314102871574478976; // scales the final result to a strict 1.0->-1.0 range
258 
259  // sum with the surflet and return
260  return vec3(xderiv, yderiv, zderiv) * FINAL_NORMALIZATION;
261 }
const GLfloat * v
Definition: gl2ext.h:2231
uniform float time
Definition: update.cs:32
uniform float particleLifetime
Definition: update.cs:36
void FAST32_hash_3D(vec3 gridcell, vec3 v2_mask, out vec4 hash_0, out vec4 hash_1, out vec4 hash_2)
vec3 gradphi(vec3 p)
Definition: update.cs:66
const vec2 eps
Definition: update.cs:37
float phi(vec3 p)
Definition: update.cs:59
Definition: matrix.h:51
GLboolean r
Definition: gl2ext.h:306
Definition: matrix.h:28
float min(float x, float y)
Definition: noise.cpp:34
void Simplex3D_GetCornerVectors(vec3 P, out vec3 Pi, out vec3 Pi_1, out vec3 Pi_2, out vec4 v1234_x, out vec4 v1234_y, out vec4 v1234_z)
Definition: update.cs:140
float clamp(float x, float min, float max)
Definition: noise.cpp:24
GLint GLfloat GLfloat GLfloat v2
Definition: gl2ext.h:1492
layout(local_size_x=64) in
vec3 SimplexPerlin3D_Deriv(vec3 P)
Definition: update.cs:216
const vec3 dx
Definition: update.cs:38
const vec3 dz
Definition: update.cs:40
float z
Definition: matrix.h:55
Definition: matrix.h:75
GLuint index
Definition: gl2ext.h:300
GLfloat GLfloat GLfloat w
Definition: gl2ext.h:2701
GLboolean GLboolean g
Definition: gl2ext.h:306
float w
Definition: matrix.h:80
const vec3 dy
Definition: update.cs:39
Matrix scale
Definition: RotoZoom.cpp:64
float x
Definition: matrix.h:53
uniform vec3 seed
Definition: update.cs:33
float y
Definition: matrix.h:54
float max(float x, float y)
Definition: noise.cpp:29
void uniform(string name, const mat4 &v)
Definition: glutil.cpp:97
void main()
Definition: update.cs:73
GLint GLint GLint GLint GLint x
Definition: gl2ext.h:574
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
GLenum GLuint buffer
Definition: gl2ext.h:628
float z
Definition: matrix.h:79
uniform vec3 emitterPos
Definition: update.cs:34
float ramp(float r)
Definition: update.cs:51
float x
Definition: matrix.h:30
const GLfloat * m
Definition: gl2ext.h:2508
GLint GLfloat GLfloat v1
Definition: gl2ext.h:1488
uniform float dt
Definition: update.cs:29
float x
Definition: matrix.h:77
float y
Definition: matrix.h:78
uniform vec3 spherePos
Definition: update.cs:35
const float regionLength
Definition: update.cs:41