UNPKG

@animech-public/playcanvas

Version:
114 lines (111 loc) 5.69 kB
import { ShaderUtils } from '../../../platform/graphics/shader-utils.js'; import { BLEND_NORMAL, BLEND_ADDITIVE, BLEND_MULTIPLICATIVE } from '../../constants.js'; import { shaderChunks } from '../chunks/chunks.js'; import { ShaderGenerator } from './shader-generator.js'; class ShaderGeneratorParticle extends ShaderGenerator { generateKey(options) { let key = 'particle'; for (const prop in options) { if (options.hasOwnProperty(prop)) { key += options[prop]; } } return key; } _animTex(options) { let vshader = ''; vshader += options.animTexLoop ? shaderChunks.particleAnimFrameLoopVS : shaderChunks.particleAnimFrameClampVS; vshader += shaderChunks.particleAnimTexVS; return vshader; } createShaderDefinition(device, options) { const executionDefine = `#define PARTICLE_${options.useCpu ? 'CPU' : 'GPU'}\n`; let fshader = `#define PARTICLE\n${executionDefine}`; let vshader = `#define VERTEXSHADER\n${executionDefine}`; if (options.mesh) vshader += '#define USE_MESH\n'; if (options.localSpace) vshader += '#define LOCAL_SPACE\n'; if (options.screenSpace) vshader += '#define SCREEN_SPACE\n'; if (options.animTex) vshader += '\nuniform vec2 animTexTilesParams;\n'; if (options.animTex) vshader += '\nuniform vec4 animTexParams;\n'; if (options.animTex) vshader += '\nuniform vec2 animTexIndexParams;\n'; if (options.normal === 2) vshader += '\nvarying mat3 ParticleMat;\n'; if (options.normal === 1) vshader += '\nvarying vec3 Normal;\n'; if (options.soft) vshader += '\nvarying float vDepth;\n'; const faceVS = options.customFace ? shaderChunks.particle_customFaceVS : shaderChunks.particle_billboardVS; if (!options.useCpu) { vshader += shaderChunks.particle_initVS; vshader += options.pack8 ? shaderChunks.particleInputRgba8PS : shaderChunks.particleInputFloatPS; if (options.soft > 0) vshader += shaderChunks.screenDepthPS; vshader += shaderChunks.particleVS; if (options.localSpace) vshader += shaderChunks.particle_localShiftVS; if (options.animTex) vshader += this._animTex(options); if (options.wrap) vshader += shaderChunks.particle_wrapVS; if (options.alignToMotion) vshader += shaderChunks.particle_pointAlongVS; vshader += options.mesh ? shaderChunks.particle_meshVS : faceVS; if (options.normal === 1) vshader += shaderChunks.particle_normalVS; if (options.normal === 2) vshader += shaderChunks.particle_TBNVS; if (options.stretch > 0.0) vshader += shaderChunks.particle_stretchVS; vshader += shaderChunks.particle_endVS; if (options.soft > 0) vshader += shaderChunks.particle_softVS; } else { if (options.soft > 0) vshader += shaderChunks.screenDepthPS; vshader += shaderChunks.particle_cpuVS; if (options.localSpace) vshader += shaderChunks.particle_localShiftVS; if (options.animTex) vshader += this._animTex(options); // if (options.wrap) vshader += shaderChunks.particle_wrapVS; if (options.alignToMotion) vshader += shaderChunks.particle_pointAlongVS; vshader += options.mesh ? shaderChunks.particle_meshVS : faceVS; if (options.normal === 1) vshader += shaderChunks.particle_normalVS; if (options.normal === 2) vshader += shaderChunks.particle_TBNVS; if (options.stretch > 0.0) vshader += shaderChunks.particle_stretchVS; vshader += shaderChunks.particle_cpu_endVS; if (options.soft > 0) vshader += shaderChunks.particle_softVS; } vshader += '}\n'; if (options.normal > 0) { if (options.normal === 1) { fshader += '\nvarying vec3 Normal;\n'; } else if (options.normal === 2) { fshader += '\nvarying mat3 ParticleMat;\n'; } fshader += '\nuniform vec3 lightCube[6];\n'; } if (options.soft) fshader += '\nvarying float vDepth;\n'; if (options.normal === 0 && options.fog === 'none') options.srgb = false; // don't have to perform all gamma conversions when no lighting and fogging is used fshader += shaderChunks.decodePS; fshader += ShaderGenerator.gammaCode(options.gamma); fshader += ShaderGenerator.tonemapCode(options.toneMap); if (options.fog === 'linear') { fshader += shaderChunks.fogLinearPS; } else if (options.fog === 'exp') { fshader += shaderChunks.fogExpPS; } else if (options.fog === 'exp2') { fshader += shaderChunks.fogExp2PS; } else { fshader += shaderChunks.fogNonePS; } if (options.normal === 2) fshader += '\nuniform sampler2D normalMap;\n'; if (options.soft > 0) fshader += shaderChunks.screenDepthPS; fshader += shaderChunks.particlePS; if (options.soft > 0) fshader += shaderChunks.particle_softPS; if (options.normal === 1) fshader += '\nvec3 normal = Normal;\n'; if (options.normal === 2) fshader += shaderChunks.particle_normalMapPS; if (options.normal > 0) fshader += options.halflambert ? shaderChunks.particle_halflambertPS : shaderChunks.particle_lambertPS; if (options.normal > 0) fshader += shaderChunks.particle_lightingPS; if (options.blend === BLEND_NORMAL) { fshader += shaderChunks.particle_blendNormalPS; } else if (options.blend === BLEND_ADDITIVE) { fshader += shaderChunks.particle_blendAddPS; } else if (options.blend === BLEND_MULTIPLICATIVE) { fshader += shaderChunks.particle_blendMultiplyPS; } fshader += shaderChunks.particle_endPS; return ShaderUtils.createDefinition(device, { name: 'ParticleShader', vertexCode: vshader, fragmentCode: fshader }); } } const particle = new ShaderGeneratorParticle(); export { particle };