UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

86 lines (85 loc) 4.18 kB
import { hashCode } from "../../../core/hash.js"; import { MapUtils } from "../../../core/map-utils.js"; import { SEMANTIC_ATTR15, SEMANTIC_BLENDINDICES, SEMANTIC_BLENDWEIGHT, SHADERLANGUAGE_GLSL, SHADERLANGUAGE_WGSL } from "../../../platform/graphics/constants.js"; import { ShaderDefinitionUtils } from "../../../platform/graphics/shader-definition-utils.js"; import { ShaderGenerator } from "./shader-generator.js"; import { ShaderChunks } from "../shader-chunks.js"; class ShaderGeneratorShader extends ShaderGenerator { generateKey(options) { const desc = options.shaderDesc; const vsHashGLSL = desc.vertexGLSL ? hashCode(desc.vertexGLSL) : 0; const fsHashGLSL = desc.fragmentGLSL ? hashCode(desc.fragmentGLSL) : 0; const vsHashWGSL = desc.vertexWGSL ? hashCode(desc.vertexWGSL) : 0; const fsHashWGSL = desc.fragmentWGSL ? hashCode(desc.fragmentWGSL) : 0; const definesHash = ShaderGenerator.definesHash(options.defines); const chunksKey = options.shaderChunks?.key ?? ""; let key = `${desc.uniqueName}_${definesHash}_${vsHashGLSL}_${fsHashGLSL}_${vsHashWGSL}_${fsHashWGSL}_${chunksKey}`; if (options.skin) key += "_skin"; if (options.useInstancing) key += "_inst"; if (options.useMorphPosition) key += "_morphp"; if (options.useMorphNormal) key += "_morphn"; if (options.useMorphTextureBasedInt) key += "_morphi"; return key; } createAttributesDefinition(definitionOptions, options) { const srcAttributes = options.shaderDesc.attributes; const attributes = srcAttributes ? { ...srcAttributes } : void 0; if (options.skin) { attributes.vertex_boneWeights = SEMANTIC_BLENDWEIGHT; attributes.vertex_boneIndices = SEMANTIC_BLENDINDICES; } if (options.useMorphPosition || options.useMorphNormal) { attributes.morph_vertex_id = SEMANTIC_ATTR15; } definitionOptions.attributes = attributes; } createVertexDefinition(definitionOptions, options, sharedIncludes, wgsl) { const desc = options.shaderDesc; const includes = new Map(sharedIncludes); includes.set("transformInstancingVS", ""); const defines = new Map(options.defines); if (options.skin) defines.set("SKIN", true); if (options.useInstancing) defines.set("INSTANCING", true); if (options.useMorphPosition || options.useMorphNormal) { defines.set("MORPHING", true); if (options.useMorphTextureBasedInt) defines.set("MORPHING_INT", true); if (options.useMorphPosition) defines.set("MORPHING_POSITION", true); if (options.useMorphNormal) defines.set("MORPHING_NORMAL", true); } definitionOptions.vertexCode = wgsl ? desc.vertexWGSL : desc.vertexGLSL; definitionOptions.vertexIncludes = includes; definitionOptions.vertexDefines = defines; } createFragmentDefinition(definitionOptions, options, sharedIncludes, wgsl) { const desc = options.shaderDesc; const includes = new Map(sharedIncludes); const defines = new Map(options.defines); definitionOptions.fragmentCode = wgsl ? desc.fragmentWGSL : desc.fragmentGLSL; definitionOptions.fragmentIncludes = includes; definitionOptions.fragmentDefines = defines; } createShaderDefinition(device, options) { const desc = options.shaderDesc; const wgsl = device.isWebGPU && !!desc.vertexWGSL && !!desc.fragmentWGSL && (options.shaderChunks?.useWGSL ?? true); const definitionOptions = { name: `ShaderMaterial-${desc.uniqueName}`, shaderLanguage: wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL, fragmentOutputTypes: desc.fragmentOutputTypes, meshUniformBufferFormat: desc.meshUniformBufferFormat, meshBindGroupFormat: desc.meshBindGroupFormat }; const shaderLanguage = wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL; const sharedIncludes = MapUtils.merge( ShaderChunks.get(device, shaderLanguage), options.shaderChunks[shaderLanguage] ); this.createAttributesDefinition(definitionOptions, options); this.createVertexDefinition(definitionOptions, options, sharedIncludes, wgsl); this.createFragmentDefinition(definitionOptions, options, sharedIncludes, wgsl); return ShaderDefinitionUtils.createDefinition(device, definitionOptions); } } const shaderGeneratorShader = new ShaderGeneratorShader(); export { shaderGeneratorShader };