playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
95 lines (94 loc) • 3.55 kB
JavaScript
import {
SEMANTIC_ATTR1,
SEMANTIC_ATTR2,
SEMANTIC_ATTR3,
SEMANTIC_ATTR4,
SEMANTIC_POSITION,
SEMANTIC_TEXCOORD0,
SHADERLANGUAGE_GLSL,
SHADERLANGUAGE_WGSL
} from "../../../platform/graphics/constants.js";
import { ShaderDefinitionUtils } from "../../../platform/graphics/shader-definition-utils.js";
import { blendNames } from "../../constants.js";
import { ShaderGenerator } from "./shader-generator.js";
import { ShaderChunks } from "../shader-chunks.js";
const normalTypeNames = [
"NONE",
"VERTEX",
"MAP"
];
class ShaderGeneratorParticle extends ShaderGenerator {
generateKey(options) {
const definesHash = ShaderGenerator.definesHash(options.defines);
let key = `particle_${definesHash}_`;
for (const prop in options) {
if (options.hasOwnProperty(prop)) {
key += options[prop];
}
}
return key;
}
createVertexDefines(options, attributes) {
const vDefines = new Map(options.defines);
if (options.mesh) vDefines.set("USE_MESH", "");
if (options.meshUv) vDefines.set("USE_MESH_UV", "");
if (options.localSpace) vDefines.set("LOCAL_SPACE", "");
if (options.screenSpace) vDefines.set("SCREEN_SPACE", "");
if (options.animTex) vDefines.set("ANIMTEX", "");
if (options.soft > 0) vDefines.set("SOFT", "");
if (options.stretch > 0) vDefines.set("STRETCH", "");
if (options.customFace) vDefines.set("CUSTOM_FACE", "");
if (options.pack8) vDefines.set("PACK8", "");
if (options.localSpace) vDefines.set("LOCAL_SPACE", "");
if (options.animTexLoop) vDefines.set("ANIMTEX_LOOP", "");
if (options.wrap) vDefines.set("WRAP", "");
if (options.alignToMotion) vDefines.set("ALIGN_TO_MOTION", "");
vDefines.set("NORMAL", normalTypeNames[options.normal]);
attributes.particle_vertexData = SEMANTIC_POSITION;
if (options.mesh && options.meshUv) {
attributes.particle_uv = SEMANTIC_TEXCOORD0;
}
if (options.useCpu) {
attributes.particle_vertexData2 = SEMANTIC_ATTR1;
attributes.particle_vertexData3 = SEMANTIC_ATTR2;
attributes.particle_vertexData4 = SEMANTIC_ATTR3;
attributes.particle_vertexData5 = SEMANTIC_ATTR4;
}
return vDefines;
}
createFragmentDefines(options) {
const fDefines = new Map(options.defines);
if (options.soft > 0) fDefines.set("SOFT", "");
if (options.halflambert) fDefines.set("HALF_LAMBERT", "");
fDefines.set("NORMAL", normalTypeNames[options.normal]);
fDefines.set("BLEND", blendNames[options.blend]);
return fDefines;
}
createShaderDefinition(device, options) {
const shaderLanguage = device.isWebGPU ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL;
const engineChunks = ShaderChunks.get(device, shaderLanguage);
const attributes = {};
const vDefines = this.createVertexDefines(options, attributes);
const fDefines = this.createFragmentDefines(options);
const executionDefine = `PARTICLE_${options.useCpu ? "CPU" : "GPU"}
`;
vDefines.set(executionDefine, "");
fDefines.set(executionDefine, "");
const includes = new Map(engineChunks);
return ShaderDefinitionUtils.createDefinition(device, {
name: "ParticleShader",
shaderLanguage,
attributes,
vertexCode: engineChunks.get("particle_shaderVS"),
fragmentCode: engineChunks.get("particle_shaderPS"),
fragmentDefines: fDefines,
fragmentIncludes: includes,
vertexIncludes: includes,
vertexDefines: vDefines
});
}
}
const particle = new ShaderGeneratorParticle();
export {
particle
};