[
  1,
  [
    "60AwGqM1dKELCGhPAR+jK6",
    "82migssElAGb04Ws6NimQX"
  ],
  [
    "mainTexture",
    "_effectAsset"
  ],
  [
    [
      "cc.Material",
      [
        "_name",
        "_techniqueData"
      ],
      2,
      11
    ],
    [
      "cc.EffectAsset",
      [
        "_name",
        "shaders",
        "techniques"
      ],
      0
    ]
  ],
  [
    [
      0,
      0,
      1,
      2
    ],
    [
      1,
      0,
      1,
      2,
      4
    ]
  ],
  [
    [
      [
        [
          0,
          "builtin-3d-particle",
          [
            {},
            "0",
            11,
            [
              {
                "defines": {
                  "CC_USE_BILLBOARD": true,
                  "CC_USE_STRETCHED_BILLBOARD": false,
                  "CC_USE_HORIZONTAL_BILLBOARD": false,
                  "CC_USE_VERTICAL_BILLBOARD": false,
                  "CC_USE_MESH": false
                }
              },
              "props",
              11,
              [
                {},
                "mainTiling_Offset",
                8,
                [
                  2,
                  1,
                  1,
                  0,
                  0
                ],
                "tintColor",
                8,
                [
                  4,
                  2141562284
                ],
                "mainTexture",
                6,
                0
              ]
            ]
          ]
        ]
      ],
      0,
      0,
      [
        0,
        0
      ],
      [
        0,
        1
      ],
      [
        0,
        1
      ]
    ],
    [
      [
        [
          1,
          "builtin-3d-particle",
          [
            {
              "hash": 1682193167,
              "record": null,
              "name": "builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:add",
              "glsl3": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform Constants{\n    vec4 mainTiling_Offset;\n    vec4 frameTile_velLenScale;\n    vec4 scale;\n};\nuniform CCGlobal {\n  mat4 cc_matView;\n  mat4 cc_matViewInv;\n  mat4 cc_matProj;\n  mat4 cc_matProjInv;\n  mat4 cc_matViewProj;\n  mat4 cc_matViewProjInv;\n  vec4 cc_cameraPos;\n  vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n};\nuniform CCLocal {\n  mat4 cc_matWorld;\n  mat4 cc_matWorldIT;\n};\nout vec2 uv;\nout vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nin vec3 a_position;\nin vec3 a_texCoord;\nin vec3 a_texCoord1;\nin vec3 a_texCoord2;\nin vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    in vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    in vec3 a_texCoord3;\n    in vec3 a_normal;\n    in vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn color;\n}\nin vec2 uv;\nin vec4 color;\nuniform sampler2D mainTexture;\nuniform FragConstants {\n  vec4 tintColor;\n};\nvec4 add () {\n  vec4 col = 2.0 * color * tintColor * texture(mainTexture, uv);\n  return CCFragOutput(col);\n}\nout vec4 cc_FragColor;\nvoid main() { cc_FragColor = add(); }"
              },
              "glsl1": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform vec4 mainTiling_Offset;\nuniform vec4 frameTile_velLenScale;\nuniform vec4 scale;\nuniform mat4 cc_matView;\nuniform mat4 cc_matViewInv;\nuniform mat4 cc_matViewProj;\nuniform vec4 cc_cameraPos;\nuniform mat4 cc_matWorld;\nvarying vec2 uv;\nvarying vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nattribute vec3 a_position;\nattribute vec3 a_texCoord;\nattribute vec3 a_texCoord1;\nattribute vec3 a_texCoord2;\nattribute vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    attribute vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    attribute vec3 a_texCoord3;\n    attribute vec3 a_normal;\n    attribute vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn color;\n}\nvarying vec2 uv;\nvarying vec4 color;\nuniform sampler2D mainTexture;\nuniform 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": []
                    }
                  ],
                  "samplers": []
                },
                "locals": {
                  "blocks": [
                    {
                      "name": "CCLocal",
                      "defines": []
                    }
                  ],
                  "samplers": []
                }
              },
              "defines": [
                {
                  "name": "CC_USE_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_STRETCHED_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_HORIZONTAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_VERTICAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_MESH",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_WORLD_SPACE",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "OUTPUT_TO_GAMMA",
                  "type": "boolean",
                  "defines": []
                }
              ],
              "blocks": [
                {
                  "name": "Constants",
                  "binding": 0,
                  "members": [
                    {
                      "name": "mainTiling_Offset",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "frameTile_velLenScale",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "scale",
                      "type": 16,
                      "count": 1
                    }
                  ],
                  "defines": []
                },
                {
                  "name": "FragConstants",
                  "binding": 1,
                  "members": [
                    {
                      "name": "tintColor",
                      "type": 16,
                      "count": 1
                    }
                  ],
                  "defines": []
                }
              ],
              "samplers": [
                {
                  "name": "mainTexture",
                  "type": 29,
                  "count": 1,
                  "binding": 30,
                  "defines": []
                }
              ]
            },
            {
              "hash": 1933642753,
              "record": null,
              "name": "builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:multiply",
              "glsl3": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform Constants{\n    vec4 mainTiling_Offset;\n    vec4 frameTile_velLenScale;\n    vec4 scale;\n};\nuniform CCGlobal {\n  mat4 cc_matView;\n  mat4 cc_matViewInv;\n  mat4 cc_matProj;\n  mat4 cc_matProjInv;\n  mat4 cc_matViewProj;\n  mat4 cc_matViewProjInv;\n  vec4 cc_cameraPos;\n  vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n};\nuniform CCLocal {\n  mat4 cc_matWorld;\n  mat4 cc_matWorldIT;\n};\nout vec2 uv;\nout vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nin vec3 a_position;\nin vec3 a_texCoord;\nin vec3 a_texCoord1;\nin vec3 a_texCoord2;\nin vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    in vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    in vec3 a_texCoord3;\n    in vec3 a_normal;\n    in vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn color;\n}\nin vec2 uv;\nin vec4 color;\nuniform sampler2D mainTexture;\nuniform 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  col.a = (1.0 - texColor.a) * (tintColor.a * color.a * 2.0);\n  return CCFragOutput(col);\n}\nout vec4 cc_FragColor;\nvoid main() { cc_FragColor = multiply(); }"
              },
              "glsl1": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform vec4 mainTiling_Offset;\nuniform vec4 frameTile_velLenScale;\nuniform vec4 scale;\nuniform mat4 cc_matView;\nuniform mat4 cc_matViewInv;\nuniform mat4 cc_matViewProj;\nuniform vec4 cc_cameraPos;\nuniform mat4 cc_matWorld;\nvarying vec2 uv;\nvarying vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nattribute vec3 a_position;\nattribute vec3 a_texCoord;\nattribute vec3 a_texCoord1;\nattribute vec3 a_texCoord2;\nattribute vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    attribute vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    attribute vec3 a_texCoord3;\n    attribute vec3 a_normal;\n    attribute vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn color;\n}\nvarying vec2 uv;\nvarying vec4 color;\nuniform sampler2D mainTexture;\nuniform 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  col.a = (1.0 - texColor.a) * (tintColor.a * color.a * 2.0);\n  return CCFragOutput(col);\n}\nvoid main() { gl_FragColor = multiply(); }"
              },
              "builtins": {
                "globals": {
                  "blocks": [
                    {
                      "name": "CCGlobal",
                      "defines": []
                    }
                  ],
                  "samplers": []
                },
                "locals": {
                  "blocks": [
                    {
                      "name": "CCLocal",
                      "defines": []
                    }
                  ],
                  "samplers": []
                }
              },
              "defines": [
                {
                  "name": "CC_USE_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_STRETCHED_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_HORIZONTAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_VERTICAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_MESH",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_WORLD_SPACE",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "OUTPUT_TO_GAMMA",
                  "type": "boolean",
                  "defines": []
                }
              ],
              "blocks": [
                {
                  "name": "Constants",
                  "binding": 0,
                  "members": [
                    {
                      "name": "mainTiling_Offset",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "frameTile_velLenScale",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "scale",
                      "type": 16,
                      "count": 1
                    }
                  ],
                  "defines": []
                },
                {
                  "name": "FragConstants",
                  "binding": 1,
                  "members": [
                    {
                      "name": "tintColor",
                      "type": 16,
                      "count": 1
                    }
                  ],
                  "defines": []
                }
              ],
              "samplers": [
                {
                  "name": "mainTexture",
                  "type": 29,
                  "count": 1,
                  "binding": 30,
                  "defines": []
                }
              ]
            },
            {
              "hash": 1851787849,
              "record": null,
              "name": "builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:addSmooth",
              "glsl3": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform Constants{\n    vec4 mainTiling_Offset;\n    vec4 frameTile_velLenScale;\n    vec4 scale;\n};\nuniform CCGlobal {\n  mat4 cc_matView;\n  mat4 cc_matViewInv;\n  mat4 cc_matProj;\n  mat4 cc_matProjInv;\n  mat4 cc_matViewProj;\n  mat4 cc_matViewProjInv;\n  vec4 cc_cameraPos;\n  vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n};\nuniform CCLocal {\n  mat4 cc_matWorld;\n  mat4 cc_matWorldIT;\n};\nout vec2 uv;\nout vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nin vec3 a_position;\nin vec3 a_texCoord;\nin vec3 a_texCoord1;\nin vec3 a_texCoord2;\nin vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    in vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    in vec3 a_texCoord3;\n    in vec3 a_normal;\n    in vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn 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}\nout vec4 cc_FragColor;\nvoid main() { cc_FragColor = addSmooth(); }"
              },
              "glsl1": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform vec4 mainTiling_Offset;\nuniform vec4 frameTile_velLenScale;\nuniform vec4 scale;\nuniform mat4 cc_matView;\nuniform mat4 cc_matViewInv;\nuniform mat4 cc_matViewProj;\nuniform vec4 cc_cameraPos;\nuniform mat4 cc_matWorld;\nvarying vec2 uv;\nvarying vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nattribute vec3 a_position;\nattribute vec3 a_texCoord;\nattribute vec3 a_texCoord1;\nattribute vec3 a_texCoord2;\nattribute vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    attribute vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    attribute vec3 a_texCoord3;\n    attribute vec3 a_normal;\n    attribute vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn 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": []
                    }
                  ],
                  "samplers": []
                },
                "locals": {
                  "blocks": [
                    {
                      "name": "CCLocal",
                      "defines": []
                    }
                  ],
                  "samplers": []
                }
              },
              "defines": [
                {
                  "name": "CC_USE_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_STRETCHED_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_HORIZONTAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_VERTICAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_MESH",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_WORLD_SPACE",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "OUTPUT_TO_GAMMA",
                  "type": "boolean",
                  "defines": []
                }
              ],
              "blocks": [
                {
                  "name": "Constants",
                  "binding": 0,
                  "members": [
                    {
                      "name": "mainTiling_Offset",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "frameTile_velLenScale",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "scale",
                      "type": 16,
                      "count": 1
                    }
                  ],
                  "defines": []
                }
              ],
              "samplers": [
                {
                  "name": "mainTexture",
                  "type": 29,
                  "count": 1,
                  "binding": 30,
                  "defines": []
                }
              ]
            },
            {
              "hash": 145387972,
              "record": null,
              "name": "builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:premultiplied",
              "glsl3": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform Constants{\n    vec4 mainTiling_Offset;\n    vec4 frameTile_velLenScale;\n    vec4 scale;\n};\nuniform CCGlobal {\n  mat4 cc_matView;\n  mat4 cc_matViewInv;\n  mat4 cc_matProj;\n  mat4 cc_matProjInv;\n  mat4 cc_matViewProj;\n  mat4 cc_matViewProjInv;\n  vec4 cc_cameraPos;\n  vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n};\nuniform CCLocal {\n  mat4 cc_matWorld;\n  mat4 cc_matWorldIT;\n};\nout vec2 uv;\nout vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nin vec3 a_position;\nin vec3 a_texCoord;\nin vec3 a_texCoord1;\nin vec3 a_texCoord2;\nin vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    in vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    in vec3 a_texCoord3;\n    in vec3 a_normal;\n    in vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn 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}\nout vec4 cc_FragColor;\nvoid main() { cc_FragColor = premultiplied(); }"
              },
              "glsl1": {
                "vert": "\nprecision highp 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    float z = pos.z;\n    float x = pos.x;\n    float y = pos.y;\n    vec4 viewQuat = quaternionFromAxis(xAxis, yAxis, zAxis);\n    vec4 rotQuat = quatMultiply(viewQuat, q);\n    rotateVecFromQuat(pos, rotQuat);\n    return pos;\n}\nvoid rotateCorner(inout vec2 corner, float angle){\n    float xOS = cos(angle) * corner.x - sin(angle) * corner.y;\n    float yOS = sin(angle) * corner.x + cos(angle) * corner.y;\n    corner.x = xOS;\n    corner.y = yOS;\n}\nuniform vec4 mainTiling_Offset;\nuniform vec4 frameTile_velLenScale;\nuniform vec4 scale;\nuniform mat4 cc_matView;\nuniform mat4 cc_matViewInv;\nuniform mat4 cc_matViewProj;\nuniform vec4 cc_cameraPos;\nuniform mat4 cc_matWorld;\nvarying vec2 uv;\nvarying vec4 color;\nvoid computeVertPos(inout vec4 pos, vec2 vertOffset, vec4 q, vec3 s\n#if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n    , mat4 viewInv\n#endif\n#if CC_USE_STRETCHED_BILLBOARD\n    , vec3 eye\n    , vec4 velocity\n    , float velocityScale\n    , float lengthScale\n    , float xIndex\n#endif\n) {\n#if CC_USE_BILLBOARD\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_USE_STRETCHED_BILLBOARD\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_USE_HORIZONTAL_BILLBOARD\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_USE_VERTICAL_BILLBOARD\n    vec2 viewSpaceVert = vec2(vertOffset.x * s.x, vertOffset.y * s.y);\n    rotateCorner(viewSpaceVert, q.z);\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_USE_MESH\n    vertIndex.y = 1. - vertIndex.y;\n#endif\n    return (aniUV.xy + vertIndex) / vec2(frameTile.x, frameTile.y);\n}\nattribute vec3 a_position;\nattribute vec3 a_texCoord;\nattribute vec3 a_texCoord1;\nattribute vec3 a_texCoord2;\nattribute vec4 a_color;\n#if CC_USE_STRETCHED_BILLBOARD\n    attribute vec3 a_color1;\n#endif\n#if CC_USE_MESH\n    attribute vec3 a_texCoord3;\n    attribute vec3 a_normal;\n    attribute vec4 a_color1;\n#endif\nvec4 lpvs_main() {\n    vec3 compScale = scale.xyz * a_texCoord1;\n    vec4 pos = vec4(a_position, 1);\n#if CC_USE_STRETCHED_BILLBOARD\n    vec4 velocity = vec4(a_color1.xyz, 0);\n#endif\n#if !CC_USE_WORLD_SPACE\n    pos = cc_matWorld * pos;\n    #if CC_USE_STRETCHED_BILLBOARD\n        velocity = cc_matWorld * velocity;\n    #endif\n#endif\n#if !CC_USE_MESH\n    vec2 cornerOffset = vec2((a_texCoord.xy - 0.5));\n    #if CC_USE_BILLBOARD\n        vec3 rotEuler = a_texCoord2;\n    #elif CC_USE_STRETCHED_BILLBOARD\n        vec3 rotEuler = vec3(0.);\n    #else\n        vec3 rotEuler = vec3(0., 0., a_texCoord2.z);\n    #endif\n    computeVertPos(pos, cornerOffset, quaternionFromEuler(rotEuler), compScale\n    #if CC_USE_BILLBOARD || CC_USE_VERTICAL_BILLBOARD\n        , cc_matViewInv\n    #endif\n    #if CC_USE_STRETCHED_BILLBOARD\n        , cc_cameraPos.xyz\n        , velocity\n        , frameTile_velLenScale.z\n        , frameTile_velLenScale.w\n        , a_texCoord.x\n    #endif\n    );\n    color = a_color;\n#else\n    mat4 xformNoScale = matrixFromRT(quaternionFromEuler(a_texCoord2), pos.xyz);\n    mat4 xform = matFromRTS(quaternionFromEuler(a_texCoord2), pos.xyz, compScale);\n    pos = xform * vec4(a_texCoord3, 1);\n    vec4 normal = xformNoScale * vec4(a_normal, 0);\n    color = a_color * a_color1;\n#endif\n    uv = computeUV(a_texCoord.z, a_texCoord.xy, frameTile_velLenScale.xy) * mainTiling_Offset.xy + mainTiling_Offset.zw;\n    pos = cc_matViewProj * pos;\n    return pos;\n}\nvoid main() { gl_Position = lpvs_main(); }",
                "frag": "\nprecision highp float;\nvec4 CCFragOutput (vec4 color) {\n  #if OUTPUT_TO_GAMMA\n    color.rgb = sqrt(color.rgb);\n  #endif\n\treturn 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": []
                    }
                  ],
                  "samplers": []
                },
                "locals": {
                  "blocks": [
                    {
                      "name": "CCLocal",
                      "defines": []
                    }
                  ],
                  "samplers": []
                }
              },
              "defines": [
                {
                  "name": "CC_USE_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_STRETCHED_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_HORIZONTAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_VERTICAL_BILLBOARD",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_MESH",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "CC_USE_WORLD_SPACE",
                  "type": "boolean",
                  "defines": []
                },
                {
                  "name": "OUTPUT_TO_GAMMA",
                  "type": "boolean",
                  "defines": []
                }
              ],
              "blocks": [
                {
                  "name": "Constants",
                  "binding": 0,
                  "members": [
                    {
                      "name": "mainTiling_Offset",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "frameTile_velLenScale",
                      "type": 16,
                      "count": 1
                    },
                    {
                      "name": "scale",
                      "type": 16,
                      "count": 1
                    }
                  ],
                  "defines": []
                }
              ],
              "samplers": [
                {
                  "name": "mainTexture",
                  "type": 29,
                  "count": 1,
                  "binding": 30,
                  "defines": []
                }
              ]
            }
          ],
          [
            {
              "name": "add",
              "passes": [
                {
                  "program": "builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:add",
                  "rasterizerState": {
                    "cullMode": 0
                  },
                  "blendState": {
                    "targets": [
                      {
                        "blend": true,
                        "blendSrc": 770,
                        "blendDst": 1,
                        "blendSrcAlpha": 770,
                        "blendDstAlpha": 1
                      }
                    ]
                  },
                  "depthStencilState": {
                    "depthTest": true,
                    "depthWrite": false
                  },
                  "properties": {
                    "mainTexture": {
                      "value": "grey",
                      "type": 29
                    },
                    "mainTiling_Offset": {
                      "type": 16,
                      "value": [
                        1,
                        1,
                        0,
                        0
                      ]
                    },
                    "tintColor": {
                      "type": 16,
                      "value": [
                        0.5,
                        0.5,
                        0.5,
                        0.5
                      ],
                      "inspector": {
                        "type": "color"
                      }
                    }
                  }
                }
              ]
            },
            {
              "name": "alpha-blend",
              "passes": [
                {
                  "program": "builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:add",
                  "rasterizerState": {
                    "cullMode": 0
                  },
                  "blendState": {
                    "targets": [
                      {
                        "blend": true,
                        "blendSrc": 770,
                        "blendDst": 771,
                        "blendSrcAlpha": 770,
                        "blendDstAlpha": 771
                      }
                    ]
                  },
                  "depthStencilState": {
                    "depthTest": true,
                    "depthWrite": false
                  },
                  "properties": {
                    "mainTexture": {
                      "value": "grey",
                      "type": 29
                    },
                    "mainTiling_Offset": {
                      "type": 16,
                      "value": [
                        1,
                        1,
                        0,
                        0
                      ]
                    },
                    "tintColor": {
                      "type": 16,
                      "value": [
                        0.5,
                        0.5,
                        0.5,
                        0.5
                      ],
                      "inspector": {
                        "type": "color"
                      }
                    }
                  }
                }
              ]
            },
            {
              "name": "add-multiply",
              "passes": [
                {
                  "program": "builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:multiply",
                  "rasterizerState": {
                    "cullMode": 0
                  },
                  "blendState": {
                    "targets": [
                      {
                        "blend": true,
                        "blendSrc": 770,
                        "blendDst": 771,
                        "blendSrcAlpha": 770,
                        "blendDstAlpha": 771
                      }
                    ]
                  },
                  "depthStencilState": {
                    "depthTest": true,
                    "depthWrite": false
                  },
                  "properties": {
                    "mainTexture": {
                      "value": "grey",
                      "type": 29
                    },
                    "mainTiling_Offset": {
                      "type": 16,
                      "value": [
                        1,
                        1,
                        0,
                        0
                      ]
                    },
                    "tintColor": {
                      "type": 16,
                      "value": [
                        0.5,
                        0.5,
                        0.5,
                        0.5
                      ],
                      "inspector": {
                        "type": "color"
                      }
                    }
                  }
                }
              ]
            },
            {
              "name": "add-smooth",
              "passes": [
                {
                  "program": "builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:addSmooth",
                  "rasterizerState": {
                    "cullMode": 0
                  },
                  "blendState": {
                    "targets": [
                      {
                        "blend": true,
                        "blendSrc": 770,
                        "blendDst": 771,
                        "blendSrcAlpha": 770,
                        "blendDstAlpha": 771
                      }
                    ]
                  },
                  "depthStencilState": {
                    "depthTest": true,
                    "depthWrite": false
                  },
                  "properties": {
                    "mainTexture": {
                      "value": "grey",
                      "type": 29
                    },
                    "mainTiling_Offset": {
                      "type": 16,
                      "value": [
                        1,
                        1,
                        0,
                        0
                      ]
                    }
                  }
                }
              ]
            },
            {
              "name": "premultiply-blend",
              "passes": [
                {
                  "program": "builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:premultiplied",
                  "rasterizerState": {
                    "cullMode": 0
                  },
                  "blendState": {
                    "targets": [
                      {
                        "blend": true,
                        "blendSrc": 770,
                        "blendDst": 771,
                        "blendSrcAlpha": 770,
                        "blendDstAlpha": 771
                      }
                    ]
                  },
                  "depthStencilState": {
                    "depthTest": true,
                    "depthWrite": false
                  },
                  "properties": {
                    "mainTexture": {
                      "value": "grey",
                      "type": 29
                    },
                    "mainTiling_Offset": {
                      "type": 16,
                      "value": [
                        1,
                        1,
                        0,
                        0
                      ]
                    }
                  }
                }
              ]
            }
          ]
        ]
      ],
      0,
      0,
      [],
      [],
      []
    ]
  ]
]