particle-vs-gpu.chunk 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. precision mediump float;
  2. #include <common/math/transform>
  3. #include <builtin/internal/particle-common>
  4. #include <builtin/uniforms/cc-local>
  5. #pragma define CURVE_MODE_FIX 1
  6. #pragma define CURVE_MODE_BLEND 2
  7. #pragma define GRADIENT_MODE_FIX 1
  8. #pragma define GRADIENT_MODE_BLEND 2
  9. #pragma define SIMULATE_SPACE_LOCAL 0
  10. #pragma define SIMULATE_SPACE_WORLD 1
  11. #pragma define ANIMATION_MODE_WHOLE_SHEET 0
  12. #pragma define ANIMATION_MODE_SINGLE_ROW 1
  13. #pragma define COLOR_OVERTIME_RAND_OFFSET 91041.
  14. #pragma define FORCE_OVERTIME_RAND_OFFSET 212165.
  15. #pragma define ROTATION_OVERTIME_RAND_OFFSET 125292.
  16. #pragma define SIZE_OVERTIME_RAND_OFFSET 39825.
  17. #pragma define TEXTURE_ANIMATION_RAND_OFFSET 90794.
  18. #pragma define VELOCITY_OVERTIME_RAND_OFFSET 197866.
  19. uniform SampleConstants {
  20. vec4 u_sampleInfo;
  21. };
  22. uniform TickConstants {
  23. vec4 u_worldRot;
  24. vec4 u_timeDelta;
  25. };
  26. in vec4 a_position_starttime; // center position,particle start time
  27. in vec4 a_color;
  28. in vec4 a_dir_life; // xyz:particle start velocity,w:particle lifetime
  29. in float a_rndSeed;
  30. #if !CC_INSTANCE_PARTICLE
  31. in vec4 a_size_uv; // xyz:size, w:uv_0
  32. in vec4 a_rotation_uv; // xyz:rotation, w:uv_1
  33. #endif
  34. #if CC_INSTANCE_PARTICLE
  35. in vec4 a_size_fid; // xyz:size, w:fid
  36. in vec3 a_rotation; // xyz:rotation
  37. in vec3 a_uv;
  38. #endif
  39. #if CC_RENDER_MODE == RENDER_MODE_MESH
  40. in vec3 a_texCoord; // mesh uv
  41. in vec3 a_texCoord3; // mesh vertices
  42. in vec3 a_normal; // mesh normal
  43. in vec4 a_color1; // mesh color
  44. #endif
  45. vec3 unpackCurveData (sampler2D tex, vec2 coord) {
  46. vec4 a = texture(tex, coord);
  47. vec4 b = texture(tex, coord + u_sampleInfo.y);
  48. float c = fract(coord.x * u_sampleInfo.x);
  49. return mix(a.xyz, b.xyz, c);
  50. }
  51. vec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {
  52. vec4 a = texture(tex, coord);
  53. vec4 b = texture(tex, coord + u_sampleInfo.y);
  54. float c = fract(coord.x * u_sampleInfo.x);
  55. w = mix(a.w, b.w, c);
  56. return mix(a.xyz, b.xyz, c);
  57. }
  58. vec4 unpackGradientData (sampler2D tex, vec2 coord) {
  59. return texture(tex, coord);
  60. }
  61. vec4 scaleAndAdd (vec4 a, vec4 b, float scale) {
  62. a.x += b.x * scale;
  63. a.y += b.y * scale;
  64. a.z += b.z * scale;
  65. return a;
  66. }
  67. // Vulkan compatible issue#9858, do not use large number (more than 100) in mod function
  68. float pseudoRandom(float x) {
  69. #if USE_VK_SHADER
  70. float o = x;
  71. x = mod(x - 1.0, 2.0) - 1.0;
  72. float freqVar = 10.16640753482; //3.1415927*(sqrt(5.0)+1.0);
  73. float y = sin(freqVar * floor(o * 0.5 - 0.5)); // some pseudorandom hash
  74. float v = max(0.0, 1.0-abs(x));
  75. v *= 0.7071067812; // fix sheared 'distance' measurements - but this is 1D so unsure it's even a good thing to try
  76. v = y < 0.0 ? -v : v;
  77. return v;
  78. #endif
  79. #if !USE_VK_SHADER
  80. float seed = mod(x, 233280.);
  81. float q = (seed * 9301. + 49297.) / 233280.;
  82. return fract(q);
  83. #endif
  84. }
  85. #if COLOR_OVER_TIME_MODULE_ENABLE
  86. uniform sampler2D color_over_time_tex0;
  87. uniform ColorConstant {
  88. int u_color_mode;
  89. };
  90. #endif
  91. #if ROTATION_OVER_TIME_MODULE_ENABLE
  92. uniform sampler2D rotation_over_time_tex0;
  93. uniform RotationConstant {
  94. int u_rotation_mode;
  95. };
  96. #endif
  97. #if SIZE_OVER_TIME_MODULE_ENABLE
  98. uniform sampler2D size_over_time_tex0;
  99. uniform SizeConstant {
  100. int u_size_mode;
  101. };
  102. #endif
  103. #if FORCE_OVER_TIME_MODULE_ENABLE
  104. uniform sampler2D force_over_time_tex0;
  105. uniform ForceConstant {
  106. int u_force_mode;
  107. int u_force_space;
  108. };
  109. #endif
  110. #if VELOCITY_OVER_TIME_MODULE_ENABLE
  111. uniform sampler2D velocity_over_time_tex0;
  112. uniform VelocityConstant {
  113. int u_velocity_mode;
  114. int u_velocity_space;
  115. };
  116. #endif
  117. #if TEXTURE_ANIMATION_MODULE_ENABLE
  118. uniform sampler2D texture_animation_tex0;
  119. uniform AnimationConstant {
  120. vec4 u_anim_info;
  121. };
  122. #endif
  123. float repeat (float t, float length) {
  124. return t - floor(t / length) * length;
  125. }
  126. vec4 rotateQuat (vec4 p, vec4 q) {
  127. vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;
  128. vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);
  129. return vec4(res.xyz, p.w);
  130. }
  131. float random (float seed) {
  132. seed = mod(seed, 233280.);
  133. float q = (seed * 9301. + 49297.) / 233280.;
  134. return fract(q);
  135. }
  136. #pragma define INDENTIFY_NEG_QUAT 10.0
  137. vec4 toQuat(vec3 rotation) {
  138. vec3 rotTmp = rotation;
  139. float mulFactor = 1.0;
  140. if (rotTmp.x > INDENTIFY_NEG_QUAT * 0.5) {
  141. rotTmp.x -= INDENTIFY_NEG_QUAT;
  142. mulFactor = -1.0;
  143. }
  144. vec4 rot = vec4(rotTmp, 0.0);
  145. rot.w = mulFactor * sqrt(abs(1.0 - rot.x * rot.x - rot.y * rot.y - rot.z * rot.z));
  146. return rot;
  147. }
  148. vec4 gpvs_main () {
  149. float activeTime = u_timeDelta.x - a_position_starttime.w;
  150. float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);
  151. vec2 timeCoord0 = vec2(normalizedTime, 0.);
  152. vec2 timeCoord1 = vec2(normalizedTime, 1.);
  153. #if CC_RENDER_MODE == RENDER_MODE_MESH
  154. vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);
  155. #endif
  156. #if CC_RENDER_MODE != RENDER_MODE_MESH
  157. #if !CC_INSTANCE_PARTICLE
  158. vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);
  159. #endif
  160. #if CC_INSTANCE_PARTICLE
  161. vec2 vertIdx = a_uv.xy;
  162. #endif
  163. #endif
  164. vec4 velocity = vec4(a_dir_life.xyz, 0.);
  165. vec4 pos = vec4(a_position_starttime.xyz, 1.);
  166. // size
  167. #if !CC_INSTANCE_PARTICLE
  168. vec3 size = a_size_uv.xyz;
  169. #endif
  170. #if CC_INSTANCE_PARTICLE
  171. vec3 size = a_size_fid.xyz;
  172. #endif
  173. #if SIZE_OVER_TIME_MODULE_ENABLE
  174. if (u_size_mode == CURVE_MODE_FIX) {
  175. size *= unpackCurveData(size_over_time_tex0, timeCoord0);
  176. } else {
  177. vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);
  178. vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);
  179. float factor_s = pseudoRandom(a_rndSeed + SIZE_OVERTIME_RAND_OFFSET);
  180. size *= mix(size_0, size_1, factor_s);
  181. }
  182. #endif
  183. vec3 compScale = scale.xyz * size;
  184. // force
  185. #if FORCE_OVER_TIME_MODULE_ENABLE
  186. vec3 forceAnim = vec3(0.);
  187. if (u_force_mode == CURVE_MODE_FIX) {
  188. forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);
  189. } else {
  190. vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);
  191. vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);
  192. float factor_f = pseudoRandom(a_rndSeed + FORCE_OVERTIME_RAND_OFFSET);
  193. forceAnim = mix(force_0, force_1, factor_f);
  194. }
  195. vec4 forceTrack = vec4(forceAnim, 0.);
  196. if (u_force_space == SIMULATE_SPACE_LOCAL) {
  197. forceTrack = rotateQuat(forceTrack, u_worldRot);
  198. }
  199. velocity.xyz += forceTrack.xyz;
  200. #endif
  201. // velocity
  202. #if VELOCITY_OVER_TIME_MODULE_ENABLE
  203. float speedModifier0 = 1.;
  204. float speedModifier1 = 1.;
  205. vec3 velocityAnim = vec3(0.);
  206. if (u_velocity_mode == CURVE_MODE_FIX) {
  207. velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);
  208. } else {
  209. vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);
  210. vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);
  211. float factor_v = pseudoRandom(a_rndSeed + VELOCITY_OVERTIME_RAND_OFFSET);
  212. velocityAnim = mix(vectory_0, vectory_1, factor_v);
  213. speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);
  214. }
  215. vec4 velocityTrack = vec4(velocityAnim, 0.);
  216. if (u_velocity_space == SIMULATE_SPACE_LOCAL) {
  217. velocityTrack = rotateQuat(velocityTrack, u_worldRot);
  218. }
  219. velocity.xyz += velocityTrack.xyz;
  220. velocity.xyz *= speedModifier0;
  221. #endif
  222. pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;
  223. #if !CC_USE_WORLD_SPACE
  224. pos = cc_matWorld * pos;
  225. #if CC_RENDER_MODE == RENDER_MODE_STRETCHED_BILLBOARD
  226. velocity = rotateQuat(velocity, u_worldRot);
  227. #endif
  228. #endif
  229. // rotation
  230. #if !CC_INSTANCE_PARTICLE
  231. vec3 startRotation = a_rotation_uv.xyz;
  232. #endif
  233. #if CC_INSTANCE_PARTICLE
  234. vec3 startRotation = a_rotation;
  235. #endif
  236. #if CC_RENDER_MODE != RENDER_MODE_MESH
  237. #if CC_RENDER_MODE == RENDER_MODE_BILLBOARD
  238. vec3 rotEuler = startRotation.xyz;
  239. #elif CC_RENDER_MODE == RENDER_MODE_STRETCHED_BILLBOARD
  240. vec3 rotEuler = vec3(0.);
  241. #endif
  242. #if CC_RENDER_MODE != RENDER_MODE_BILLBOARD && CC_RENDER_MODE != RENDER_MODE_STRETCHED_BILLBOARD
  243. vec3 rotEuler = vec3(0., 0., startRotation.z);
  244. #endif
  245. vec4 rot = quaternionFromEuler(rotEuler);
  246. #endif
  247. #if CC_RENDER_MODE == RENDER_MODE_MESH
  248. vec4 rot = quaternionFromEuler(startRotation);
  249. #endif
  250. #if ROTATION_OVER_TIME_MODULE_ENABLE
  251. if (u_rotation_mode == CURVE_MODE_FIX) {
  252. vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;
  253. vec4 quat = eulerToQuat(euler);
  254. mat3 mLocal = quatToMat3(quat);
  255. mat3 mStart = quatToMat3(rot);
  256. rot = mat3ToQuat(mStart * mLocal);
  257. } else {
  258. vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);
  259. vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);
  260. float factor_r = pseudoRandom(a_rndSeed + ROTATION_OVERTIME_RAND_OFFSET);
  261. vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;
  262. #if CC_RENDER_MODE == RENDER_MODE_VERTICAL_BILLBOARD || CC_RENDER_MODE == RENDER_MODE_HORIZONTAL_BILLBOARD
  263. euler = vec3(0.0, 0.0, euler.z);
  264. #endif
  265. vec4 quat = eulerToQuat(euler);
  266. mat3 mLocal = quatToMat3(quat);
  267. mat3 mStart = quatToMat3(rot);
  268. rot = mat3ToQuat(mStart * mLocal);
  269. }
  270. #endif
  271. // color
  272. #if COLOR_OVER_TIME_MODULE_ENABLE
  273. if (u_color_mode == GRADIENT_MODE_FIX) {
  274. color = a_color * texture(color_over_time_tex0, timeCoord0);
  275. } else {
  276. vec4 color_0 = texture(color_over_time_tex0, timeCoord0);
  277. vec4 color_1 = texture(color_over_time_tex0, timeCoord1);
  278. float factor_c = pseudoRandom(a_rndSeed + COLOR_OVERTIME_RAND_OFFSET);
  279. color = a_color * mix(color_0, color_1, factor_c);
  280. }
  281. #endif
  282. #if !COLOR_OVER_TIME_MODULE_ENABLE
  283. color = a_color;
  284. #endif
  285. #if CC_RENDER_MODE != RENDER_MODE_MESH
  286. vec2 cornerOffset = vec2((vertIdx - 0.5));
  287. #if CC_RENDER_MODE == RENDER_MODE_STRETCHED_BILLBOARD
  288. rot = vec4(0.0, 0.0, 0.0, 1.0);
  289. #endif
  290. computeVertPos(pos, cornerOffset, rot, compScale
  291. #if CC_RENDER_MODE == RENDER_MODE_BILLBOARD || CC_RENDER_MODE == RENDER_MODE_VERTICAL_BILLBOARD
  292. , cc_matViewInv
  293. #endif
  294. #if CC_RENDER_MODE == RENDER_MODE_STRETCHED_BILLBOARD
  295. , cc_cameraPos.xyz
  296. , velocity
  297. , frameTile_velLenScale.z
  298. , frameTile_velLenScale.w
  299. #if !CC_INSTANCE_PARTICLE
  300. , a_size_uv.w
  301. #endif
  302. #if CC_INSTANCE_PARTICLE
  303. , a_uv.x
  304. #endif
  305. #endif
  306. );
  307. #endif
  308. #if CC_RENDER_MODE == RENDER_MODE_MESH
  309. mat3 rotMat = quatToMat3(rot);
  310. mat3 nodeMat = quatToMat3(nodeRotation);
  311. rotMat = nodeMat * rotMat;
  312. rot = mat3ToQuat(rotMat);
  313. mat4 xformNoScale = matrixFromRT(rot, pos.xyz);
  314. mat4 xform = matFromRTS(rot, pos.xyz, compScale);
  315. pos = xform * vec4(a_texCoord3, 1);
  316. vec4 normal = xformNoScale * vec4(a_normal, 0);
  317. color *= a_color1;
  318. #endif
  319. pos = cc_matViewProj * pos;
  320. float frameIndex = 0.;
  321. #if TEXTURE_ANIMATION_MODULE_ENABLE
  322. float startFrame = 0.;
  323. vec3 frameInfo = vec3(0.);
  324. if (int(u_anim_info.x) == GRADIENT_MODE_FIX) {
  325. frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);
  326. } else {
  327. vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);
  328. vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);
  329. float factor_t = pseudoRandom(a_rndSeed + TEXTURE_ANIMATION_RAND_OFFSET);
  330. frameInfo = mix(frameInfo0, frameInfo1, factor_t);
  331. }
  332. startFrame = frameInfo.x / u_anim_info.y;
  333. float EPSILON = 1e-6;
  334. frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1. + EPSILON);
  335. #endif
  336. uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;
  337. return pos;
  338. }