/* * KNWebGLShader.js * Keynote HTML Player * * Created by Tungwei Cheng * Copyright (c) 2016-2019 Apple Inc. All rights reserved. */ var KNWebGLShader = {}; KNWebGLShader.defaultTexture = { attribNames: ["Position", "TexCoord"], uniformNames: ["MVPMatrix", "Texture"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ attribute vec4 Position;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ v_TexCoord = TexCoord;\n\ gl_Position = (MVPMatrix * Position);\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ gl_FragColor = texture2D(Texture, v_TexCoord);\n\ }\ " }; KNWebGLShader.defaultTextureAndOpacity = { attribNames: ["Position", "TexCoord"], uniformNames: ["MVPMatrix", "Texture", "Opacity"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ attribute vec4 Position;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ v_TexCoord = TexCoord;\n\ gl_Position = (MVPMatrix * Position);\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ uniform float Opacity;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ vec4 texColor = texture2D(Texture, v_TexCoord);\n\ gl_FragColor = vec4(Opacity) * texColor;\n\ }\ " }; KNWebGLShader.contentsAndOpacity = { attribNames: ["Position", "TexCoord"], uniformNames: ["MVPMatrix", "Texture", "Texture2", "mixFactor", "Opacity"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ attribute vec4 Position;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ v_TexCoord = TexCoord;\n\ gl_Position = (MVPMatrix * Position);\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ uniform sampler2D Texture2;\n\ uniform float mixFactor;\n\ uniform float Opacity;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ vec4 outgoingColor = texture2D(Texture2, v_TexCoord);\n\ vec4 incomingColor = texture2D(Texture, v_TexCoord);\n\ vec4 result = mix(outgoingColor, incomingColor, mixFactor);\n\ gl_FragColor = vec4(Opacity) * result;\n\ }\ " }; KNWebGLShader.contents = { attribNames: ["Position", "TexCoord"], uniformNames: ["MVPMatrix", "Texture", "Texture2", "mixFactor"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ attribute vec4 Position;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ v_TexCoord = TexCoord;\n\ gl_Position = (MVPMatrix * Position);\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ uniform sampler2D Texture2;\n\ uniform float mixFactor;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ vec4 outgoingColor = texture2D(Texture2, v_TexCoord);\n\ vec4 incomingColor = texture2D(Texture, v_TexCoord);\n\ vec4 result = mix(outgoingColor, incomingColor, mixFactor);\n\ gl_FragColor = result;\n\ }\ " }; KNWebGLShader.iris = { attribNames: ["Position", "TexCoord"], uniformNames: ["PercentForAlpha", "Scale", "Mix", "Texture", "MVPMatrix", "Opacity"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ attribute vec4 Position;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ v_TexCoord = TexCoord;\n\ gl_Position = MVPMatrix * Position;\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ uniform float Opacity;\n\ uniform float PercentForAlpha;\n\ uniform float Scale;\n\ uniform float Mix;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ vec4 incomingTexColor = texture2D(Texture, v_TexCoord);\n\ vec4 clear = vec4(0.0, 0.0, 0.0, 0.0);\n\ float tolerance = PercentForAlpha/5.0;\n\ vec2 powers = vec2((v_TexCoord.x - 0.5) * Scale,v_TexCoord.y - 0.5);\n\ powers *= powers;\n\ float radiusSqrd = PercentForAlpha * PercentForAlpha;\n\ float dist = (powers.x+powers.y)/((0.5*Scale)*(0.5*Scale)+0.25);\n\ float gradient = smoothstep(radiusSqrd, radiusSqrd+tolerance, dist);\n\ gl_FragColor = vec4(Opacity) * mix(clear, incomingTexColor, abs(Mix - gradient));\n\ }\ " }; KNWebGLShader.twist = { attribNames: ["Position", "TexCoord", "Normal"], uniformNames: ["TextureMatrix", "SpecularColor", "FlipNormals", "MVPMatrix", "Texture"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ uniform mat3 TextureMatrix;\n\ uniform float SpecularColor;\n\ uniform mediump float FlipNormals;\n\ attribute vec3 Position;\n\ attribute vec3 Normal;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ varying vec3 v_DiffuseColor;\n\ varying vec3 v_SpecularColor;\n\ const vec3 c_AmbientColor = vec3(0.2);\n\ const vec3 c_DiffuseColor = vec3(1);\n\ const float c_LightExponent = 32.0;\n\ const vec3 c_LightDirection = vec3(0.1580, +0.5925, 0.7900);\n\ const vec3 c_LightHalfPlane = vec3(0.0835, +0.3131, 0.9460);\n\ void main()\n\ {\n\ vec3 thisNormal = Normal * FlipNormals;\n\ // Lighting\n\ float ndotl = max(0.0, dot(thisNormal, c_LightDirection));\n\ float ndoth = max(0.0, dot(thisNormal, c_LightHalfPlane));\n\ v_DiffuseColor = (c_AmbientColor + ndotl * c_DiffuseColor);\n\ v_SpecularColor = (ndoth <= 0.0) ? vec3(0) : (pow(ndoth, c_LightExponent) * vec3(SpecularColor));\n\ gl_Position = MVPMatrix * vec4(Position, 1.0);\n\ v_TexCoord = (TextureMatrix * vec3(TexCoord,1.0)).xy;\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ varying vec2 v_TexCoord;\n\ varying vec3 v_DiffuseColor;\n\ varying vec3 v_SpecularColor;\n\ void main()\n\ {\n\ vec4 texColor = texture2D(Texture, v_TexCoord);\n\ // Lighting\n\ texColor.xyz = texColor.xyz * v_DiffuseColor + v_SpecularColor;\n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.colorPlanes = { attribNames: ["Position", "TexCoord"], uniformNames: ["MVPMatrix", "FlipTexCoords", "Texture", "ColorMask"], vertex: "\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ uniform mat4 MVPMatrix;\n\ uniform vec2 FlipTexCoords;\n\ attribute vec2 Position;\n\ attribute vec2 TexCoord;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ v_TexCoord = vec2(FlipTexCoords.x == 0.0 ? TexCoord.x : 1.0-TexCoord.x, FlipTexCoords.y == 0.0 ? TexCoord.y : 1.0-TexCoord.y);\n\ gl_Position = MVPMatrix * vec4(Position, 0,1);\n\ }\ ", fragment: "\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D Texture;\n\ uniform vec4 ColorMask;\n\ varying vec2 v_TexCoord;\n\ void main()\n\ {\n\ vec4 texColor = texture2D(Texture, v_TexCoord);\n\ texColor *= ColorMask;\n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.flop = { attribNames: ["Position", "TexCoord", "Normal"], uniformNames: ["TextureMatrix", "FlipNormals", "MVPMatrix", "Texture"], vertex: "\ \n\ #ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ \n\ uniform mat4 MVPMatrix;\n\ uniform mat3 TextureMatrix;\n\ uniform float FlipNormals;\n\ \n\ attribute vec3 Position;\n\ attribute vec3 Normal;\n\ attribute vec2 TexCoord;\n\ \n\ varying vec2 v_TexCoord;\n\ varying vec3 v_DiffuseColor;\n\ \n\ const vec3 c_AmbientColor = vec3(0.1);\n\ const vec3 c_DiffuseColor = vec3(1);\n\ const float c_LightExponent = 32.0;\n\ \n\ const vec3 c_LightDirection = vec3(0.000, +0.000, 0.900);\n\ \n\ void main()\n\ {\n\ vec3 thisNormal = Normal * FlipNormals;\n\ \n\ // Lighting\n\ vec3 lightDirection = vec3(c_LightDirection.x,c_LightDirection.y,c_LightDirection.z);\n\ \n\ float ndotl = max(0.0, dot(thisNormal, lightDirection));\n\ \n\ v_DiffuseColor = (c_AmbientColor + ndotl * c_DiffuseColor);\n\ \n\ gl_Position = MVPMatrix * vec4(Position, 1);\n\ v_TexCoord = (TextureMatrix * vec3(TexCoord,1)).xy;\n\ }\ ", fragment: "\ \n\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ \n\ uniform sampler2D Texture;\n\ \n\ varying vec2 v_TexCoord;\n\ varying vec3 v_DiffuseColor;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(Texture, v_TexCoord);\n\ \n\ // Lighting\n\ texColor.xyz = texColor.xyz * v_DiffuseColor;\n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.anvilsmoke = { attribNames: ["Rotation", "Speed", "Scale", "LifeSpan", "ParticleTexCoord", "Center", "Position"], uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix"], vertex: "\ \n\ uniform mat4 MVPMatrix;\n\ uniform float Percent;\n\ uniform float Opacity;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 ParticleTexCoord;\n\ attribute vec3 Rotation;\n\ attribute vec3 Speed;\n\ attribute float Scale;\n\ attribute vec2 LifeSpan;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ const float Pi = 3.1415926;\n\ const float Pi_2 = 1.5707963;\n\ const float TwoPi = 6.2831852;\n\ \n\ const float sineConstB = 1.2732396; /* = 4./Pi; */\n\ const float sineConstC = -0.40528476; /* = -4./(Pi*Pi); */\n\ \n\ vec3 fastSine(vec3 angle)\n\ {\n\ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\ }\n\ \n\ mat3 fastRotationMatrix(vec3 theRotation)\n\ {\n\ vec3 sinXYZ = fastSine(theRotation);\n\ vec3 cosXYZ = fastSine(Pi_2 - theRotation);\n\ mat3 rotMatrix = mat3( cosXYZ.y*cosXYZ.z, sinXYZ.x*sinXYZ.y*cosXYZ.z+cosXYZ.x*sinXYZ.z, -cosXYZ.x*sinXYZ.y*cosXYZ.z+sinXYZ.x*sinXYZ.z,\n\ -cosXYZ.y*sinXYZ.z, -sinXYZ.x*sinXYZ.y*sinXYZ.z+cosXYZ.x*cosXYZ.z, cosXYZ.x*sinXYZ.y*sinXYZ.z+sinXYZ.x*cosXYZ.z,\n\ sinXYZ.y, -sinXYZ.x*cosXYZ.y, cosXYZ.x*cosXYZ.y);\n\ return rotMatrix;\n\ }\n\ \n\ void main()\n\ {\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ realPercent = clamp(realPercent, 0.0, 1.0);\n\ realPercent = sqrt(realPercent);\n\ \n\ /* SCALE */\n\ vec4 originalPosition = vec4(Position,0,1);\n\ vec4 center = vec4(Center, 0,1);\n\ vec3 scaleDirectionVec = vec3(originalPosition.xy-center.xy,0) * Scale * mix(0.1, 1.0, realPercent);\n\ \n\ /* ROTATE */\n\ mat3 rotMatrix = fastRotationMatrix(Rotation * realPercent);\n\ vec3 rotatedVec = rotMatrix * scaleDirectionVec;\n\ vec4 position = center + vec4(rotatedVec,0);\n\ \n\ float speedAdjust = realPercent;\n\ vec3 thisSpeed = Speed;\n\ thisSpeed.x *= sqrt(realPercent);\n\ thisSpeed.y *= realPercent*realPercent;\n\ position += vec4(thisSpeed, 0);\n\ \n\ float thisOpacity = Opacity;\n\ thisOpacity *= (1.0 - realPercent); /* fade out gradually */\n\ thisOpacity *= min(1.0, realPercent*20.0); /* fade in quickly */\n\ \n\ /* output */\n\ gl_Position = MVPMatrix * position;\n\ //v_Color = vec4(1.0, 1.0, 1.0, thisOpacity); //we applied a fix here, might not work everywhere\n\ v_Color = vec4(thisOpacity);\n\ v_TexCoord = ParticleTexCoord;\n\ }\n\ ", fragment: "\ \n\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D ParticleTexture;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ texColor *= v_Color;\n\ \n\ gl_FragColor = texColor;\n\ }\n\ " }; KNWebGLShader.anvilspeck = { attribNames: ["Speed", "Scale", "LifeSpan", "ParticleTexCoord", "Center", "Position"], uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix"], vertex: "\ \n\ uniform mat4 MVPMatrix;\n\ uniform float Percent;\n\ uniform float Opacity;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 ParticleTexCoord;\n\ attribute vec3 Speed;\n\ attribute float Scale;\n\ attribute vec2 LifeSpan;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ const float Pi = 3.1415926;\n\ const float Pi_2 = 1.5707963;\n\ const float TwoPi = 6.2831852;\n\ \n\ const float sineConstB = 1.2732396; /* = 4./Pi; */\n\ const float sineConstC = -0.40528476; /* = -4./(Pi*Pi); */\n\ \n\ vec3 fastSine(vec3 angle)\n\ {\n\ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\ }\n\ \n\ void main()\n\ {\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ realPercent = clamp(realPercent, 0.0, 1.0);\n\ \n\ /* SCALE */\n\ vec4 originalPosition = vec4(Position,0,1);\n\ vec4 center = vec4(Center, 0,1);\n\ vec3 thisScale = Scale * vec3(1, Speed.z, 1) * mix(0.1, 1.0, realPercent);\n\ vec3 scaleDirectionVec = vec3(originalPosition.xy-center.xy,0) * thisScale;\n\ \n\ vec4 position = center + vec4(scaleDirectionVec,0);\n\ \n\ float speedAdjust = realPercent;\n\ vec3 thisPos = vec3(Speed.x * realPercent,\n\ Speed.y * fastSine(Pi*0.85*vec3(realPercent,0,0)).x, /* arc with gravity */\n\ 0);\n\ position += vec4(thisPos, 0);\n\ \n\ float thisOpacity = Opacity;\n\ thisOpacity *= (1.0 - realPercent); /* fade out gradually */\n\ thisOpacity *= min(1.0, realPercent*20.0); /* fade in quickly */\n\ \n\ /* output */\n\ gl_Position = MVPMatrix * position;\n\ v_Color = vec4(thisOpacity);\n\ v_TexCoord = ParticleTexCoord;\n\ }\ ", fragment: "\ \n\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D ParticleTexture;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ texColor *= v_Color;\n\ \n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.flame = { attribNames: ["Rotation", "Speed", "LifeSpan", "ParticleTexCoord", "Center", "Position"], uniformNames: ["Percent", "Duration", "Opacity", "RotationMax", "SpeedMax", "ParticleTexture", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ uniform float Percent;\n\ uniform float Duration;\n\ \n\ attribute vec3 Rotation;\n\ attribute vec3 Speed;\n\ uniform float Opacity;\n\ attribute vec2 LifeSpan;\n\ attribute vec2 ParticleTexCoord;\n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ \n\ uniform mediump float RotationMax;\n\ uniform mediump float SpeedMax;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ const float Pi = 3.1415926;\n\ const float Pi_2 = 1.5707963;\n\ const float TwoPi = 6.2831852;\n\ \n\ const float sineConstB = 1.2732396; /* = 4./Pi; */\n\ const float sineConstC = -0.40528476; /* = -4./(Pi*Pi); */\n\ \n\ float fastSine(float angle)\n\ {\n\ float theAngle = mod(angle + Pi, TwoPi) - Pi;\n\ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\ }\n\ \n\ const vec4 kStartColor = vec4( 1.0, 1.0, 1.0, 0.0 ); /* white */\n\ const vec4 kMidColor = vec4( 0.97, 1.0, 0.32, 0.0 ); /* yellow */\n\ const vec4 kEndColor = vec4( 0.9, 0.0, 0.0, 0.0 ); /* red */\n\ const float kColorMidPoint = 0.1;\n\ \n\ vec4 flameColor(float aPercent)\n\ {\n\ float thePercent = aPercent;\n\ /* CONSTANTS */\n\ float beginCutoff = 0.4/Duration; /* start slow (not bright white) */\n\ float smokeCutoff = 1.0 - (0.95/Duration); /* end with black, basically */\n\ float alphaCutoff = 1.0 - 0.5/Duration; /* fade out towards the end */\n\ \n\ float alpha = (thePercent < alphaCutoff) ? 1.0 : (1.0-(thePercent-alphaCutoff)/(1.0-alphaCutoff));\n\ vec4 theColor = vec4(0,0,0, alpha * 0.75);\n\ \n\ if (Percent < beginCutoff) {\n\ float colorCutoff = beginCutoff*3.0;\n\ thePercent += mix(colorCutoff, 0.0, Percent/beginCutoff);\n\ }\n\ \n\ if (thePercent < kColorMidPoint) {\n\ float newPercent = thePercent/kColorMidPoint;\n\ theColor += mix(kStartColor, kMidColor, newPercent);\n\ } else {\n\ float newPercent = (thePercent-kColorMidPoint)/(1.0-kColorMidPoint);\n\ theColor += mix(kMidColor, kEndColor, newPercent);\n\ }\n\ \n\ if (Percent > smokeCutoff) {\n\ /* smoke */\n\ float smokeAmount = (Percent - smokeCutoff)/(1.0 - smokeCutoff);\n\ smokeAmount = sqrt(smokeAmount);\n\ smokeAmount *= (0.25+thePercent*thePercent);\n\ theColor = vec4(theColor.rgb * max(0.0, 1.0-smokeAmount), theColor.a);\n\ }\n\ \n\ return theColor;\n\ }\n\ \n\ void main()\n\ {\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ bool shouldDiscard = realPercent < 0.0 || realPercent > 1.0;\n\ realPercent = clamp(realPercent, 0.0, 1.0);\n\ \n\ vec4 scaleDirectionVec = vec4(Position-Center,0,0);\n\ \n\ /* ROTATE */\n\ float halfPercent = realPercent/2.0;\n\ vec3 thisRotation = Rotation * RotationMax;\n\ float theRotation = thisRotation.x + thisRotation.z * (halfPercent * (halfPercent + 1.0));\n\ float sinRot = fastSine(theRotation);\n\ float cosRot = fastSine(Pi_2 - theRotation);\n\ mat3 rotMatrix = mat3(cosRot,-sinRot,0, sinRot,cosRot,0, 0,0,1);\n\ vec3 rotatedVec = rotMatrix * scaleDirectionVec.xyz;\n\ \n\ /* SCALE */\n\ float scaleAdjust = (0.1 + 1.0-(1.0-realPercent)*(1.0-realPercent));\n\ vec4 position = vec4(Center,0,1) + vec4(rotatedVec * scaleAdjust * (shouldDiscard ? 0.001 : 1.0), 0);\n\ \n\ /* POSITION */\n\ vec3 thisSpeed = Speed * SpeedMax;\n\ vec4 upVector = vec4(0.0, realPercent*realPercent * -thisSpeed.y, 0.0, 0.0);\n\ position += upVector;\n\ \n\ v_Color = flameColor(realPercent)*Opacity;\n\ gl_Position = MVPMatrix * position;\n\ v_TexCoord = ParticleTexCoord;\n\ }\ ", fragment: "\ \n\ #ifdef GL_ES\n\ precision mediump float;\n\ #endif\n\ uniform sampler2D ParticleTexture;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ texColor *= v_Color;\n\ \n\ gl_FragColor = texColor;\n\ }\n\ " }; KNWebGLShader.confetti = { attribNames: ["Rotation", "Speed", "TexCoord", "Center", "Position"], uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ uniform mat4 MVPMatrix;\n\ \n\ uniform float Percent;\n\ uniform mediump float Opacity;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 TexCoord;\n\ attribute vec3 Rotation;\n\ attribute vec3 Speed;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ const float Pi = 3.1415926;\n\ const float Pi_2 = 1.5707963;\n\ const float TwoPi = 6.2831852;\n\ \n\ const float sineConstB = 1.2732396;\n\ const float sineConstC = -0.40528476;\n\ \n\ vec3 fastSine(vec3 angle)\n\ {\n\ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\ }\n\ \n\ mat3 fastRotationMatrix(vec3 theRotation)\n\ {\n\ vec3 sinXYZ = fastSine(theRotation);\n\ vec3 cosXYZ = fastSine(Pi_2 - theRotation);\n\ mat3 rotMatrix = mat3( cosXYZ.y*cosXYZ.z, sinXYZ.x*sinXYZ.y*cosXYZ.z+cosXYZ.x*sinXYZ.z, -cosXYZ.x*sinXYZ.y*cosXYZ.z+sinXYZ.x*sinXYZ.z,\n\ -cosXYZ.y*sinXYZ.z, -sinXYZ.x*sinXYZ.y*sinXYZ.z+cosXYZ.x*cosXYZ.z, cosXYZ.x*sinXYZ.y*sinXYZ.z+sinXYZ.x*cosXYZ.z,\n\ sinXYZ.y, -sinXYZ.x*cosXYZ.y, cosXYZ.x*cosXYZ.y);\n\ return rotMatrix;\n\ }\n\ \n\ void main()\n\ {\n\ /* SCALE */\n\ vec4 originalPosition = vec4(Position, 0, 1);\n\ vec3 scaleDirectionVec = vec3(Position-Center,0);\n\ \n\ /* ROTATE */\n\ mat3 rotMatrix = fastRotationMatrix(Rotation * Percent);\n\ vec3 rotatedVec = scaleDirectionVec * rotMatrix;\n\ vec4 position = vec4(Center,0,1) + vec4(rotatedVec,0);\n\ \n\ float colorAdjust = abs((rotMatrix * vec3(0,0,1)).z);\n\ \n\ float speedAdjust = Percent;\n\ position += vec4(Speed, 0) * speedAdjust;\n\ \n\ /* output */\n\ gl_Position = MVPMatrix * position;\n\ v_Color = vec4(vec3(colorAdjust), Opacity);\n\ v_TexCoord = TexCoord;\n\ }\ ", fragment: "\ \n\ precision mediump float;\n\ \n\ uniform sampler2D ParticleTexture;\n\ //uniform float Opacity;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ texColor *= v_Color;\n\ //texColor.a = Opacity;\n\ \n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.diffuse = { attribNames: ["Rotation", "Speed", "TexCoord", "Center", "Position", "LifeSpan"], uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix", "RotationMax", "SpeedMax"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ \n\ uniform float Percent;\n\ uniform mediump float Opacity;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 TexCoord;\n\ \n\ attribute mediump vec3 Rotation;\n\ uniform mediump float RotationMax;\n\ attribute mediump vec3 Speed;\n\ uniform mediump float SpeedMax;\n\ attribute mediump vec2 LifeSpan;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ const float Pi = 3.1415926;\n\ const float Pi_2 = 1.5707963;\n\ const float TwoPi = 6.2831852;\n\ \n\ const float sineConstB = 1.2732396;\n\ const float sineConstC = -0.40528476;\n\ \n\ vec3 fastSine(vec3 angle)\n\ {\n\ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\ }\n\ \n\ mat3 fastRotationMatrix(vec3 theRotation)\n\ {\n\ vec3 sinXYZ = fastSine(theRotation);\n\ vec3 cosXYZ = fastSine(Pi_2 - theRotation);\n\ mat3 rotMatrix = mat3( cosXYZ.y*cosXYZ.z, sinXYZ.x*sinXYZ.y*cosXYZ.z+cosXYZ.x*sinXYZ.z, -cosXYZ.x*sinXYZ.y*cosXYZ.z+sinXYZ.x*sinXYZ.z,\n\ -cosXYZ.y*sinXYZ.z, -sinXYZ.x*sinXYZ.y*sinXYZ.z+cosXYZ.x*cosXYZ.z, cosXYZ.x*sinXYZ.y*sinXYZ.z+sinXYZ.x*cosXYZ.z,\n\ sinXYZ.y, -sinXYZ.x*cosXYZ.y, cosXYZ.x*cosXYZ.y);\n\ return rotMatrix;\n\ }\n\ \n\ void main()\n\ {\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ float doDiscard = (realPercent > 1.0) ? 0.0 : 1.0;\n\ realPercent = clamp(realPercent, 0.0,1.0);\n\ float revPercent = 1.0-realPercent;\n\ \n\ //SCALE\n\ vec4 originalPosition = vec4(Position, 0, 1);\n\ vec3 scaleDirectionVec = vec3(Position-Center,0);\n\ \n\ //ROTATE\n\ vec3 thisRotation = Rotation * RotationMax;\n\ mat3 rotMatrix = fastRotationMatrix(thisRotation * realPercent);\n\ vec3 rotatedVec = scaleDirectionVec * rotMatrix;\n\ vec4 position = vec4(Center,0,1) + vec4(rotatedVec,0) * doDiscard;\n\ \n\ vec3 thisSpeed = Speed * SpeedMax;\n\ float l2r = -thisSpeed.x/abs(thisSpeed.x);\n\ float reverseVector = l2r*(thisSpeed.x+abs(thisSpeed.y)) * realPercent/8.0;\n\ \n\ float speedMultiplier = 1.-pow(revPercent, 2.0);\n\ vec3 dist = thisSpeed * speedMultiplier;\n\ dist.x += reverseVector;\n\ position.xyz += dist;\n\ \n\ float colorAdjust = abs((rotMatrix * vec3(0,0,1)).z);\n\ \n\ //output\n\ gl_Position = MVPMatrix * position;\n\ v_Color = vec4(vec3(colorAdjust), 1) * (revPercent*Opacity);\n\ v_TexCoord = TexCoord;\n\ }\ ", fragment: "\ \n\ precision mediump float;\n\ \n\ uniform sampler2D Texture;\n\ uniform float Opacity;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(Texture, v_TexCoord);\n\ \n\ texColor *= v_Color;\n\ \n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.fireworks = { attribNames: ["Color", "Speed", "LifeSpan", "Scale", "ParticleTexCoord", "Center", "Position"], uniformNames: ["Percent", "PreviousPercent", "Gravity", "StartScale", "ShouldSparkle", "SparklePeriod", "ParticleBurstTiming", "PreviousParticleBurstTiming", "SpeedMax", "ParticleTexture", "Opacity", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ \n\ uniform float Percent;\n\ uniform float PreviousPercent;\n\ uniform float Gravity;\n\ uniform float StartScale;\n\ uniform float ShouldSparkle;\n\ uniform float SparklePeriod;\n\ uniform float ParticleBurstTiming;\n\ uniform float PreviousParticleBurstTiming;\n\ uniform float SpeedMax;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 ParticleTexCoord;\n\ \n\ attribute vec4 Color;\n\ attribute vec3 Speed;\n\ attribute vec2 LifeSpan;\n\ attribute float Scale;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ realPercent = clamp(realPercent, 0.0, 1.0);\n\ \n\ float prevRealPercent = (PreviousPercent-LifeSpan.x)/LifeSpan.y;\n\ prevRealPercent = clamp(prevRealPercent, 0.0,1.0);\n\ \n\ vec4 center = vec4(Center,0,1);\n\ vec4 scaleDirectionVec = vec4(Position-Center,0,0);\n\ \n\ // TRANSLATE\n\ vec3 translation = Speed * (SpeedMax * ParticleBurstTiming); // (1.0-pow(1.0-realPercent, ExplosionPower));\n\ translation.y -= Gravity * (Percent - LifeSpan.x); // Gravity is in terms of global percent, not particle system percent\n\ \n\ vec3 prevTranslation = Speed * (SpeedMax * PreviousParticleBurstTiming);\n\ prevTranslation.y -= Gravity * (PreviousPercent - LifeSpan.x); // Gravity is in terms of global percent, not particle system percent\n\ \n\ vec3 blurOffset = translation - prevTranslation; // Blur in direction of velocity\n\ \n\ // project centerVec onto translationOffset to get direction\n\ blurOffset *= (dot(blurOffset, scaleDirectionVec.xyz) >= 0.0 ? 1.0 : -1.0);\n\ \n\ center.xyz += translation;\n\ \n\ // SCALE\n\ float scalePercent = (1.0-(1.0-realPercent)*(1.0-realPercent));\n\ float scaleAdjust = mix(StartScale, Scale, scalePercent);\n\ // scale down to zero, unless we're sparkling\n\ scaleAdjust *= (ShouldSparkle>0.5 ? 0.25 : 1.0-scalePercent);\n\ vec4 position = center + scaleDirectionVec * scaleAdjust;\n\ position += vec4(blurOffset,0);\n\ \n\ // SPARKLE\n\ float sparkleOpacity = fract(realPercent*realPercent * SparklePeriod);\n\ sparkleOpacity = smoothstep(0.0, 1.0, sparkleOpacity);\n\ \n\ // COLOR\n\ vec4 color = mix(vec4(1), Color, scalePercent * (ShouldSparkle<0.5 ? 1.0 : 0.5)); // white to color\n\ color *= (ShouldSparkle<0.5 ? 1.0 : sparkleOpacity); // apply sparkle opacity\n\ color *= (realPercent>=1.0 ? 0.0 : 1.0);\n\ v_Color = color;\n\ \n\ gl_Position = MVPMatrix * position;\n\ v_TexCoord = ParticleTexCoord;\n\ }\ ", fragment: "\ \n\ precision mediump float;\n\ \n\ uniform sampler2D ParticleTexture;\n\ uniform float Opacity;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ //varying float particleTexPercent;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ texColor *= v_Color * Opacity;\n\ //texColor.a *= Opacity;\n\ \n\ //texColor = vec4(v_TexCoord, 0, 1);\n\ \n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.fireworkstrails = { attribNames: [ "Position", "TexCoord"], uniformNames: ["Texture", "Opacity", "NoiseAmount", "NoiseSeed", "NoiseMax", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 TexCoord;\n\ \n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ gl_Position = MVPMatrix * vec4(Position, 0,1);\n\ v_TexCoord = TexCoord;\n\ }\ ", fragment: "\ precision mediump float;\n\ \n\ uniform sampler2D Texture;\n\ uniform float Opacity;\n\ uniform float NoiseAmount;\n\ uniform vec2 NoiseSeed;\n\ uniform float NoiseMax;\n\ \n\ //varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ //varying float particleTexPercent;\n\ \n\ float rand(vec2 co){\n\ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n\ }\n\ \n\ float inverseSquare(float a) {\n\ return 1.0-(1.0-a)*(1.0-a);\n\ }\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(Texture, v_TexCoord);\n\ \n\ //texColor = bloom(texColor);\n\ \n\ // Dither transparency to add noise\n\ float randomNoise = NoiseMax*rand(v_TexCoord*NoiseSeed);\n\ float randomAmount = NoiseAmount * 1.5*max(0.0, texColor.a-0.3333);\n\ \n\ float thisOpacity = Opacity * mix(1.0, randomNoise, randomAmount);\n\ texColor *= thisOpacity;\n\ \n\ //texColor = vec4(v_TexCoord, 0, 1);\n\ \n\ gl_FragColor = texColor;\n\ }\ " }; KNWebGLShader.horizontalGaussianBlur = { attribNames: [ "Position"], uniformNames: ["Texture", "TextureSize", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ \n\ attribute vec2 Position;\n\ \n\ void main()\n\ {\n\ gl_Position = MVPMatrix * vec4(Position, 0, 1);\n\ }\ ", fragment: "\ precision highp float;\n\ \n\ uniform sampler2D Texture;\n\ uniform vec2 TextureSize;\n\ \n\ const vec2 offset1 = vec2(1.3846153846, 0);\n\ const vec2 offset2 = vec2(3.2307692308, 0);\n\ const float weight0 = 0.2270270270;\n\ const float weight1 = 0.3162162162;\n\ const float weight2 = 0.0702702703;\n\ \n\ void main()\n\ {\n\ vec4 color = texture2D(Texture, gl_FragCoord.xy*TextureSize) * weight0;\n\ \n\ color += texture2D(Texture, (gl_FragCoord.xy + offset1)*TextureSize) * weight1;\n\ color += texture2D(Texture, (gl_FragCoord.xy - offset1)*TextureSize) * weight1;\n\ \n\ color += texture2D(Texture, (gl_FragCoord.xy + offset2)*TextureSize) * weight2;\n\ color += texture2D(Texture, (gl_FragCoord.xy - offset2)*TextureSize) * weight2;\n\ \n\ gl_FragColor = color;\n\ }\ " }; KNWebGLShader.verticalGaussianBlur = { attribNames: [ "Position"], uniformNames: ["Texture", "TextureSize", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ \n\ attribute vec2 Position;\n\ \n\ void main()\n\ {\n\ gl_Position = MVPMatrix * vec4(Position, 0, 1);\n\ }\ ", fragment: "\ precision highp float;\n\ \n\ uniform sampler2D Texture;\n\ uniform vec2 TextureSize;\n\ \n\ const vec2 offset1 = vec2(0, 1.3846153846);\n\ const vec2 offset2 = vec2(0, 3.2307692308);\n\ const float weight0 = 0.2270270270;\n\ const float weight1 = 0.3162162162;\n\ const float weight2 = 0.0702702703;\n\ \n\ void main()\n\ {\n\ vec4 color = texture2D(Texture, gl_FragCoord.xy*TextureSize) * weight0;\n\ \n\ color += texture2D(Texture, (gl_FragCoord.xy + offset1)*TextureSize) * weight1;\n\ color += texture2D(Texture, (gl_FragCoord.xy - offset1)*TextureSize) * weight1;\n\ \n\ color += texture2D(Texture, (gl_FragCoord.xy + offset2)*TextureSize) * weight2;\n\ color += texture2D(Texture, (gl_FragCoord.xy - offset2)*TextureSize) * weight2;\n\ \n\ gl_FragColor = color;\n\ }\ " }; KNWebGLShader.bloom = { attribNames: [ "Position", "TexCoord"], uniformNames: ["Texture", "BlurTexture", "BloomAmount", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 TexCoord;\n\ \n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ v_TexCoord = TexCoord;\n\ gl_Position = MVPMatrix * vec4(Position, 0, 1);\n\ }\ ", fragment: "\ precision mediump float;\n\ \n\ uniform sampler2D Texture;\n\ uniform sampler2D BlurTexture;\n\ uniform float BloomAmount;\n\ \n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 color = texture2D(Texture, v_TexCoord);\n\ vec4 blurColor = texture2D(BlurTexture, v_TexCoord);\n\ \n\ color += (blurColor + color) * BloomAmount;\n\ gl_FragColor = color;\n\ }\ " }; KNWebGLShader.shimmerObject = { attribNames: [ "Position", "Center", "TexCoord", "Color", "Speed"], uniformNames: ["Percent", "Opacity", "RotationMatrix", "SpeedMax", "Texture", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ uniform float Percent;\n\ uniform float Opacity;\n\ \n\ uniform mat3 RotationMatrix;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 TexCoord;\n\ attribute vec4 Color;\n\ \n\ attribute vec3 Speed;\n\ uniform float SpeedMax;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ float thisPercent = Percent;\n\ float invPercent = 1.0-thisPercent;\n\ float thisPercent2 = thisPercent*thisPercent;\n\ \n\ /* CENTER */\n\ vec3 scaleDirectionVec = vec3((Position.x-Center.x),(Position.y-Center.y),0);\n\ \n\ /* ROTATE */\n\ vec3 rotatedVec = RotationMatrix * scaleDirectionVec.xyz;\n\ \n\ /* SCALE */\n\ float scale = invPercent;\n\ vec4 position = vec4(Center.xy,0,1) + vec4(rotatedVec,0) * scale;\n\ \n\ vec3 thisSpeed = Speed * SpeedMax;\n\ position.xyz += thisSpeed * thisPercent*(3.0 + mix(thisPercent2*thisPercent, 1.0-invPercent*invPercent, thisPercent2));\n\ \n\ vec4 outColor = Color;\n\ outColor = vec4(Opacity);\n\ \n\ /* output */\n\ gl_Position = MVPMatrix * position;\n\ v_Color = outColor;\n\ v_TexCoord = TexCoord;\n\ }\n\ ", fragment: "\ precision mediump float;\n\ \n\ uniform sampler2D Texture;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 color = texture2D(Texture, v_TexCoord);\n\ \n\ color *= v_Color;\n\ \n\ gl_FragColor = color;\n\ }\ " }; KNWebGLShader.shimmerParticle = { attribNames: [ "Position", "Center", "ParticleTexCoord", "Color", "LifeSpan", "Speed", "Scale"], uniformNames: ["Percent", "Opacity", "ParticleScalePercent", "RotationMatrix", "SpeedMax", "ParticleTexture", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ uniform float Percent;\n\ uniform float Opacity;\n\ \n\ uniform float ParticleScalePercent;\n\ uniform mat3 RotationMatrix;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ attribute vec2 ParticleTexCoord;\n\ attribute vec4 Color;\n\ attribute vec2 LifeSpan;\n\ \n\ attribute vec3 Speed;\n\ uniform float SpeedMax;\n\ attribute float Scale;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ float scaleUpDown(float x) {\n\ float result = 1.0 - abs(2.0*(x-0.5));\n\ result *= result;\n\ return result;\n\ }\n\ \n\ void main()\n\ {\n\ /* LIFESPAN */\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ float doDiscard = (realPercent > 1.0 || realPercent < 0.0) ? 0.0 : 1.0;\n\ realPercent = clamp(realPercent, 0.0,1.0);\n\ float realPercent2 = realPercent*realPercent;\n\ float invPercent2 = 1.0-realPercent;\n\ invPercent2 *= invPercent2;\n\ \n\ vec3 scaleDirectionVec = vec3((Position.x-Center.x),(Position.y-Center.y),0);\n\ \n\ /* ROTATE */\n\ vec3 rotatedVec = RotationMatrix * scaleDirectionVec.xyz;\n\ \n\ /* SCALE */\n\ float scalePercent = (LifeSpan.x <= 0.001 ? ParticleScalePercent : scaleUpDown(realPercent));\n\ float scale = scalePercent * Scale * doDiscard;\n\ vec4 position = vec4(Center,0,1) + vec4(rotatedVec,0) * scale;\n\ \n\ vec3 thisSpeed = Speed * SpeedMax;\n\ position.xyz += thisSpeed * realPercent*(3.0 + mix(realPercent*realPercent2, 1.0-invPercent2, realPercent2));\n\ \n\ // Only adjust opacity on particles that last the duration of the animation\n\ float thisOpacity = (LifeSpan.x <= 0.001 ? Opacity : 1.0);\n\ vec4 color = vec4(Color.rgb, 1) * thisOpacity;\n\ \n\ v_Color = color;\n\ v_TexCoord = ParticleTexCoord;\n\ gl_Position = MVPMatrix * position;\n\ }\n\ ", fragment: "\ precision mediump float;\n\ \n\ uniform sampler2D ParticleTexture;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 color = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ color *= v_Color;\n\ \n\ gl_FragColor = color;\n\ }\ " }; KNWebGLShader.sparkle = { attribNames: ["Scale", "LifeSpan", "Speed", "ParticleTexCoord", "Center", "Position"], uniformNames: ["Percent", "Opacity", "Color", "SpeedMax", "ParticleTexture", "MVPMatrix"], vertex: "\ \n\ precision highp float;\n\ \n\ uniform mat4 MVPMatrix;\n\ uniform float Percent;\n\ \n\ attribute vec2 Position;\n\ attribute vec2 Center;\n\ uniform float Opacity;\n\ attribute vec2 ParticleTexCoord;\n\ uniform vec4 Color;\n\ \n\ attribute mediump vec3 Speed;\n\ uniform mediump float SpeedMax;\n\ attribute mediump float Scale;\n\ attribute mediump vec2 LifeSpan;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ float ReverseSquareOfFloat(float f) {\n\ return 1.0 - (1.0-f)*(1.0-f);\n\ }\n\ \n\ void main()\n\ {\n\ float doDiscard = 0.0;\n\ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\ if (realPercent < 0.0 || realPercent > 1.0) {\n\ doDiscard = 1.0;\n\ realPercent = 1.0;\n\ }\n\ \n\ vec4 position;\n\ vec4 scaleDirectionVec = vec4((Position.x-Center.x),(Position.y-Center.y),0,0);\n\ \n\ // SCALE\n\ float scaleAdjust = realPercent;\n\ if (scaleAdjust < 0.1) {\n\ scaleAdjust /= 0.1;\n\ scaleAdjust = sqrt(scaleAdjust);\n\ } else {\n\ scaleAdjust = 1.0-(scaleAdjust-0.1)/0.9;\n\ scaleAdjust = scaleAdjust*scaleAdjust*scaleAdjust;\n\ }\n\ scaleAdjust *= (doDiscard==0.0 ? 1.0 : 0.0);\n\ position = vec4(Center,0,1) + scaleDirectionVec * scaleAdjust * Scale;\n\ \n\ // POSITION\n\ vec3 thisSpeed = Speed * SpeedMax;\n\ position += vec4(thisSpeed, 0) * realPercent;\n\ \n\ float invPercent = 1.0 - realPercent;\n\ vec3 rgbColor = mix(Color.rgb, vec3(1,1,1), invPercent*invPercent*invPercent);\n\ \n\ /* output */\n\ gl_Position = MVPMatrix * position;\n\ v_Color = vec4(rgbColor, (1.0-realPercent*realPercent)*Opacity);\n\ v_TexCoord = ParticleTexCoord;\n\ }\ ", fragment: "\ \n\ precision mediump float;\n\ \n\ uniform sampler2D ParticleTexture;\n\ \n\ varying vec4 v_Color;\n\ varying vec2 v_TexCoord;\n\ \n\ void main()\n\ {\n\ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\ \n\ texColor *= v_Color;\n\ \n\ gl_FragColor = texColor;\n\ }\ " };