{"__type__":"cc.EffectAsset","_name":"builtin-3d-particle","techniques":[{"name":"add","passes":[{"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":{"value":[1,1,0,0],"type":16},"tintColor":{"value":[0.5,0.5,0.5,0.5],"inspector":{"type":"color"},"type":16}},"program":"builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:add"}]},{"name":"alpha-blend","passes":[{"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":{"value":[1,1,0,0],"type":16},"tintColor":{"value":[0.5,0.5,0.5,0.5],"inspector":{"type":"color"},"type":16}},"program":"builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:add"}]},{"name":"add-multiply","passes":[{"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":{"value":[1,1,0,0],"type":16},"tintColor":{"value":[0.5,0.5,0.5,0.5],"inspector":{"type":"color"},"type":16}},"program":"builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:multiply"}]},{"name":"add-smooth","passes":[{"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":{"value":[1,1,0,0],"type":16}},"program":"builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:addSmooth"}]},{"name":"premultiply-blend","passes":[{"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":{"value":[1,1,0,0],"type":16}},"program":"builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:premultiplied"}]}],"shaders":[{"hash":2425527384,"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  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_nativeSize;\n  highp   mat4 cc_matView;\n  mediump mat4 cc_matViewInv;\n  mediump mat4 cc_matProj;\n  mediump mat4 cc_matProjInv;\n  mediump mat4 cc_matViewProj;\n  mediump mat4 cc_matViewProjInv;\n  mediump vec4 cc_cameraPos;\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 highp mat4 cc_matView;\nuniform mediump mat4 cc_matViewInv;\nuniform mediump mat4 cc_matViewProj;\nuniform mediump 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","members":[{"name":"mainTiling_Offset","type":16,"count":1},{"name":"frameTile_velLenScale","type":16,"count":1},{"name":"scale","type":16,"count":1}],"defines":[],"binding":0},{"name":"FragConstants","members":[{"name":"tintColor","type":16,"count":1}],"defines":[],"binding":1}],"samplers":[{"name":"mainTexture","type":29,"count":1,"defines":[],"binding":30}],"record":null,"name":"builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:add"},{"hash":1041140199,"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  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_nativeSize;\n  highp   mat4 cc_matView;\n  mediump mat4 cc_matViewInv;\n  mediump mat4 cc_matProj;\n  mediump mat4 cc_matProjInv;\n  mediump mat4 cc_matViewProj;\n  mediump mat4 cc_matViewProjInv;\n  mediump vec4 cc_cameraPos;\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 highp mat4 cc_matView;\nuniform mediump mat4 cc_matViewInv;\nuniform mediump mat4 cc_matViewProj;\nuniform mediump 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","members":[{"name":"mainTiling_Offset","type":16,"count":1},{"name":"frameTile_velLenScale","type":16,"count":1},{"name":"scale","type":16,"count":1}],"defines":[],"binding":0},{"name":"FragConstants","members":[{"name":"tintColor","type":16,"count":1}],"defines":[],"binding":1}],"samplers":[{"name":"mainTexture","type":29,"count":1,"defines":[],"binding":30}],"record":null,"name":"builtin-3d-particle|particle-vs-legacy:lpvs_main|tinted-fs:multiply"},{"hash":4223686731,"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  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_nativeSize;\n  highp   mat4 cc_matView;\n  mediump mat4 cc_matViewInv;\n  mediump mat4 cc_matProj;\n  mediump mat4 cc_matProjInv;\n  mediump mat4 cc_matViewProj;\n  mediump mat4 cc_matViewProjInv;\n  mediump vec4 cc_cameraPos;\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 highp mat4 cc_matView;\nuniform mediump mat4 cc_matViewInv;\nuniform mediump mat4 cc_matViewProj;\nuniform mediump 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","members":[{"name":"mainTiling_Offset","type":16,"count":1},{"name":"frameTile_velLenScale","type":16,"count":1},{"name":"scale","type":16,"count":1}],"defines":[],"binding":0}],"samplers":[{"name":"mainTexture","type":29,"count":1,"defines":[],"binding":30}],"record":null,"name":"builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:addSmooth"},{"hash":3289288011,"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  highp   vec4 cc_time;\n  mediump vec4 cc_screenSize;\n  mediump vec4 cc_screenScale;\n  mediump vec4 cc_nativeSize;\n  highp   mat4 cc_matView;\n  mediump mat4 cc_matViewInv;\n  mediump mat4 cc_matProj;\n  mediump mat4 cc_matProjInv;\n  mediump mat4 cc_matViewProj;\n  mediump mat4 cc_matViewProjInv;\n  mediump vec4 cc_cameraPos;\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 highp mat4 cc_matView;\nuniform mediump mat4 cc_matViewInv;\nuniform mediump mat4 cc_matViewProj;\nuniform mediump 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","members":[{"name":"mainTiling_Offset","type":16,"count":1},{"name":"frameTile_velLenScale","type":16,"count":1},{"name":"scale","type":16,"count":1}],"defines":[],"binding":0}],"samplers":[{"name":"mainTexture","type":29,"count":1,"defines":[],"binding":30}],"record":null,"name":"builtin-3d-particle|particle-vs-legacy:lpvs_main|no-tint-fs:premultiplied"}]}