UNPKG

playcanvas

Version:

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

261 lines (260 loc) 8.17 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { Debug } from "../../core/debug.js"; import { math } from "../../core/math/math.js"; import { uniformTypeToName, UNIFORMTYPE_BOOL, UNIFORMTYPE_INT, UNIFORMTYPE_FLOAT, UNIFORMTYPE_UINT, UNIFORMTYPE_VEC2, UNIFORMTYPE_VEC3, UNIFORMTYPE_VEC4, UNIFORMTYPE_IVEC2, UNIFORMTYPE_UVEC2, UNIFORMTYPE_IVEC3, UNIFORMTYPE_IVEC4, UNIFORMTYPE_BVEC2, UNIFORMTYPE_BVEC3, UNIFORMTYPE_UVEC3, UNIFORMTYPE_BVEC4, UNIFORMTYPE_MAT4, UNIFORMTYPE_MAT2, UNIFORMTYPE_MAT3, UNIFORMTYPE_FLOATARRAY, UNIFORMTYPE_UVEC4, UNIFORMTYPE_VEC2ARRAY, UNIFORMTYPE_VEC3ARRAY, UNIFORMTYPE_VEC4ARRAY, UNIFORMTYPE_MAT4ARRAY, UNIFORMTYPE_INTARRAY, UNIFORMTYPE_UINTARRAY, UNIFORMTYPE_BOOLARRAY, UNIFORMTYPE_IVEC2ARRAY, UNIFORMTYPE_UVEC2ARRAY, UNIFORMTYPE_BVEC2ARRAY, UNIFORMTYPE_IVEC3ARRAY, UNIFORMTYPE_UVEC3ARRAY, UNIFORMTYPE_BVEC3ARRAY, UNIFORMTYPE_IVEC4ARRAY, UNIFORMTYPE_UVEC4ARRAY, UNIFORMTYPE_BVEC4ARRAY } from "./constants.js"; const uniformTypeToNumComponents = []; uniformTypeToNumComponents[UNIFORMTYPE_FLOAT] = 1; uniformTypeToNumComponents[UNIFORMTYPE_VEC2] = 2; uniformTypeToNumComponents[UNIFORMTYPE_VEC3] = 3; uniformTypeToNumComponents[UNIFORMTYPE_VEC4] = 4; uniformTypeToNumComponents[UNIFORMTYPE_INT] = 1; uniformTypeToNumComponents[UNIFORMTYPE_IVEC2] = 2; uniformTypeToNumComponents[UNIFORMTYPE_IVEC3] = 3; uniformTypeToNumComponents[UNIFORMTYPE_IVEC4] = 4; uniformTypeToNumComponents[UNIFORMTYPE_BOOL] = 1; uniformTypeToNumComponents[UNIFORMTYPE_BVEC2] = 2; uniformTypeToNumComponents[UNIFORMTYPE_BVEC3] = 3; uniformTypeToNumComponents[UNIFORMTYPE_BVEC4] = 4; uniformTypeToNumComponents[UNIFORMTYPE_MAT2] = 8; uniformTypeToNumComponents[UNIFORMTYPE_MAT3] = 12; uniformTypeToNumComponents[UNIFORMTYPE_MAT4] = 16; uniformTypeToNumComponents[UNIFORMTYPE_UINT] = 1; uniformTypeToNumComponents[UNIFORMTYPE_UVEC2] = 2; uniformTypeToNumComponents[UNIFORMTYPE_UVEC3] = 3; uniformTypeToNumComponents[UNIFORMTYPE_UVEC4] = 4; class UniformFormat { /** * Create a new UniformFormat instance. * * @param {string} name - The name of the uniform. * @param {number} type - The type of the uniform. One of the UNIFORMTYPE_*** constants. * @param {number} count - The number of elements in the array. Defaults to 0, which represents * a single element (not an array). */ constructor(name, type, count = 0) { /** * @type {string} * @ignore */ __publicField(this, "name"); // UNIFORMTYPE_*** /** * @type {number} * @ignore */ __publicField(this, "type"); /** * @type {number} * @ignore */ __publicField(this, "byteSize"); /** * Index of the uniform in an array of 32bit values (Float32Array and similar) * * @type {number} * @ignore */ __publicField(this, "offset"); /** * @type {ScopeId} * @ignore */ __publicField(this, "scopeId"); /** * Count of elements for arrays, otherwise 0. * * @type {number} * @ignore */ __publicField(this, "count"); /** * Number of components in each element (e.g. vec2 has 2 components, mat4 has 16 components) * * @type {number} * @ignore */ __publicField(this, "numComponents"); this.shortName = name; this.name = count ? `${name}[0]` : name; this.type = type; this.numComponents = uniformTypeToNumComponents[type]; Debug.assert(this.numComponents, `Unhandled uniform format ${type} used for ${name}`); this.updateType = type; if (count > 0) { switch (type) { case UNIFORMTYPE_FLOAT: this.updateType = UNIFORMTYPE_FLOATARRAY; break; case UNIFORMTYPE_INT: this.updateType = UNIFORMTYPE_INTARRAY; break; case UNIFORMTYPE_UINT: this.updateType = UNIFORMTYPE_UINTARRAY; break; case UNIFORMTYPE_BOOL: this.updateType = UNIFORMTYPE_BOOLARRAY; break; case UNIFORMTYPE_VEC2: this.updateType = UNIFORMTYPE_VEC2ARRAY; break; case UNIFORMTYPE_IVEC2: this.updateType = UNIFORMTYPE_IVEC2ARRAY; break; case UNIFORMTYPE_UVEC2: this.updateType = UNIFORMTYPE_UVEC2ARRAY; break; case UNIFORMTYPE_BVEC2: this.updateType = UNIFORMTYPE_BVEC2ARRAY; break; case UNIFORMTYPE_VEC3: this.updateType = UNIFORMTYPE_VEC3ARRAY; break; case UNIFORMTYPE_IVEC3: this.updateType = UNIFORMTYPE_IVEC3ARRAY; break; case UNIFORMTYPE_UVEC3: this.updateType = UNIFORMTYPE_UVEC3ARRAY; break; case UNIFORMTYPE_BVEC3: this.updateType = UNIFORMTYPE_BVEC3ARRAY; break; case UNIFORMTYPE_VEC4: this.updateType = UNIFORMTYPE_VEC4ARRAY; break; case UNIFORMTYPE_IVEC4: this.updateType = UNIFORMTYPE_IVEC4ARRAY; break; case UNIFORMTYPE_UVEC4: this.updateType = UNIFORMTYPE_UVEC4ARRAY; break; case UNIFORMTYPE_BVEC4: this.updateType = UNIFORMTYPE_BVEC4ARRAY; break; case UNIFORMTYPE_MAT4: this.updateType = UNIFORMTYPE_MAT4ARRAY; break; default: Debug.error(`Uniform array of type ${uniformTypeToName[type]} is not supported when processing uniform '${name}'.`); Debug.call(() => { this.invalid = true; }); break; } } this.count = count; Debug.assert(!isNaN(count), `Unsupported uniform: ${name}[${count}]`); Debug.call(() => { if (isNaN(count)) { this.invalid = true; } }); let componentSize = this.numComponents; if (count) { componentSize = math.roundUp(componentSize, 4); } this.byteSize = componentSize * 4; if (count) { this.byteSize *= count; } Debug.assert(this.byteSize, `Unknown byte size for uniform format ${type} used for ${name}`); } /** * True if this is an array of elements (i.e. count > 0) * * @type {boolean} */ get isArrayType() { return this.count > 0; } // std140 rules: https://registry.khronos.org/OpenGL/specs/gl/glspec45.core.pdf#page=159 // TODO: this supports limited subset of functionality, arrays and arrays of structs are not supported. calculateOffset(offset) { let alignment = this.byteSize <= 8 ? this.byteSize : 16; if (this.count) { alignment = 16; } offset = math.roundUp(offset, alignment); this.offset = offset / 4; } } class UniformBufferFormat { /** * Create a new UniformBufferFormat instance. * * @param {GraphicsDevice} graphicsDevice - The graphics device. * @param {UniformFormat[]} uniforms - An array of uniforms to be stored in the buffer */ constructor(graphicsDevice, uniforms) { /** @ignore */ __publicField(this, "byteSize", 0); /** * @type {Map<string,UniformFormat>} * @ignore */ __publicField(this, "map", /* @__PURE__ */ new Map()); this.scope = graphicsDevice.scope; this.uniforms = uniforms; let offset = 0; for (let i = 0; i < uniforms.length; i++) { const uniform = uniforms[i]; uniform.calculateOffset(offset); offset = uniform.offset * 4 + uniform.byteSize; uniform.scopeId = this.scope.resolve(uniform.name); this.map.set(uniform.name, uniform); } this.byteSize = math.roundUp(offset, 16); } /** * Returns format of a uniform with specified name. Returns undefined if the uniform is not found. * * @param {string} name - The name of the uniform. * @returns {UniformFormat|undefined} - The format of the uniform. */ get(name) { return this.map.get(name); } } export { UniformBufferFormat, UniformFormat };