UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

121 lines (118 loc) 4.72 kB
import { Debug } from '../core/debug.js'; import { DeviceCache } from '../platform/graphics/device-cache.js'; import { SHADER_DEPTH, SHADER_PICK, SHADER_FORWARD, SHADER_PREPASS, SHADER_SHADOW } from './constants.js'; /** * @import { GraphicsDevice } from '../platform/graphics/graphics-device.js' */ // device cache storing shader pass data per device var shaderPassDeviceCache = new DeviceCache(); /** * Info about a shader pass. Shader pass is represented by a unique index and a name, and the * index is used to access the shader required for the pass, from an array stored in the * material or mesh instance. */ class ShaderPassInfo { buildShaderDefines() { var keyword; if (this.isShadow) { keyword = 'SHADOW'; } else if (this.isForward) { keyword = 'FORWARD'; } else if (this.index === SHADER_DEPTH) { keyword = 'DEPTH'; } else if (this.index === SHADER_PICK) { keyword = 'PICK'; } this.defines.set("" + keyword + "_PASS", ''); this.defines.set("" + this.name.toUpperCase() + "_PASS", ''); } /** * @param {string} name - The name, for example 'depth'. Must contain only letters, numbers, * and underscores, and start with a letter. * @param {number} index - Index from ShaderPass#nextIndex. * @param {object} [options] - Options for additional configuration of the shader pass. * @param {boolean} [options.isForward] - Whether the pass is forward. * @param {boolean} [options.isShadow] - Whether the pass is shadow. * @param {boolean} [options.lightType] - Type of light, for example `pc.LIGHTTYPE_DIRECTIONAL`. * @param {boolean} [options.shadowType] - Type of shadow, for example `pc.SHADOW_PCF3_32F`. */ constructor(name, index, options = {}){ /** @type {Map<string, string} */ this.defines = new Map(); Debug.assert(/^[a-z]\w*$/i.test(name), "ShaderPass name can only contain letters, numbers and underscores and start with a letter: " + name); this.name = name; this.index = index; // assign options as properties to this object Object.assign(this, options); this.buildShaderDefines(); } } /** * Class responsible for management of shader passes, associated with a device. * * @ignore */ class ShaderPass { /** * Get access to the shader pass instance for the specified device. * * @param {GraphicsDevice} device - The graphics device. * @returns { ShaderPass } The shader pass instance for the specified device. */ static get(device) { Debug.assert(device); return shaderPassDeviceCache.get(device, ()=>{ return new ShaderPass(); }); } /** * Allocates a shader pass with the specified name and options. * * @param {string} name - A name of the shader pass. * @param {object} [options] - Options for the shader pass, which are added as properties to the * shader pass info. * @returns {ShaderPassInfo} The allocated shader pass info. */ allocate(name, options) { var info = this.passesNamed.get(name); if (info === undefined) { info = new ShaderPassInfo(name, this.nextIndex, options); this.passesNamed.set(info.name, info); this.passesIndexed[info.index] = info; this.nextIndex++; } return info; } /** * Return the shader pass info for the specified index. * * @param {number} index - The shader pass index. * @returns {ShaderPassInfo} - The shader pass info. */ getByIndex(index) { var info = this.passesIndexed[index]; Debug.assert(info); return info; } getByName(name) { return this.passesNamed.get(name); } constructor(){ /** * Allocated shader passes, map of a shader pass name to info. * * @type {Map<string, ShaderPassInfo>} */ this.passesNamed = new Map(); /** * Allocated shader passes, indexed by their index. * * @type {Array<ShaderPassInfo>} */ this.passesIndexed = []; /** Next available index */ this.nextIndex = 0; var add = (name, index, options)=>{ var info = this.allocate(name, options); Debug.assert(info.index === index); }; // add default passes in the required order, to match the constants add('forward', SHADER_FORWARD, { isForward: true }); add('prepass', SHADER_PREPASS); add('depth', SHADER_DEPTH); add('pick', SHADER_PICK); add('shadow', SHADER_SHADOW); } } export { ShaderPass, ShaderPassInfo };