{
  "__type__": "cc.EffectAsset",
  "_name": "builtin-particle-gpu",
  "_objFlags": 0,
  "_native": "",
  "techniques": [
    {
      "name": "add",
      "passes": [
        {
          "rasterizerState": {
            "cullMode": 0
          },
          "blendState": {
            "targets": [
              {
                "blend": true,
                "blendSrc": 2,
                "blendDst": 1,
                "blendSrcAlpha": 2,
                "blendDstAlpha": 1
              }
            ]
          },
          "program": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|tinted-fs:add",
          "depthStencilState": {
            "depthTest": true,
            "depthWrite": false
          },
          "properties": {
            "mainTexture": {
              "value": "grey",
              "type": 28
            },
            "mainTiling_Offset": {
              "value": [
                1,
                1,
                0,
                0
              ],
              "type": 16
            },
            "tintColor": {
              "value": [
                0.5,
                0.5,
                0.5,
                0.5
              ],
              "editor": {
                "type": "color"
              },
              "type": 16
            }
          }
        }
      ]
    },
    {
      "name": "alpha-blend",
      "passes": [
        {
          "rasterizerState": {
            "cullMode": 0
          },
          "blendState": {
            "targets": [
              {
                "blend": true,
                "blendSrc": 2,
                "blendDst": 4,
                "blendSrcAlpha": 0,
                "blendDstAlpha": 1
              }
            ]
          },
          "program": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|tinted-fs:add",
          "depthStencilState": {
            "depthTest": true,
            "depthWrite": false
          },
          "properties": {
            "mainTexture": {
              "value": "grey",
              "type": 28
            },
            "mainTiling_Offset": {
              "value": [
                1,
                1,
                0,
                0
              ],
              "type": 16
            },
            "tintColor": {
              "value": [
                0.5,
                0.5,
                0.5,
                0.5
              ],
              "editor": {
                "type": "color"
              },
              "type": 16
            }
          }
        }
      ]
    },
    {
      "name": "add-multiply",
      "passes": [
        {
          "rasterizerState": {
            "cullMode": 0
          },
          "blendState": {
            "targets": [
              {
                "blend": true,
                "blendSrc": 7,
                "blendDst": 1,
                "blendSrcAlpha": 0,
                "blendDstAlpha": 3
              }
            ]
          },
          "program": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|tinted-fs:multiply",
          "depthStencilState": {
            "depthTest": true,
            "depthWrite": false
          },
          "properties": {
            "mainTexture": {
              "value": "grey",
              "type": 28
            },
            "mainTiling_Offset": {
              "value": [
                1,
                1,
                0,
                0
              ],
              "type": 16
            },
            "tintColor": {
              "value": [
                0.5,
                0.5,
                0.5,
                0.5
              ],
              "editor": {
                "type": "color"
              },
              "type": 16
            }
          }
        }
      ]
    },
    {
      "name": "add-smooth",
      "passes": [
        {
          "rasterizerState": {
            "cullMode": 0
          },
          "blendState": {
            "targets": [
              {
                "blend": true,
                "blendSrc": 2,
                "blendDst": 1,
                "blendSrcAlpha": 2,
                "blendDstAlpha": 1
              }
            ]
          },
          "program": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|no-tint-fs:addSmooth",
          "depthStencilState": {
            "depthTest": true,
            "depthWrite": false
          },
          "properties": {
            "mainTexture": {
              "value": "grey",
              "type": 28
            },
            "mainTiling_Offset": {
              "value": [
                1,
                1,
                0,
                0
              ],
              "type": 16
            }
          }
        }
      ]
    },
    {
      "name": "premultiply-blend",
      "passes": [
        {
          "rasterizerState": {
            "cullMode": 0
          },
          "blendState": {
            "targets": [
              {
                "blend": true,
                "blendSrc": 2,
                "blendDst": 4,
                "blendSrcAlpha": 0,
                "blendDstAlpha": 1
              }
            ]
          },
          "program": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|no-tint-fs:premultiplied",
          "depthStencilState": {
            "depthTest": true,
            "depthWrite": false
          },
          "properties": {
            "mainTexture": {
              "value": "grey",
              "type": 28
            },
            "mainTiling_Offset": {
              "value": [
                1,
                1,
                0,
                0
              ],
              "type": 16
            }
          }
        }
      ]
    }
  ],
  "shaders": [
    {
      "blocks": [
        {
          "name": "Constants",
          "members": [
            {
              "name": "mainTiling_Offset",
              "type": 16,
              "count": 1
            },
            {
              "name": "frameTile_velLenScale",
              "type": 16,
              "count": 1
            },
            {
              "name": "scale",
              "type": 16,
              "count": 1
            },
            {
              "name": "nodeRotation",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 0
        },
        {
          "name": "SampleConstants",
          "members": [
            {
              "name": "u_sampleInfo",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 1
        },
        {
          "name": "TickConstants",
          "members": [
            {
              "name": "u_worldRot",
              "type": 16,
              "count": 1
            },
            {
              "name": "u_timeDelta",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 2
        },
        {
          "name": "ColorConstant",
          "members": [
            {
              "name": "u_color_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 3
        },
        {
          "name": "RotationConstant",
          "members": [
            {
              "name": "u_rotation_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 4
        },
        {
          "name": "SizeConstant",
          "members": [
            {
              "name": "u_size_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 5
        },
        {
          "name": "ForceConstant",
          "members": [
            {
              "name": "u_force_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_force_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 6
        },
        {
          "name": "VelocityConstant",
          "members": [
            {
              "name": "u_velocity_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_velocity_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 7
        },
        {
          "name": "AnimationConstant",
          "members": [
            {
              "name": "u_anim_info",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 8
        },
        {
          "name": "FragConstants",
          "members": [
            {
              "name": "tintColor",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 16,
          "binding": 9
        }
      ],
      "samplerTextures": [
        {
          "name": "color_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 10
        },
        {
          "name": "rotation_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 11
        },
        {
          "name": "size_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 12
        },
        {
          "name": "force_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 13
        },
        {
          "name": "velocity_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 14
        },
        {
          "name": "texture_animation_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 15
        },
        {
          "name": "mainTexture",
          "type": 28,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "binding": 16
        }
      ],
      "samplers": [],
      "textures": [],
      "buffers": [],
      "images": [],
      "subpassInputs": [],
      "attributes": [
        {
          "name": "a_position_starttime",
          "defines": [],
          "format": 44,
          "location": 0
        },
        {
          "name": "a_size_uv",
          "defines": [],
          "format": 44,
          "location": 1
        },
        {
          "name": "a_rotation_uv",
          "defines": [],
          "format": 44,
          "location": 2
        },
        {
          "name": "a_color",
          "defines": [],
          "format": 44,
          "location": 3
        },
        {
          "name": "a_dir_life",
          "defines": [],
          "format": 44,
          "location": 4
        },
        {
          "name": "a_rndSeed",
          "defines": [],
          "format": 11,
          "location": 5
        },
        {
          "name": "a_texCoord",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 6
        },
        {
          "name": "a_texCoord3",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 7
        },
        {
          "name": "a_normal",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 8
        },
        {
          "name": "a_color1",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 44,
          "location": 9
        }
      ],
      "varyings": [
        {
          "name": "uv",
          "type": 14,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 0
        },
        {
          "name": "color",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 1
        }
      ],
      "fragColors": [
        {
          "name": "cc_FragColor",
          "typename": "vec4",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "location": 0
        }
      ],
      "hash": 1250077034,
      "glsl4": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(set = 1, binding = 0) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(set = 2, binding = 0) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nlayout(location = 0) out mediump vec2 uv;\nlayout(location = 1) out mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(set = 1, binding = 1) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(set = 1, binding = 2) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nlayout(location = 0) in vec4 a_position_starttime;\nlayout(location = 1) in vec4 a_size_uv;\nlayout(location = 2) in vec4 a_rotation_uv;\nlayout(location = 3) in vec4 a_color;\nlayout(location = 4) in vec4 a_dir_life;\nlayout(location = 5) in float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  layout(location = 6) in vec3 a_texCoord;\n  layout(location = 7) in vec3 a_texCoord3;\n  layout(location = 8) in vec3 a_normal;\n  layout(location = 9) in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 10) uniform sampler2D color_over_time_tex0;\n  layout(set = 1, binding = 3) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 11) uniform sampler2D rotation_over_time_tex0;\n  layout(set = 1, binding = 4) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 12) uniform sampler2D size_over_time_tex0;\n  layout(set = 1, binding = 5) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 13) uniform sampler2D force_over_time_tex0;\n  layout(set = 1, binding = 6) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 14) uniform sampler2D velocity_over_time_tex0;\n  layout(set = 1, binding = 7) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  layout(set = 1, binding = 15) uniform sampler2D texture_animation_tex0;\n  layout(set = 1, binding = 8) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nlayout(location = 0) in vec2 uv;\nlayout(location = 1) in vec4 color;\nlayout(set = 1, binding = 16) uniform sampler2D mainTexture;\nlayout(set = 1, binding = 9) uniform FragConstants {\n  vec4 tintColor;\n};\nvec4 add () {\n  vec4 col = 2.0 * color * tintColor * texture(mainTexture, uv);\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = add(); }"
      },
      "glsl3": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(std140) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(std140) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nout mediump vec2 uv;\nout mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(std140) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(std140) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nin vec4 a_position_starttime;\nin vec4 a_size_uv;\nin vec4 a_rotation_uv;\nin vec4 a_color;\nin vec4 a_dir_life;\nin float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  in vec3 a_texCoord;\n  in vec3 a_texCoord3;\n  in vec3 a_normal;\n  in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n  layout(std140) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n  layout(std140) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n  layout(std140) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n  layout(std140) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n  layout(std140) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n  layout(std140) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nin vec2 uv;\nin vec4 color;\nuniform sampler2D mainTexture;\nlayout(std140) uniform FragConstants {\n  vec4 tintColor;\n};\nvec4 add () {\n  vec4 col = 2.0 * color * tintColor * texture(mainTexture, uv);\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = add(); }"
      },
      "glsl1": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\n   uniform vec4 mainTiling_Offset;\n   uniform vec4 frameTile_velLenScale;\n   uniform vec4 scale;\n   uniform vec4 nodeRotation;\nuniform highp mat4 cc_matView;\n  uniform highp mat4 cc_matViewInv;\n  uniform highp mat4 cc_matViewProj;\n  uniform highp vec4 cc_cameraPos;\nuniform highp mat4 cc_matWorld;\nvarying mediump vec2 uv;\nvarying mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\n          uniform vec4 u_sampleInfo;\n    uniform vec4 u_worldRot;\n    uniform vec4 u_timeDelta;\nattribute vec4 a_position_starttime;\nattribute vec4 a_size_uv;\nattribute vec4 a_rotation_uv;\nattribute vec4 a_color;\nattribute vec4 a_dir_life;\nattribute float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  attribute vec3 a_texCoord;\n  attribute vec3 a_texCoord3;\n  attribute vec3 a_normal;\n  attribute vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n      uniform int u_color_mode;\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n      uniform int u_rotation_mode;\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n      uniform int u_size_mode;\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n      uniform int u_force_mode;\n    uniform int u_force_space;\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n      uniform int u_velocity_mode;\n    uniform int u_velocity_space;\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n      uniform vec4 u_anim_info;\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture2D(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture2D(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture2D(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nvarying vec2 uv;\nvarying vec4 color;\nuniform sampler2D mainTexture;\n   uniform vec4 tintColor;\nvec4 add () {\n  vec4 col = 2.0 * color * tintColor * texture2D(mainTexture, uv);\n  return CCFragOutput(col);\n}\nvoid main() { gl_FragColor = add(); }"
      },
      "builtins": {
        "globals": {
          "blocks": [
            {
              "name": "CCGlobal",
              "defines": []
            },
            {
              "name": "CCCamera",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "locals": {
          "blocks": [
            {
              "name": "CCLocal",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "statistics": {
          "CC_EFFECT_USED_VERTEX_UNIFORM_VECTORS": 63,
          "CC_EFFECT_USED_FRAGMENT_UNIFORM_VECTORS": 40
        }
      },
      "defines": [
        {
          "name": "CC_RENDER_MODE",
          "type": "number",
          "defines": [],
          "range": [
            0,
            4
          ]
        },
        {
          "name": "USE_VK_SHADER",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "COLOR_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "ROTATION_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "SIZE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "FORCE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "VELOCITY_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "TEXTURE_ANIMATION_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "CC_USE_WORLD_SPACE",
          "type": "boolean",
          "defines": []
        }
      ],
      "name": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|tinted-fs:add"
    },
    {
      "blocks": [
        {
          "name": "Constants",
          "members": [
            {
              "name": "mainTiling_Offset",
              "type": 16,
              "count": 1
            },
            {
              "name": "frameTile_velLenScale",
              "type": 16,
              "count": 1
            },
            {
              "name": "scale",
              "type": 16,
              "count": 1
            },
            {
              "name": "nodeRotation",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 0
        },
        {
          "name": "SampleConstants",
          "members": [
            {
              "name": "u_sampleInfo",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 1
        },
        {
          "name": "TickConstants",
          "members": [
            {
              "name": "u_worldRot",
              "type": 16,
              "count": 1
            },
            {
              "name": "u_timeDelta",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 2
        },
        {
          "name": "ColorConstant",
          "members": [
            {
              "name": "u_color_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 3
        },
        {
          "name": "RotationConstant",
          "members": [
            {
              "name": "u_rotation_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 4
        },
        {
          "name": "SizeConstant",
          "members": [
            {
              "name": "u_size_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 5
        },
        {
          "name": "ForceConstant",
          "members": [
            {
              "name": "u_force_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_force_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 6
        },
        {
          "name": "VelocityConstant",
          "members": [
            {
              "name": "u_velocity_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_velocity_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 7
        },
        {
          "name": "AnimationConstant",
          "members": [
            {
              "name": "u_anim_info",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 8
        },
        {
          "name": "FragConstants",
          "members": [
            {
              "name": "tintColor",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 16,
          "binding": 9
        }
      ],
      "samplerTextures": [
        {
          "name": "color_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 10
        },
        {
          "name": "rotation_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 11
        },
        {
          "name": "size_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 12
        },
        {
          "name": "force_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 13
        },
        {
          "name": "velocity_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 14
        },
        {
          "name": "texture_animation_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 15
        },
        {
          "name": "mainTexture",
          "type": 28,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "binding": 16
        }
      ],
      "samplers": [],
      "textures": [],
      "buffers": [],
      "images": [],
      "subpassInputs": [],
      "attributes": [
        {
          "name": "a_position_starttime",
          "defines": [],
          "format": 44,
          "location": 0
        },
        {
          "name": "a_size_uv",
          "defines": [],
          "format": 44,
          "location": 1
        },
        {
          "name": "a_rotation_uv",
          "defines": [],
          "format": 44,
          "location": 2
        },
        {
          "name": "a_color",
          "defines": [],
          "format": 44,
          "location": 3
        },
        {
          "name": "a_dir_life",
          "defines": [],
          "format": 44,
          "location": 4
        },
        {
          "name": "a_rndSeed",
          "defines": [],
          "format": 11,
          "location": 5
        },
        {
          "name": "a_texCoord",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 6
        },
        {
          "name": "a_texCoord3",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 7
        },
        {
          "name": "a_normal",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 8
        },
        {
          "name": "a_color1",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 44,
          "location": 9
        }
      ],
      "varyings": [
        {
          "name": "uv",
          "type": 14,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 0
        },
        {
          "name": "color",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 1
        }
      ],
      "fragColors": [
        {
          "name": "cc_FragColor",
          "typename": "vec4",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "location": 0
        }
      ],
      "hash": 1333465447,
      "glsl4": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(set = 1, binding = 0) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(set = 2, binding = 0) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nlayout(location = 0) out mediump vec2 uv;\nlayout(location = 1) out mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(set = 1, binding = 1) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(set = 1, binding = 2) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nlayout(location = 0) in vec4 a_position_starttime;\nlayout(location = 1) in vec4 a_size_uv;\nlayout(location = 2) in vec4 a_rotation_uv;\nlayout(location = 3) in vec4 a_color;\nlayout(location = 4) in vec4 a_dir_life;\nlayout(location = 5) in float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  layout(location = 6) in vec3 a_texCoord;\n  layout(location = 7) in vec3 a_texCoord3;\n  layout(location = 8) in vec3 a_normal;\n  layout(location = 9) in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 10) uniform sampler2D color_over_time_tex0;\n  layout(set = 1, binding = 3) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 11) uniform sampler2D rotation_over_time_tex0;\n  layout(set = 1, binding = 4) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 12) uniform sampler2D size_over_time_tex0;\n  layout(set = 1, binding = 5) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 13) uniform sampler2D force_over_time_tex0;\n  layout(set = 1, binding = 6) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 14) uniform sampler2D velocity_over_time_tex0;\n  layout(set = 1, binding = 7) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  layout(set = 1, binding = 15) uniform sampler2D texture_animation_tex0;\n  layout(set = 1, binding = 8) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nlayout(location = 0) in vec2 uv;\nlayout(location = 1) in vec4 color;\nlayout(set = 1, binding = 16) uniform sampler2D mainTexture;\nlayout(set = 1, binding = 9) uniform FragConstants {\n  vec4 tintColor;\n};\nvec4 multiply () {\n  vec4 col;\n  vec4 texColor = texture(mainTexture, uv);\n  col.rgb = tintColor.rgb * texColor.rgb * color.rgb * vec3(2.0);\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = multiply(); }"
      },
      "glsl3": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(std140) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(std140) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nout mediump vec2 uv;\nout mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(std140) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(std140) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nin vec4 a_position_starttime;\nin vec4 a_size_uv;\nin vec4 a_rotation_uv;\nin vec4 a_color;\nin vec4 a_dir_life;\nin float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  in vec3 a_texCoord;\n  in vec3 a_texCoord3;\n  in vec3 a_normal;\n  in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n  layout(std140) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n  layout(std140) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n  layout(std140) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n  layout(std140) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n  layout(std140) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n  layout(std140) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nin vec2 uv;\nin vec4 color;\nuniform sampler2D mainTexture;\nlayout(std140) uniform FragConstants {\n  vec4 tintColor;\n};\nvec4 multiply () {\n  vec4 col;\n  vec4 texColor = texture(mainTexture, uv);\n  col.rgb = tintColor.rgb * texColor.rgb * color.rgb * vec3(2.0);\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = multiply(); }"
      },
      "glsl1": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\n   uniform vec4 mainTiling_Offset;\n   uniform vec4 frameTile_velLenScale;\n   uniform vec4 scale;\n   uniform vec4 nodeRotation;\nuniform highp mat4 cc_matView;\n  uniform highp mat4 cc_matViewInv;\n  uniform highp mat4 cc_matViewProj;\n  uniform highp vec4 cc_cameraPos;\nuniform highp mat4 cc_matWorld;\nvarying mediump vec2 uv;\nvarying mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\n          uniform vec4 u_sampleInfo;\n    uniform vec4 u_worldRot;\n    uniform vec4 u_timeDelta;\nattribute vec4 a_position_starttime;\nattribute vec4 a_size_uv;\nattribute vec4 a_rotation_uv;\nattribute vec4 a_color;\nattribute vec4 a_dir_life;\nattribute float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  attribute vec3 a_texCoord;\n  attribute vec3 a_texCoord3;\n  attribute vec3 a_normal;\n  attribute vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n      uniform int u_color_mode;\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n      uniform int u_rotation_mode;\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n      uniform int u_size_mode;\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n      uniform int u_force_mode;\n    uniform int u_force_space;\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n      uniform int u_velocity_mode;\n    uniform int u_velocity_space;\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n      uniform vec4 u_anim_info;\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture2D(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture2D(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture2D(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nvarying vec2 uv;\nvarying vec4 color;\nuniform sampler2D mainTexture;\n   uniform vec4 tintColor;\nvec4 multiply () {\n  vec4 col;\n  vec4 texColor = texture2D(mainTexture, uv);\n  col.rgb = tintColor.rgb * texColor.rgb * color.rgb * vec3(2.0);\n  return CCFragOutput(col);\n}\nvoid main() { gl_FragColor = multiply(); }"
      },
      "builtins": {
        "globals": {
          "blocks": [
            {
              "name": "CCGlobal",
              "defines": []
            },
            {
              "name": "CCCamera",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "locals": {
          "blocks": [
            {
              "name": "CCLocal",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "statistics": {
          "CC_EFFECT_USED_VERTEX_UNIFORM_VECTORS": 63,
          "CC_EFFECT_USED_FRAGMENT_UNIFORM_VECTORS": 40
        }
      },
      "defines": [
        {
          "name": "CC_RENDER_MODE",
          "type": "number",
          "defines": [],
          "range": [
            0,
            4
          ]
        },
        {
          "name": "USE_VK_SHADER",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "COLOR_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "ROTATION_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "SIZE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "FORCE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "VELOCITY_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "TEXTURE_ANIMATION_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "CC_USE_WORLD_SPACE",
          "type": "boolean",
          "defines": []
        }
      ],
      "name": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|tinted-fs:multiply"
    },
    {
      "blocks": [
        {
          "name": "Constants",
          "members": [
            {
              "name": "mainTiling_Offset",
              "type": 16,
              "count": 1
            },
            {
              "name": "frameTile_velLenScale",
              "type": 16,
              "count": 1
            },
            {
              "name": "scale",
              "type": 16,
              "count": 1
            },
            {
              "name": "nodeRotation",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 0
        },
        {
          "name": "SampleConstants",
          "members": [
            {
              "name": "u_sampleInfo",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 1
        },
        {
          "name": "TickConstants",
          "members": [
            {
              "name": "u_worldRot",
              "type": 16,
              "count": 1
            },
            {
              "name": "u_timeDelta",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 2
        },
        {
          "name": "ColorConstant",
          "members": [
            {
              "name": "u_color_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 3
        },
        {
          "name": "RotationConstant",
          "members": [
            {
              "name": "u_rotation_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 4
        },
        {
          "name": "SizeConstant",
          "members": [
            {
              "name": "u_size_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 5
        },
        {
          "name": "ForceConstant",
          "members": [
            {
              "name": "u_force_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_force_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 6
        },
        {
          "name": "VelocityConstant",
          "members": [
            {
              "name": "u_velocity_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_velocity_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 7
        },
        {
          "name": "AnimationConstant",
          "members": [
            {
              "name": "u_anim_info",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 8
        }
      ],
      "samplerTextures": [
        {
          "name": "color_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 9
        },
        {
          "name": "rotation_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 10
        },
        {
          "name": "size_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 11
        },
        {
          "name": "force_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 12
        },
        {
          "name": "velocity_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 13
        },
        {
          "name": "texture_animation_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 14
        },
        {
          "name": "mainTexture",
          "type": 28,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "binding": 15
        }
      ],
      "samplers": [],
      "textures": [],
      "buffers": [],
      "images": [],
      "subpassInputs": [],
      "attributes": [
        {
          "name": "a_position_starttime",
          "defines": [],
          "format": 44,
          "location": 0
        },
        {
          "name": "a_size_uv",
          "defines": [],
          "format": 44,
          "location": 1
        },
        {
          "name": "a_rotation_uv",
          "defines": [],
          "format": 44,
          "location": 2
        },
        {
          "name": "a_color",
          "defines": [],
          "format": 44,
          "location": 3
        },
        {
          "name": "a_dir_life",
          "defines": [],
          "format": 44,
          "location": 4
        },
        {
          "name": "a_rndSeed",
          "defines": [],
          "format": 11,
          "location": 5
        },
        {
          "name": "a_texCoord",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 6
        },
        {
          "name": "a_texCoord3",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 7
        },
        {
          "name": "a_normal",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 8
        },
        {
          "name": "a_color1",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 44,
          "location": 9
        }
      ],
      "varyings": [
        {
          "name": "uv",
          "type": 14,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 0
        },
        {
          "name": "color",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 1
        }
      ],
      "fragColors": [
        {
          "name": "cc_FragColor",
          "typename": "vec4",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "location": 0
        }
      ],
      "hash": 2496557486,
      "glsl4": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(set = 1, binding = 0) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(set = 2, binding = 0) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nlayout(location = 0) out mediump vec2 uv;\nlayout(location = 1) out mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(set = 1, binding = 1) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(set = 1, binding = 2) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nlayout(location = 0) in vec4 a_position_starttime;\nlayout(location = 1) in vec4 a_size_uv;\nlayout(location = 2) in vec4 a_rotation_uv;\nlayout(location = 3) in vec4 a_color;\nlayout(location = 4) in vec4 a_dir_life;\nlayout(location = 5) in float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  layout(location = 6) in vec3 a_texCoord;\n  layout(location = 7) in vec3 a_texCoord3;\n  layout(location = 8) in vec3 a_normal;\n  layout(location = 9) in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 9) uniform sampler2D color_over_time_tex0;\n  layout(set = 1, binding = 3) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 10) uniform sampler2D rotation_over_time_tex0;\n  layout(set = 1, binding = 4) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 11) uniform sampler2D size_over_time_tex0;\n  layout(set = 1, binding = 5) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 12) uniform sampler2D force_over_time_tex0;\n  layout(set = 1, binding = 6) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 13) uniform sampler2D velocity_over_time_tex0;\n  layout(set = 1, binding = 7) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  layout(set = 1, binding = 14) uniform sampler2D texture_animation_tex0;\n  layout(set = 1, binding = 8) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nlayout(location = 0) in vec2 uv;\nlayout(location = 1) in vec4 color;\nlayout(set = 1, binding = 15) uniform sampler2D mainTexture;\nvec4 addSmooth () {\n  vec4 col = color * texture(mainTexture, uv);\n  col.rgb *= col.a;\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = addSmooth(); }"
      },
      "glsl3": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(std140) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(std140) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nout mediump vec2 uv;\nout mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(std140) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(std140) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nin vec4 a_position_starttime;\nin vec4 a_size_uv;\nin vec4 a_rotation_uv;\nin vec4 a_color;\nin vec4 a_dir_life;\nin float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  in vec3 a_texCoord;\n  in vec3 a_texCoord3;\n  in vec3 a_normal;\n  in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n  layout(std140) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n  layout(std140) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n  layout(std140) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n  layout(std140) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n  layout(std140) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n  layout(std140) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nin vec2 uv;\nin vec4 color;\nuniform sampler2D mainTexture;\nvec4 addSmooth () {\n  vec4 col = color * texture(mainTexture, uv);\n  col.rgb *= col.a;\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = addSmooth(); }"
      },
      "glsl1": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\n   uniform vec4 mainTiling_Offset;\n   uniform vec4 frameTile_velLenScale;\n   uniform vec4 scale;\n   uniform vec4 nodeRotation;\nuniform highp mat4 cc_matView;\n  uniform highp mat4 cc_matViewInv;\n  uniform highp mat4 cc_matViewProj;\n  uniform highp vec4 cc_cameraPos;\nuniform highp mat4 cc_matWorld;\nvarying mediump vec2 uv;\nvarying mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\n          uniform vec4 u_sampleInfo;\n    uniform vec4 u_worldRot;\n    uniform vec4 u_timeDelta;\nattribute vec4 a_position_starttime;\nattribute vec4 a_size_uv;\nattribute vec4 a_rotation_uv;\nattribute vec4 a_color;\nattribute vec4 a_dir_life;\nattribute float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  attribute vec3 a_texCoord;\n  attribute vec3 a_texCoord3;\n  attribute vec3 a_normal;\n  attribute vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n      uniform int u_color_mode;\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n      uniform int u_rotation_mode;\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n      uniform int u_size_mode;\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n      uniform int u_force_mode;\n    uniform int u_force_space;\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n      uniform int u_velocity_mode;\n    uniform int u_velocity_space;\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n      uniform vec4 u_anim_info;\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture2D(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture2D(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture2D(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nvarying vec2 uv;\nvarying vec4 color;\nuniform sampler2D mainTexture;\nvec4 addSmooth () {\n  vec4 col = color * texture2D(mainTexture, uv);\n  col.rgb *= col.a;\n  return CCFragOutput(col);\n}\nvoid main() { gl_FragColor = addSmooth(); }"
      },
      "builtins": {
        "globals": {
          "blocks": [
            {
              "name": "CCGlobal",
              "defines": []
            },
            {
              "name": "CCCamera",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "locals": {
          "blocks": [
            {
              "name": "CCLocal",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "statistics": {
          "CC_EFFECT_USED_VERTEX_UNIFORM_VECTORS": 63,
          "CC_EFFECT_USED_FRAGMENT_UNIFORM_VECTORS": 39
        }
      },
      "defines": [
        {
          "name": "CC_RENDER_MODE",
          "type": "number",
          "defines": [],
          "range": [
            0,
            4
          ]
        },
        {
          "name": "USE_VK_SHADER",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "COLOR_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "ROTATION_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "SIZE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "FORCE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "VELOCITY_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "TEXTURE_ANIMATION_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "CC_USE_WORLD_SPACE",
          "type": "boolean",
          "defines": []
        }
      ],
      "name": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|no-tint-fs:addSmooth"
    },
    {
      "blocks": [
        {
          "name": "Constants",
          "members": [
            {
              "name": "mainTiling_Offset",
              "type": 16,
              "count": 1
            },
            {
              "name": "frameTile_velLenScale",
              "type": 16,
              "count": 1
            },
            {
              "name": "scale",
              "type": 16,
              "count": 1
            },
            {
              "name": "nodeRotation",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 0
        },
        {
          "name": "SampleConstants",
          "members": [
            {
              "name": "u_sampleInfo",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 1
        },
        {
          "name": "TickConstants",
          "members": [
            {
              "name": "u_worldRot",
              "type": 16,
              "count": 1
            },
            {
              "name": "u_timeDelta",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [],
          "stageFlags": 1,
          "binding": 2
        },
        {
          "name": "ColorConstant",
          "members": [
            {
              "name": "u_color_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 3
        },
        {
          "name": "RotationConstant",
          "members": [
            {
              "name": "u_rotation_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 4
        },
        {
          "name": "SizeConstant",
          "members": [
            {
              "name": "u_size_mode",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 5
        },
        {
          "name": "ForceConstant",
          "members": [
            {
              "name": "u_force_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_force_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 6
        },
        {
          "name": "VelocityConstant",
          "members": [
            {
              "name": "u_velocity_mode",
              "type": 5,
              "count": 1
            },
            {
              "name": "u_velocity_space",
              "type": 5,
              "count": 1
            }
          ],
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 7
        },
        {
          "name": "AnimationConstant",
          "members": [
            {
              "name": "u_anim_info",
              "type": 16,
              "count": 1
            }
          ],
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 8
        }
      ],
      "samplerTextures": [
        {
          "name": "color_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "COLOR_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 9
        },
        {
          "name": "rotation_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "ROTATION_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 10
        },
        {
          "name": "size_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "SIZE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 11
        },
        {
          "name": "force_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "FORCE_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 12
        },
        {
          "name": "velocity_over_time_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "VELOCITY_OVER_TIME_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 13
        },
        {
          "name": "texture_animation_tex0",
          "type": 28,
          "count": 1,
          "defines": [
            "TEXTURE_ANIMATION_MODULE_ENABLE"
          ],
          "stageFlags": 1,
          "binding": 14
        },
        {
          "name": "mainTexture",
          "type": 28,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "binding": 15
        }
      ],
      "samplers": [],
      "textures": [],
      "buffers": [],
      "images": [],
      "subpassInputs": [],
      "attributes": [
        {
          "name": "a_position_starttime",
          "defines": [],
          "format": 44,
          "location": 0
        },
        {
          "name": "a_size_uv",
          "defines": [],
          "format": 44,
          "location": 1
        },
        {
          "name": "a_rotation_uv",
          "defines": [],
          "format": 44,
          "location": 2
        },
        {
          "name": "a_color",
          "defines": [],
          "format": 44,
          "location": 3
        },
        {
          "name": "a_dir_life",
          "defines": [],
          "format": 44,
          "location": 4
        },
        {
          "name": "a_rndSeed",
          "defines": [],
          "format": 11,
          "location": 5
        },
        {
          "name": "a_texCoord",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 6
        },
        {
          "name": "a_texCoord3",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 7
        },
        {
          "name": "a_normal",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 32,
          "location": 8
        },
        {
          "name": "a_color1",
          "defines": [
            "CC_RENDER_MODE"
          ],
          "format": 44,
          "location": 9
        }
      ],
      "varyings": [
        {
          "name": "uv",
          "type": 14,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 0
        },
        {
          "name": "color",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 17,
          "location": 1
        }
      ],
      "fragColors": [
        {
          "name": "cc_FragColor",
          "typename": "vec4",
          "type": 16,
          "count": 1,
          "defines": [],
          "stageFlags": 16,
          "location": 0
        }
      ],
      "hash": 306521187,
      "glsl4": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(set = 1, binding = 0) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(set = 2, binding = 0) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nlayout(location = 0) out mediump vec2 uv;\nlayout(location = 1) out mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(set = 1, binding = 1) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(set = 1, binding = 2) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nlayout(location = 0) in vec4 a_position_starttime;\nlayout(location = 1) in vec4 a_size_uv;\nlayout(location = 2) in vec4 a_rotation_uv;\nlayout(location = 3) in vec4 a_color;\nlayout(location = 4) in vec4 a_dir_life;\nlayout(location = 5) in float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  layout(location = 6) in vec3 a_texCoord;\n  layout(location = 7) in vec3 a_texCoord3;\n  layout(location = 8) in vec3 a_normal;\n  layout(location = 9) in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 9) uniform sampler2D color_over_time_tex0;\n  layout(set = 1, binding = 3) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 10) uniform sampler2D rotation_over_time_tex0;\n  layout(set = 1, binding = 4) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 11) uniform sampler2D size_over_time_tex0;\n  layout(set = 1, binding = 5) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 12) uniform sampler2D force_over_time_tex0;\n  layout(set = 1, binding = 6) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  layout(set = 1, binding = 13) uniform sampler2D velocity_over_time_tex0;\n  layout(set = 1, binding = 7) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  layout(set = 1, binding = 14) uniform sampler2D texture_animation_tex0;\n  layout(set = 1, binding = 8) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(set = 0, binding = 0) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(set = 0, binding = 1) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nlayout(location = 0) in vec2 uv;\nlayout(location = 1) in vec4 color;\nlayout(set = 1, binding = 15) uniform sampler2D mainTexture;\nvec4 premultiplied () {\n  vec4 col = color * texture(mainTexture, uv) * color.a;\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = premultiplied(); }"
      },
      "glsl3": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nlayout(std140) uniform Constants {\n  vec4 mainTiling_Offset;\n  vec4 frameTile_velLenScale;\n  vec4 scale;\n  vec4 nodeRotation;\n};\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nlayout(std140) uniform CCLocal {\n  highp mat4 cc_matWorld;\n  highp mat4 cc_matWorldIT;\n  highp vec4 cc_lightingMapUVParam;\n};\nout mediump vec2 uv;\nout mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nlayout(std140) uniform SampleConstants {\n  vec4 u_sampleInfo;\n};\nlayout(std140) uniform TickConstants {\n  vec4 u_worldRot;\n  vec4 u_timeDelta;\n};\nin vec4 a_position_starttime;\nin vec4 a_size_uv;\nin vec4 a_rotation_uv;\nin vec4 a_color;\nin vec4 a_dir_life;\nin float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  in vec3 a_texCoord;\n  in vec3 a_texCoord3;\n  in vec3 a_normal;\n  in vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture(tex, coord);\n  vec4 b = texture(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n  layout(std140) uniform ColorConstant {\n    int u_color_mode;\n  };\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n  layout(std140) uniform RotationConstant {\n    int u_rotation_mode;\n  };\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n  layout(std140) uniform SizeConstant {\n    int u_size_mode;\n  };\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n  layout(std140) uniform ForceConstant {\n    int u_force_mode;\n    int u_force_space;\n  };\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n  layout(std140) uniform VelocityConstant {\n    int u_velocity_mode;\n    int u_velocity_space;\n  };\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n  layout(std140) uniform AnimationConstant {\n    vec4 u_anim_info;\n  };\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nlayout(std140) uniform CCGlobal {\n  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_nativeSize;\n};\nlayout(std140) uniform CCCamera {\n  highp   mat4 cc_matView;\n  highp   mat4 cc_matViewInv;\n  highp   mat4 cc_matProj;\n  highp   mat4 cc_matProjInv;\n  highp   mat4 cc_matViewProj;\n  highp   mat4 cc_matViewProjInv;\n  highp   vec4 cc_cameraPos;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_exposure;\n  mediump vec4 cc_mainLitDir;\n  mediump vec4 cc_mainLitColor;\n  mediump vec4 cc_ambientSky;\n  mediump vec4 cc_ambientGround;\n  mediump vec4 cc_fogColor;\n  mediump vec4 cc_fogBase;\n  mediump vec4 cc_fogAdd;\n  mediump vec4 cc_nearFar;\n  mediump vec4 cc_viewPort;\n};\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nin vec2 uv;\nin vec4 color;\nuniform sampler2D mainTexture;\nvec4 premultiplied () {\n  vec4 col = color * texture(mainTexture, uv) * color.a;\n  return CCFragOutput(col);\n}\nlayout(location = 0) out vec4 cc_FragColor;\nvoid main() { cc_FragColor = premultiplied(); }"
      },
      "glsl1": {
        "vert": "\nprecision mediump float;\nvec4 quaternionFromAxis (vec3 xAxis,vec3 yAxis,vec3 zAxis){\n  mat3 m = mat3(xAxis,yAxis,zAxis);\n  float trace = m[0][0] + m[1][1] + m[2][2];\n  vec4 quat;\n  if (trace > 0.) {\n    float s = 0.5 / sqrt(trace + 1.0);\n    quat.w = 0.25 / s;\n    quat.x = (m[2][1] - m[1][2]) * s;\n    quat.y = (m[0][2] - m[2][0]) * s;\n    quat.z = (m[1][0] - m[0][1]) * s;\n  } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) {\n    float s = 2.0 * sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]);\n    quat.w = (m[2][1] - m[1][2]) / s;\n    quat.x = 0.25 * s;\n    quat.y = (m[0][1] + m[1][0]) / s;\n    quat.z = (m[0][2] + m[2][0]) / s;\n  } else if (m[1][1] > m[2][2]) {\n    float s = 2.0 * sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]);\n    quat.w = (m[0][2] - m[2][0]) / s;\n    quat.x = (m[0][1] + m[1][0]) / s;\n    quat.y = 0.25 * s;\n    quat.z = (m[1][2] + m[2][1]) / s;\n  } else {\n    float s = 2.0 * sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]);\n    quat.w = (m[1][0] - m[0][1]) / s;\n    quat.x = (m[0][2] + m[2][0]) / s;\n    quat.y = (m[1][2] + m[2][1]) / s;\n    quat.z = 0.25 * s;\n  }\n  float len = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;\n  if (len > 0.) {\n    len = 1. / sqrt(len);\n    quat.x = quat.x * len;\n    quat.y = quat.y * len;\n    quat.z = quat.z * len;\n    quat.w = quat.w * len;\n  }\n  return quat;\n}\nvec4 quaternionFromEuler (vec3 angle){\n  float x = angle.x / 2.;\n  float y = angle.y / 2.;\n  float z = angle.z / 2.;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat = vec4(0);\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\nmat4 matrixFromRT (vec4 q, vec3 p){\n  float x2 = q.x + q.x;\n  float y2 = q.y + q.y;\n  float z2 = q.z + q.z;\n  float xx = q.x * x2;\n  float xy = q.x * y2;\n  float xz = q.x * z2;\n  float yy = q.y * y2;\n  float yz = q.y * z2;\n  float zz = q.z * z2;\n  float wx = q.w * x2;\n  float wy = q.w * y2;\n  float wz = q.w * z2;\n  return mat4(\n    1. - (yy + zz), xy + wz, xz - wy, 0,\n    xy - wz, 1. - (xx + zz), yz + wx, 0,\n    xz + wy, yz - wx, 1. - (xx + yy), 0,\n    p.x, p.y, p.z, 1\n  );\n}\nmat4 matFromRTS (vec4 q, vec3 t, vec3 s){\n  float x = q.x, y = q.y, z = q.z, w = q.w;\n  float x2 = x + x;\n  float y2 = y + y;\n  float z2 = z + z;\n  float xx = x * x2;\n  float xy = x * y2;\n  float xz = x * z2;\n  float yy = y * y2;\n  float yz = y * z2;\n  float zz = z * z2;\n  float wx = w * x2;\n  float wy = w * y2;\n  float wz = w * z2;\n  float sx = s.x;\n  float sy = s.y;\n  float sz = s.z;\n  return mat4((1. - (yy + zz)) * sx, (xy + wz) * sx, (xz - wy) * sx, 0,\n    (xy - wz) * sy, (1. - (xx + zz)) * sy, (yz + wx) * sy, 0,\n    (xz + wy) * sz, (yz - wx) * sz, (1. - (xx + yy)) * sz, 0,\n    t.x, t.y, t.z, 1);\n}\nvec4 quatMultiply (vec4 a, vec4 b){\n  vec4 quat;\n  quat.x = a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y;\n  quat.y = a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z;\n  quat.z = a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x;\n  quat.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;\n  return quat;\n}\nvoid rotateVecFromQuat (inout vec3 v, vec4 q){\n  float ix = q.w * v.x + q.y * v.z - q.z * v.y;\n  float iy = q.w * v.y + q.z * v.x - q.x * v.z;\n  float iz = q.w * v.z + q.x * v.y - q.y * v.x;\n  float iw = -q.x * v.x - q.y * v.y - q.z * v.z;\n  v.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;\n  v.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;\n  v.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;\n}\nvec3 rotateInLocalSpace (vec3 pos, vec3 xAxis, vec3 yAxis, vec3 zAxis, vec4 q){\n  vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n  vec4 rotQuat = quatMultiply(viewQuat, q);\n  rotateVecFromQuat(pos, rotQuat);\n  return pos;\n}\nmat3 quatToMat3(vec4 q) {\n  vec3 m0 = vec3(\n    1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z,\n    2.0 * q.x * q.y + 2.0 * q.w * q.z,\n    2.0 * q.x * q.z - 2.0 * q.w * q.y);\n\tvec3 m1 = vec3(\n    2.0 * q.x * q.y - 2.0 * q.w * q.z,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.z * q.z,\n    2.0 * q.y * q.z + 2.0 * q.w * q.x);\n\tvec3 m2 = vec3(\n    2.0 * q.x * q.z + 2.0 * q.w * q.y,\n    2.0 * q.y * q.z - 2.0 * q.w * q.x,\n    1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y);\n  return mat3(m0, m1, m2);\n}\nvec4 mat3ToQuat(mat3 mat) {\n  float tr = mat[0][0] + mat[1][1] + mat[2][2];\n\tfloat qw, qx, qy, qz;\n  if (tr > 0.0) {\n    float S = sqrt(tr + 1.0) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = 0.25 * S;\n\t  qx = (mat[1][2] - mat[2][1]) * invS;\n\t  qy = (mat[2][0] - mat[0][2]) * invS;\n\t  qz = (mat[0][1] - mat[1][0]) * invS;\n  } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) {\n    float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[1][2] - mat[2][1]) * invS;\n\t  qx = 0.25 * S;\n\t  qy = (mat[1][0] + mat[0][1]) * invS;\n\t  qz = (mat[2][0] + mat[0][2]) * invS;\n  } else if (mat[1][1] > mat[2][2]) {\n\t  float S = sqrt(1.0 + mat[1][1] - mat[0][0] - mat[2][2]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[2][0] - mat[0][2]) * invS;\n\t  qx = (mat[1][0] + mat[0][1]) * invS;\n\t  qy = 0.25 * S;\n\t  qz = (mat[2][1] + mat[1][2]) * invS;\n  } else {\n\t  float S = sqrt(1.0 + mat[2][2] - mat[0][0] - mat[1][1]) * 2.0;\n\t  float invS = 1.0 / S;\n\t  qw = (mat[0][1] - mat[1][0]) * invS;\n\t  qx = (mat[2][0] + mat[0][2]) * invS;\n\t  qy = (mat[2][1] + mat[1][2]) * invS;\n\t  qz = 0.25 * S;\n  }\n  return vec4(qx, qy, qz, qw);\n}\nvec4 eulerToQuat(vec3 euler) {\n  vec3 er = euler * 0.5;\n  float x = er.x, y = er.y, z = er.z;\n  float sx = sin(x);\n  float cx = cos(x);\n  float sy = sin(y);\n  float cy = cos(y);\n  float sz = sin(z);\n  float cz = cos(z);\n  vec4 quat;\n  quat.x = sx * cy * cz + cx * sy * sz;\n  quat.y = cx * sy * cz + sx * cy * sz;\n  quat.z = cx * cy * sz - sx * sy * cz;\n  quat.w = cx * cy * cz - sx * sy * sz;\n  return quat;\n}\n   uniform vec4 mainTiling_Offset;\n   uniform vec4 frameTile_velLenScale;\n   uniform vec4 scale;\n   uniform vec4 nodeRotation;\nuniform highp mat4 cc_matView;\n  uniform highp mat4 cc_matViewInv;\n  uniform highp mat4 cc_matViewProj;\n  uniform highp vec4 cc_cameraPos;\nuniform highp mat4 cc_matWorld;\nvarying mediump vec2 uv;\nvarying mediump vec4 color;\nvoid computeVertPos (inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n  , mat4 viewInv\n#endif\n#if CC_RENDER_MODE == 1\n  , vec3 eye\n  , vec4 velocity\n  , float velocityScale\n  , float lengthScale\n  , float xIndex\n#endif\n) {\n#if CC_RENDER_MODE == 0\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = normalize(vec3(viewInv[0][0], viewInv[1][0], viewInv[2][0]));\n  vec3 camY = normalize(vec3(viewInv[0][1], viewInv[1][1], viewInv[2][1]));\n  vec3 camZ = normalize(vec3(viewInv[0][2], viewInv[1][2], viewInv[2][2]));\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, camZ, q);\n#elif CC_RENDER_MODE == 1\n  vec3 camRight = normalize(cross(pos.xyz - eye, velocity.xyz)) * s.x;\n  vec3 camUp = velocity.xyz * velocityScale + normalize(velocity.xyz) * lengthScale * s.y;\n  pos.xyz += (camRight * abs(vertOffset.x) * sign(vertOffset.y)) - camUp * xIndex;\n#elif CC_RENDER_MODE == 2\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  vec3 camX = vec3(1, 0, 0);\n  vec3 camY = vec3(0, 0, -1);\n  pos.xyz += rotateInLocalSpace(viewSpaceVert, camX, camY, cross(camX, camY), q);\n#elif CC_RENDER_MODE == 3\n  vec3 viewSpaceVert = vec3(vertOffset.x * s.x, vertOffset.y * s.y, 0.);\n  rotateVecFromQuat(viewSpaceVert, q);\n  vec3 camX = normalize(vec3(cc_matView[0][0], cc_matView[1][0], cc_matView[2][0]));\n  vec3 camY = vec3(0, 1, 0);\n  vec3 offset = camX * viewSpaceVert.x + camY * viewSpaceVert.y;\n  pos.xyz += offset;\n#else\n  pos.x += vertOffset.x;\n  pos.y += vertOffset.y;\n#endif\n}\nvec2 computeUV (float frameIndex, vec2 vertIndex, vec2 frameTile){\n  vec2 aniUV = vec2(0, floor(frameIndex * frameTile.y));\n  aniUV.x = floor(frameIndex * frameTile.x * frameTile.y - aniUV.y * frameTile.x);\n#if CC_RENDER_MODE != 4\n  vertIndex.y = 1. - vertIndex.y;\n#endif\n  return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\n          uniform vec4 u_sampleInfo;\n    uniform vec4 u_worldRot;\n    uniform vec4 u_timeDelta;\nattribute vec4 a_position_starttime;\nattribute vec4 a_size_uv;\nattribute vec4 a_rotation_uv;\nattribute vec4 a_color;\nattribute vec4 a_dir_life;\nattribute float a_rndSeed;\n#if CC_RENDER_MODE == 4\n  attribute vec3 a_texCoord;\n  attribute vec3 a_texCoord3;\n  attribute vec3 a_normal;\n  attribute vec4 a_color1;\n#endif\nvec3 unpackCurveData (sampler2D tex, vec2 coord) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  return mix(a.xyz, b.xyz, c);\n}\nvec3 unpackCurveData (sampler2D tex, vec2 coord, out float w) {\n  vec4 a = texture2D(tex, coord);\n  vec4 b = texture2D(tex, coord + u_sampleInfo.y);\n  float c = fract(coord.x * u_sampleInfo.x);\n  w = mix(a.w, b.w, c);\n  return mix(a.xyz, b.xyz, c);\n}\nfloat pseudoRandom(float x) {\n#if USE_VK_SHADER\n  float o = x;\n  x = mod(x - 1.0, 2.0) - 1.0;\n  float freqVar = 10.16640753482;\n  float y = sin(freqVar * floor(o * 0.5 - 0.5));\n  float v = max(0.0, 1.0-abs(x));\n  v *= 0.7071067812;\n  v = y < 0.0 ? -v : v;\n  return v;\n#else\n  float seed = mod(x, 233280.);\n  float q = (seed * 9301. + 49297.) / 233280.;\n  return fract(q);\n#endif\n}\n#if COLOR_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D color_over_time_tex0;\n      uniform int u_color_mode;\n#endif\n#if ROTATION_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D rotation_over_time_tex0;\n      uniform int u_rotation_mode;\n#endif\n#if SIZE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D size_over_time_tex0;\n      uniform int u_size_mode;\n#endif\n#if FORCE_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D force_over_time_tex0;\n      uniform int u_force_mode;\n    uniform int u_force_space;\n#endif\n#if VELOCITY_OVER_TIME_MODULE_ENABLE\n  uniform sampler2D velocity_over_time_tex0;\n      uniform int u_velocity_mode;\n    uniform int u_velocity_space;\n#endif\n#if TEXTURE_ANIMATION_MODULE_ENABLE\n  uniform sampler2D texture_animation_tex0;\n      uniform vec4 u_anim_info;\n#endif\nfloat repeat (float t, float length) {\n  return t - floor(t / length) * length;\n}\nvec4 rotateQuat (vec4 p, vec4 q) {\n  vec3 iv = cross(q.xyz, p.xyz) + q.w * p.xyz;\n  vec3 res = p.xyz + 2.0 * cross(q.xyz, iv);\n  return vec4(res.xyz, p.w);\n}\nvec4 gpvs_main () {\n  float activeTime = u_timeDelta.x - a_position_starttime.w;\n  float normalizedTime = clamp(activeTime / a_dir_life.w, 0.0, 1.0);\n  vec2 timeCoord0 = vec2(normalizedTime, 0.);\n  vec2 timeCoord1 = vec2(normalizedTime, 1.);\n  #if CC_RENDER_MODE == 4\n    vec2 vertIdx = vec2(a_texCoord.x, a_texCoord.y);\n  #else\n    vec2 vertIdx = vec2(a_size_uv.w, a_rotation_uv.w);\n  #endif\n  vec4 velocity = vec4(a_dir_life.xyz, 0.);\n  vec4 pos = vec4(a_position_starttime.xyz, 1.);\n  vec3 size = a_size_uv.xyz;\n  #if SIZE_OVER_TIME_MODULE_ENABLE\n    if (u_size_mode == 1) {\n      size *= unpackCurveData(size_over_time_tex0, timeCoord0);\n    } else {\n      vec3 size_0 = unpackCurveData(size_over_time_tex0, timeCoord0);\n      vec3 size_1 = unpackCurveData(size_over_time_tex0, timeCoord1);\n      float factor_s = pseudoRandom(a_rndSeed + 39825.);\n      size *= mix(size_0, size_1, factor_s);\n    }\n  #endif\n  vec3 compScale = scale.xyz * size;\n  #if FORCE_OVER_TIME_MODULE_ENABLE\n    vec3 forceAnim = vec3(0.);\n    if (u_force_mode == 1) {\n      forceAnim = unpackCurveData(force_over_time_tex0, timeCoord0);\n    } else {\n      vec3 force_0 = unpackCurveData(force_over_time_tex0, timeCoord0);\n      vec3 force_1 = unpackCurveData(force_over_time_tex0, timeCoord1);\n      float factor_f =  pseudoRandom(a_rndSeed + 212165.);\n      forceAnim = mix(force_0, force_1, factor_f);\n    }\n    vec4 forceTrack = vec4(forceAnim, 0.);\n    if (u_force_space == 0) {\n      forceTrack = rotateQuat(forceTrack, u_worldRot);\n    }\n    velocity.xyz += forceTrack.xyz;\n  #endif\n  #if VELOCITY_OVER_TIME_MODULE_ENABLE\n    float speedModifier0 = 1.;\n    float speedModifier1 = 1.;\n    vec3 velocityAnim = vec3(0.);\n    if (u_velocity_mode == 1) {\n      velocityAnim = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n    } else {\n      vec3 vectory_0 = unpackCurveData(velocity_over_time_tex0, timeCoord0, speedModifier0);\n      vec3 vectory_1 = unpackCurveData(velocity_over_time_tex0, timeCoord1, speedModifier1);\n      float factor_v = pseudoRandom(a_rndSeed + 197866.);\n      velocityAnim = mix(vectory_0, vectory_1, factor_v);\n      speedModifier0 = mix(speedModifier0, speedModifier1, factor_v);\n    }\n    vec4 velocityTrack = vec4(velocityAnim, 0.);\n    if (u_velocity_space == 0) {\n      velocityTrack = rotateQuat(velocityTrack, u_worldRot);\n    }\n    velocity.xyz += velocityTrack.xyz;\n    velocity.xyz *= speedModifier0;\n  #endif\n  pos.xyz += velocity.xyz * normalizedTime * a_dir_life.w;\n  #if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_RENDER_MODE == 1\n      velocity = rotateQuat(velocity, u_worldRot);\n    #endif\n  #endif\n  vec3 startRotation = a_rotation_uv.xyz;\n  #if CC_RENDER_MODE != 4\n    #if CC_RENDER_MODE == 0\n      vec3 rotEuler = startRotation.xyz;\n    #elif CC_RENDER_MODE == 1\n      vec3 rotEuler = vec3(0.);\n    #else\n      vec3 rotEuler = vec3(0., 0., startRotation.z);\n    #endif\n    vec4 rot = quaternionFromEuler(rotEuler);\n  #else\n    vec4 rot = quaternionFromEuler(startRotation);\n  #endif\n  #if ROTATION_OVER_TIME_MODULE_ENABLE\n    if (u_rotation_mode == 1) {\n      vec3 euler = unpackCurveData(rotation_over_time_tex0, timeCoord0) * normalizedTime * a_dir_life.w;\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    } else {\n      vec3 rotation_0 = unpackCurveData(rotation_over_time_tex0, timeCoord0);\n      vec3 rotation_1 = unpackCurveData(rotation_over_time_tex0, timeCoord1);\n      float factor_r = pseudoRandom(a_rndSeed + 125292.);\n      vec3 euler = mix(rotation_0, rotation_1, factor_r) * normalizedTime * a_dir_life.w;\n      #if CC_RENDER_MODE == 3 || CC_RENDER_MODE == 2\n        euler = vec3(0.0, 0.0, euler.z);\n      #endif\n      vec4 quat = eulerToQuat(euler);\n      mat3 mLocal = quatToMat3(quat);\n      mat3 mStart = quatToMat3(rot);\n      rot = mat3ToQuat(mStart * mLocal);\n    }\n  #endif\n  #if COLOR_OVER_TIME_MODULE_ENABLE\n    if (u_color_mode == 1) {\n      color = a_color * texture2D(color_over_time_tex0, timeCoord0);\n    } else {\n      vec4 color_0 = texture2D(color_over_time_tex0, timeCoord0);\n      vec4 color_1 = texture2D(color_over_time_tex0, timeCoord1);\n      float factor_c = pseudoRandom(a_rndSeed + 91041.);\n      color = a_color * mix(color_0, color_1, factor_c);\n    }\n  #else\n    color = a_color;\n  #endif\n  #if CC_RENDER_MODE != 4\n    vec2 cornerOffset = vec2((vertIdx - 0.5));\n    #if CC_RENDER_MODE == 1\n      rot = vec4(0.0, 0.0, 0.0, 1.0);\n    #endif\n    computeVertPos(pos, cornerOffset, rot, compScale\n      #if CC_RENDER_MODE == 0 || CC_RENDER_MODE == 3\n        , cc_matViewInv\n      #endif\n      #if CC_RENDER_MODE == 1\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_size_uv.w\n      #endif\n    );\n  #else\n    mat3 rotMat = quatToMat3(rot);\n    mat3 nodeMat = quatToMat3(nodeRotation);\n    rotMat = nodeMat * rotMat;\n    rot = mat3ToQuat(rotMat);\n    mat4 xformNoScale = matrixFromRT(rot, pos.xyz);\n    mat4 xform = matFromRTS(rot, pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color *= a_color1;\n  #endif\n  pos = cc_matViewProj * pos;\n  float frameIndex = 0.;\n  #if TEXTURE_ANIMATION_MODULE_ENABLE\n    float startFrame = 0.;\n    vec3 frameInfo = vec3(0.);\n    if (int(u_anim_info.x) == 1) {\n      frameInfo = unpackCurveData(texture_animation_tex0, timeCoord0);\n    } else {\n      vec3 frameInfo0 = unpackCurveData(texture_animation_tex0, timeCoord0);\n      vec3 frameInfo1 = unpackCurveData(texture_animation_tex0, timeCoord1);\n      float factor_t = pseudoRandom(a_rndSeed + 90794.);\n      frameInfo = mix(frameInfo0, frameInfo1, factor_t);\n    }\n    startFrame = frameInfo.x / u_anim_info.y;\n    frameIndex = repeat(u_anim_info.z * (frameInfo.y + startFrame), 1.);\n  #endif\n  uv = computeUV(frameIndex, vertIdx, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n  return pos;\n}\nvoid main() { gl_Position = gpvs_main(); }",
        "frag": "\nprecision mediump float;\nvec4 CCFragOutput (vec4 color) {\n  return color;\n}\nvarying vec2 uv;\nvarying vec4 color;\nuniform sampler2D mainTexture;\nvec4 premultiplied () {\n  vec4 col = color * texture2D(mainTexture, uv) * color.a;\n  return CCFragOutput(col);\n}\nvoid main() { gl_FragColor = premultiplied(); }"
      },
      "builtins": {
        "globals": {
          "blocks": [
            {
              "name": "CCGlobal",
              "defines": []
            },
            {
              "name": "CCCamera",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "locals": {
          "blocks": [
            {
              "name": "CCLocal",
              "defines": []
            }
          ],
          "samplerTextures": [],
          "buffers": [],
          "images": []
        },
        "statistics": {
          "CC_EFFECT_USED_VERTEX_UNIFORM_VECTORS": 63,
          "CC_EFFECT_USED_FRAGMENT_UNIFORM_VECTORS": 39
        }
      },
      "defines": [
        {
          "name": "CC_RENDER_MODE",
          "type": "number",
          "defines": [],
          "range": [
            0,
            4
          ]
        },
        {
          "name": "USE_VK_SHADER",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "COLOR_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "ROTATION_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "SIZE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "FORCE_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "VELOCITY_OVER_TIME_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "TEXTURE_ANIMATION_MODULE_ENABLE",
          "type": "boolean",
          "defines": []
        },
        {
          "name": "CC_USE_WORLD_SPACE",
          "type": "boolean",
          "defines": []
        }
      ],
      "name": "builtin-particle-gpu|particle-vs-gpu:gpvs_main|no-tint-fs:premultiplied"
    }
  ],
  "combinations": [],
  "hideInEditor": false
}