playcanvas
Version:
PlayCanvas WebGL game engine
96 lines (94 loc) • 3.63 kB
JavaScript
var particleVS = `
fn unpack3NFloats(src: f32) -> vec3f {
let r = fract(src);
let g = fract(src * 256.0);
let b = fract(src * 65536.0);
return vec3f(r, g, b);
}
fn saturate(x: f32) -> f32 {
return clamp(x, 0.0, 1.0);
}
struct TexLerpUnpackResult {
result: vec4f,
unpacked: vec3f
}
fn tex1Dlod_lerp_simple(tex: texture_2d<f32>, texSampler: sampler, tc: vec2f) -> vec4f {
let tc_next = tc + vec2f(uniform.graphSampleSize);
return mix( textureSample(tex, texSampler, tc), textureSample(tex, texSampler, tc_next), fract(tc.x * uniform.graphNumSamples) );
}
fn tex1Dlod_lerp_unpack(tex: texture_2d<f32>, texSampler: sampler, tc: vec2f) -> TexLerpUnpackResult {
let tc_next = tc + vec2f(uniform.graphSampleSize);
let a = textureSampleLevel(tex, texSampler, tc, 0.0);
let b = textureSampleLevel(tex, texSampler, tc_next, 0.0);
let c = fract(tc.x * uniform.graphNumSamples);
let unpackedA = unpack3NFloats(a.w);
let unpackedB = unpack3NFloats(b.w);
let w_out = mix(unpackedA, unpackedB, c);
return TexLerpUnpackResult(mix(a, b, c), w_out);
}
struct RotateResult {
rotatedVec: vec2f,
matrix: mat2x2f
}
fn rotateWithMatrix(quadXY: vec2f, pRotation: f32) -> RotateResult {
let c = cos(pRotation);
let s = sin(pRotation);
let m = mat2x2f(vec2f(c, s), vec2f(-s, c));
return RotateResult(m * quadXY, m);
}
fn billboard(InstanceCoords: vec3f, quadXY: vec2f) -> vec3f {
var pos: vec3f;
#ifdef SCREEN_SPACE
pos = vec3f(-1.0, 0.0, 0.0) * quadXY.x + vec3f(0.0, -1.0, 0.0) * quadXY.y;
#else
pos = -uniform.matrix_viewInverse[0].xyz * quadXY.x + -uniform.matrix_viewInverse[1].xyz * quadXY.y;
#endif
return pos;
}
fn customFace(InstanceCoords: vec3f, quadXY: vec2f) -> vec3f {
let pos = uniform.faceTangent * quadXY.x + uniform.faceBinorm * quadXY.y;
return pos;
}
fn safeNormalize(v: vec2f) -> vec2f {
let l = length(v);
return select(v, v / l, l > 1e-06);
}
@vertex
fn vertexMain(input: VertexInput) -> VertexOutput {
var output: VertexOutput;
let meshLocalPos_in = input.particle_vertexData.xyz;
let id = floor(input.particle_vertexData.w);
let rndFactor = fract(sin(id + 1.0 + uniform.seed));
let rndFactor3 = vec3f(rndFactor, fract(rndFactor*10.0), fract(rndFactor*100.0));
let uv = id / uniform.numParticlesPot;
readInput(uv);
#ifdef LOCAL_SPACE
let modelRotation = mat3x3f(uniform.matrix_model[0].xyz, uniform.matrix_model[1].xyz, uniform.matrix_model[2].xyz);
inVel = modelRotation * inVel;
#endif
let viewRotation = mat3x3f(uniform.matrix_view[0].xyz, uniform.matrix_view[1].xyz, uniform.matrix_view[2].xyz);
let velocityV = safeNormalize((viewRotation * inVel).xy);
let particleLifetime = uniform.lifetime;
var meshLocalPos = meshLocalPos_in;
if (inLife <= 0.0 || inLife > particleLifetime || !inShow) {
meshLocalPos = vec3f(0.0);
}
let quadXY = meshLocalPos.xy;
let nlife = clamp(inLife / particleLifetime, 0.0, 1.0);
let lerp_result = tex1Dlod_lerp_unpack(internalTex2, internalTex2Sampler, vec2f(nlife, 0.0));
let params = lerp_result.result;
let paramDiv = lerp_result.unpacked;
var scale = params.y;
let scaleDiv = paramDiv.x;
let alphaDiv = paramDiv.z;
scale = scale + (scaleDiv * 2.0 - 1.0) * uniform.scaleDivMult * fract(rndFactor*10000.0);
#ifndef USE_MESH
output.texCoordsAlphaLife = vec4f(quadXY * -0.5 + 0.5, (alphaDiv * 2.0 - 1.0) * uniform.alphaDivMult * fract(rndFactor*1000.0), nlife);
#else
output.texCoordsAlphaLife = vec4f(particle_uv, (alphaDiv * 2.0 - 1.0) * uniform.alphaDivMult * fract(rndFactor*1000.0), nlife);
#endif
var particlePos = inPos;
var particlePosMoved = vec3f(0.0);
var rotMatrix: mat2x2f;
`;
export { particleVS as default };