UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

151 lines (95 loc) 4.2 kB
export const ParticleBillboardShader = { vertex() { return ` uniform float cameraNear; uniform float cameraFar; uniform vec2 resolution; attribute float size; attribute float atlasPatch; attribute float rotation; varying vec4 vPatch; varying float vSize; varying float vFadeDistance; varying vec4 vColor; varying vec2 vRotationMultiplier; void main() { float paramScale = 1.0; vColor = vec4(1.0); vSize = size * paramScale; vPatch = atlasPatch; mat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix; vec4 position4 = vec4( position, 1.0 ); gl_Position = modelViewProjectionMatrix * position4; float rotationGlobal = rotation; vRotationMultiplier = vec2( cos(rotationGlobal),sin(rotationGlobal) ); float radius = vSize/2.0; #ifdef DEPTH_SOFT_ENABLED vFadeDistance = 1.0 / radius; #endif gl_PointSize = resolution.y * projectionMatrix[1][1] * radius / gl_Position.w; }` }, fragment() { return ` uniform sampler2D tSpriteAtlas; uniform sampler2D tDepth; uniform float cameraNear; uniform float cameraFar; uniform mat4 modelViewMatrix; uniform mat4 projectionMatrix; uniform vec2 resolution; varying float vFadeDistance; varying vec4 vPatch; varying float vSize; varying vec4 vColor; varying vec2 vRotationMultiplier; float depthToLinear( float z ) { float z_n = 2.0 * z - 1.0; float z_e = 2.0 * cameraNear * cameraFar / (cameraFar + cameraNear - z_n * (cameraFar - cameraNear)); return z_e; } float calculateFade(in float particleDepth, in float sceneDepth){ float zFade; float linearParticleDepth = depthToLinear(particleDepth); float linearSceneDepth = depthToLinear(sceneDepth); float depthDelta = (linearSceneDepth - linearParticleDepth); float inputDepth = depthDelta* vFadeDistance; if(inputDepth <= 0.0){ return 0.0; } if(inputDepth >= 1.0){ return 1.0; } if(inputDepth <= 0.5){ zFade = 0.5 * pow( clamp(2.0*inputDepth, 0.0, 1.0), 2.0); }else{ zFade = 1.0 - 0.5 * pow( clamp(2.0*(1.0 - inputDepth), 0.0, 1.0), 2.0); } return zFade; } void main() { float fragmentDepth = gl_FragCoord.z; vec2 pixelPosition = gl_FragCoord.xy / resolution; float sceneDepth = texture2D( tDepth, pixelPosition ).x; #ifdef DEPTH_READ_ENABLED if(fragmentDepth + 0.0001 > sceneDepth){ discard; } #endif vec2 centeredUv = gl_PointCoord.xy - 0.5; vec2 texelCoordinate = vec2( centeredUv.x* vRotationMultiplier.x - centeredUv.y* vRotationMultiplier.y, centeredUv.x * vRotationMultiplier.y + centeredUv.y * vRotationMultiplier.x) + 0.5; texelCoordinate = clamp(texelCoordinate, vec2(0.0), vec2(1.0) ); vec2 uv = texelCoordinate*vPatch.zw + vPatch.xy; vec4 spriteColor = texture2D( tSpriteAtlas, uv ); if(spriteColor.a == 0.0){ discard; } vec4 texel = spriteColor *vColor; #ifdef DEPTH_SOFT_ENABLED float zFade = calculateFade(fragmentDepth, sceneDepth); texel.a *= zFade; #endif gl_FragColor = texel; }`; } }