123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873 |
- import { Logger } from "../Misc/logger.js";
- import { Tools } from "../Misc/tools.js";
- import "../Engines/Extensions/engine.uniformBuffer.js";
- /**
- * Uniform buffer objects.
- *
- * Handles blocks of uniform on the GPU.
- *
- * If WebGL 2 is not available, this class falls back on traditional setUniformXXX calls.
- *
- * For more information, please refer to :
- * https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object
- */
- export class UniformBuffer {
- /**
- * Instantiates a new Uniform buffer objects.
- *
- * Handles blocks of uniform on the GPU.
- *
- * If WebGL 2 is not available, this class falls back on traditional setUniformXXX calls.
- *
- * For more information, please refer to :
- * @see https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object
- * @param engine Define the engine the buffer is associated with
- * @param data Define the data contained in the buffer
- * @param dynamic Define if the buffer is updatable
- * @param name to assign to the buffer (debugging purpose)
- * @param forceNoUniformBuffer define that this object must not rely on UBO objects
- */
- constructor(engine, data, dynamic, name, forceNoUniformBuffer = false) {
- // Matrix cache
- this._valueCache = {};
- this._engine = engine;
- this._noUBO = !engine.supportsUniformBuffers || forceNoUniformBuffer;
- this._dynamic = dynamic;
- this._name = name ?? "no-name";
- this._data = data || [];
- this._uniformLocations = {};
- this._uniformSizes = {};
- this._uniformArraySizes = {};
- this._uniformLocationPointer = 0;
- this._needSync = false;
- if (this._engine._features.trackUbosInFrame) {
- this._buffers = [];
- this._bufferIndex = -1;
- this._createBufferOnWrite = false;
- this._currentFrameId = 0;
- }
- if (this._noUBO) {
- this.updateMatrix3x3 = this._updateMatrix3x3ForEffect;
- this.updateMatrix2x2 = this._updateMatrix2x2ForEffect;
- this.updateFloat = this._updateFloatForEffect;
- this.updateFloat2 = this._updateFloat2ForEffect;
- this.updateFloat3 = this._updateFloat3ForEffect;
- this.updateFloat4 = this._updateFloat4ForEffect;
- this.updateFloatArray = this._updateFloatArrayForEffect;
- this.updateArray = this._updateArrayForEffect;
- this.updateIntArray = this._updateIntArrayForEffect;
- this.updateUIntArray = this._updateUIntArrayForEffect;
- this.updateMatrix = this._updateMatrixForEffect;
- this.updateMatrices = this._updateMatricesForEffect;
- this.updateVector3 = this._updateVector3ForEffect;
- this.updateVector4 = this._updateVector4ForEffect;
- this.updateColor3 = this._updateColor3ForEffect;
- this.updateColor4 = this._updateColor4ForEffect;
- this.updateDirectColor4 = this._updateDirectColor4ForEffect;
- this.updateInt = this._updateIntForEffect;
- this.updateInt2 = this._updateInt2ForEffect;
- this.updateInt3 = this._updateInt3ForEffect;
- this.updateInt4 = this._updateInt4ForEffect;
- this.updateUInt = this._updateUIntForEffect;
- this.updateUInt2 = this._updateUInt2ForEffect;
- this.updateUInt3 = this._updateUInt3ForEffect;
- this.updateUInt4 = this._updateUInt4ForEffect;
- }
- else {
- this._engine._uniformBuffers.push(this);
- this.updateMatrix3x3 = this._updateMatrix3x3ForUniform;
- this.updateMatrix2x2 = this._updateMatrix2x2ForUniform;
- this.updateFloat = this._updateFloatForUniform;
- this.updateFloat2 = this._updateFloat2ForUniform;
- this.updateFloat3 = this._updateFloat3ForUniform;
- this.updateFloat4 = this._updateFloat4ForUniform;
- this.updateFloatArray = this._updateFloatArrayForUniform;
- this.updateArray = this._updateArrayForUniform;
- this.updateIntArray = this._updateIntArrayForUniform;
- this.updateUIntArray = this._updateUIntArrayForUniform;
- this.updateMatrix = this._updateMatrixForUniform;
- this.updateMatrices = this._updateMatricesForUniform;
- this.updateVector3 = this._updateVector3ForUniform;
- this.updateVector4 = this._updateVector4ForUniform;
- this.updateColor3 = this._updateColor3ForUniform;
- this.updateColor4 = this._updateColor4ForUniform;
- this.updateDirectColor4 = this._updateDirectColor4ForUniform;
- this.updateInt = this._updateIntForUniform;
- this.updateInt2 = this._updateInt2ForUniform;
- this.updateInt3 = this._updateInt3ForUniform;
- this.updateInt4 = this._updateInt4ForUniform;
- this.updateUInt = this._updateUIntForUniform;
- this.updateUInt2 = this._updateUInt2ForUniform;
- this.updateUInt3 = this._updateUInt3ForUniform;
- this.updateUInt4 = this._updateUInt4ForUniform;
- }
- }
- /**
- * Indicates if the buffer is using the WebGL2 UBO implementation,
- * or just falling back on setUniformXXX calls.
- */
- get useUbo() {
- return !this._noUBO;
- }
- /**
- * Indicates if the WebGL underlying uniform buffer is in sync
- * with the javascript cache data.
- */
- get isSync() {
- return !this._needSync;
- }
- /**
- * Indicates if the WebGL underlying uniform buffer is dynamic.
- * Also, a dynamic UniformBuffer will disable cache verification and always
- * update the underlying WebGL uniform buffer to the GPU.
- * @returns if Dynamic, otherwise false
- */
- isDynamic() {
- return this._dynamic !== undefined;
- }
- /**
- * The data cache on JS side.
- * @returns the underlying data as a float array
- */
- getData() {
- return this._bufferData;
- }
- /**
- * The underlying WebGL Uniform buffer.
- * @returns the webgl buffer
- */
- getBuffer() {
- return this._buffer;
- }
- /**
- * std140 layout specifies how to align data within an UBO structure.
- * See https://khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf#page=159
- * for specs.
- * @param size
- */
- _fillAlignment(size) {
- // This code has been simplified because we only use floats, vectors of 1, 2, 3, 4 components
- // and 4x4 matrices
- // TODO : change if other types are used
- let alignment;
- if (size <= 2) {
- alignment = size;
- }
- else {
- alignment = 4;
- }
- if (this._uniformLocationPointer % alignment !== 0) {
- const oldPointer = this._uniformLocationPointer;
- this._uniformLocationPointer += alignment - (this._uniformLocationPointer % alignment);
- const diff = this._uniformLocationPointer - oldPointer;
- for (let i = 0; i < diff; i++) {
- this._data.push(0);
- }
- }
- }
- /**
- * Adds an uniform in the buffer.
- * Warning : the subsequents calls of this function must be in the same order as declared in the shader
- * for the layout to be correct ! The addUniform function only handles types like float, vec2, vec3, vec4, mat4,
- * meaning size=1,2,3,4 or 16. It does not handle struct types.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param size Data size, or data directly.
- * @param arraySize The number of elements in the array, 0 if not an array.
- */
- addUniform(name, size, arraySize = 0) {
- if (this._noUBO) {
- return;
- }
- if (this._uniformLocations[name] !== undefined) {
- // Already existing uniform
- return;
- }
- // This function must be called in the order of the shader layout !
- // size can be the size of the uniform, or data directly
- let data;
- // std140 FTW...
- if (arraySize > 0) {
- if (size instanceof Array) {
- // eslint-disable-next-line no-throw-literal
- throw "addUniform should not be use with Array in UBO: " + name;
- }
- this._fillAlignment(4);
- this._uniformArraySizes[name] = { strideSize: size, arraySize };
- if (size == 16) {
- size = size * arraySize;
- }
- else {
- const perElementPadding = 4 - size;
- const totalPadding = perElementPadding * arraySize;
- size = size * arraySize + totalPadding;
- }
- data = [];
- // Fill with zeros
- for (let i = 0; i < size; i++) {
- data.push(0);
- }
- }
- else {
- if (size instanceof Array) {
- data = size;
- size = data.length;
- }
- else {
- size = size;
- data = [];
- // Fill with zeros
- for (let i = 0; i < size; i++) {
- data.push(0);
- }
- }
- this._fillAlignment(size);
- }
- this._uniformSizes[name] = size;
- this._uniformLocations[name] = this._uniformLocationPointer;
- this._uniformLocationPointer += size;
- for (let i = 0; i < size; i++) {
- this._data.push(data[i]);
- }
- this._needSync = true;
- }
- /**
- * Adds a Matrix 4x4 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param mat A 4x4 matrix.
- */
- addMatrix(name, mat) {
- this.addUniform(name, Array.prototype.slice.call(mat.asArray()));
- }
- /**
- * Adds a vec2 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param x Define the x component value of the vec2
- * @param y Define the y component value of the vec2
- */
- addFloat2(name, x, y) {
- const temp = [x, y];
- this.addUniform(name, temp);
- }
- /**
- * Adds a vec3 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param x Define the x component value of the vec3
- * @param y Define the y component value of the vec3
- * @param z Define the z component value of the vec3
- */
- addFloat3(name, x, y, z) {
- const temp = [x, y, z];
- this.addUniform(name, temp);
- }
- /**
- * Adds a vec3 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param color Define the vec3 from a Color
- */
- addColor3(name, color) {
- const temp = [color.r, color.g, color.b];
- this.addUniform(name, temp);
- }
- /**
- * Adds a vec4 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param color Define the rgb components from a Color
- * @param alpha Define the a component of the vec4
- */
- addColor4(name, color, alpha) {
- const temp = [color.r, color.g, color.b, alpha];
- this.addUniform(name, temp);
- }
- /**
- * Adds a vec3 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- * @param vector Define the vec3 components from a Vector
- */
- addVector3(name, vector) {
- const temp = [vector.x, vector.y, vector.z];
- this.addUniform(name, temp);
- }
- /**
- * Adds a Matrix 3x3 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- */
- addMatrix3x3(name) {
- this.addUniform(name, 12);
- }
- /**
- * Adds a Matrix 2x2 to the uniform buffer.
- * @param name Name of the uniform, as used in the uniform block in the shader.
- */
- addMatrix2x2(name) {
- this.addUniform(name, 8);
- }
- /**
- * Effectively creates the WebGL Uniform Buffer, once layout is completed with `addUniform`.
- */
- create() {
- if (this._noUBO) {
- return;
- }
- if (this._buffer) {
- return; // nothing to do
- }
- // See spec, alignment must be filled as a vec4
- this._fillAlignment(4);
- this._bufferData = new Float32Array(this._data);
- this._rebuild();
- this._needSync = true;
- }
- // The result of this method is used for debugging purpose, as part of the buffer name
- // It is meant to more easily know what this buffer is about when debugging
- // Some buffers can have a lot of uniforms (several dozens), so the method only returns the first 10 of them
- // (should be enough to understand what the buffer is for)
- _getNames() {
- const names = [];
- let i = 0;
- for (const name in this._uniformLocations) {
- names.push(name);
- if (++i === 10) {
- break;
- }
- }
- return names.join(",");
- }
- /** @internal */
- _rebuild() {
- if (this._noUBO || !this._bufferData) {
- return;
- }
- if (this._dynamic) {
- this._buffer = this._engine.createDynamicUniformBuffer(this._bufferData, this._name + "_UniformList:" + this._getNames());
- }
- else {
- this._buffer = this._engine.createUniformBuffer(this._bufferData, this._name + "_UniformList:" + this._getNames());
- }
- if (this._engine._features.trackUbosInFrame) {
- this._buffers.push([this._buffer, this._engine._features.checkUbosContentBeforeUpload ? this._bufferData.slice() : undefined]);
- this._bufferIndex = this._buffers.length - 1;
- this._createBufferOnWrite = false;
- }
- }
- /** @internal */
- _rebuildAfterContextLost() {
- if (this._engine._features.trackUbosInFrame) {
- this._buffers = [];
- this._currentFrameId = 0;
- }
- this._rebuild();
- }
- /** @internal */
- get _numBuffers() {
- return this._buffers.length;
- }
- /** @internal */
- get _indexBuffer() {
- return this._bufferIndex;
- }
- /** Gets the name of this buffer */
- get name() {
- return this._name;
- }
- /** Gets the current effect */
- get currentEffect() {
- return this._currentEffect;
- }
- _buffersEqual(buf1, buf2) {
- for (let i = 0; i < buf1.length; ++i) {
- if (buf1[i] !== buf2[i]) {
- return false;
- }
- }
- return true;
- }
- _copyBuffer(src, dst) {
- for (let i = 0; i < src.length; ++i) {
- dst[i] = src[i];
- }
- }
- /**
- * Updates the WebGL Uniform Buffer on the GPU.
- * If the `dynamic` flag is set to true, no cache comparison is done.
- * Otherwise, the buffer will be updated only if the cache differs.
- */
- update() {
- if (this._noUBO) {
- return;
- }
- this.bindUniformBuffer();
- if (!this._buffer) {
- this.create();
- return;
- }
- if (!this._dynamic && !this._needSync) {
- this._createBufferOnWrite = this._engine._features.trackUbosInFrame;
- return;
- }
- if (this._buffers && this._buffers.length > 1 && this._buffers[this._bufferIndex][1]) {
- if (this._buffersEqual(this._bufferData, this._buffers[this._bufferIndex][1])) {
- this._needSync = false;
- this._createBufferOnWrite = this._engine._features.trackUbosInFrame;
- return;
- }
- else {
- this._copyBuffer(this._bufferData, this._buffers[this._bufferIndex][1]);
- }
- }
- this._engine.updateUniformBuffer(this._buffer, this._bufferData);
- if (this._engine._features._collectUbosUpdatedInFrame) {
- if (!UniformBuffer._UpdatedUbosInFrame[this._name]) {
- UniformBuffer._UpdatedUbosInFrame[this._name] = 0;
- }
- UniformBuffer._UpdatedUbosInFrame[this._name]++;
- }
- this._needSync = false;
- this._createBufferOnWrite = this._engine._features.trackUbosInFrame;
- }
- _createNewBuffer() {
- if (this._bufferIndex + 1 < this._buffers.length) {
- this._bufferIndex++;
- this._buffer = this._buffers[this._bufferIndex][0];
- this._createBufferOnWrite = false;
- this._needSync = true;
- }
- else {
- this._rebuild();
- }
- }
- _checkNewFrame() {
- if (this._engine._features.trackUbosInFrame && this._currentFrameId !== this._engine.frameId) {
- this._currentFrameId = this._engine.frameId;
- this._createBufferOnWrite = false;
- if (this._buffers && this._buffers.length > 0) {
- this._needSync = this._bufferIndex !== 0;
- this._bufferIndex = 0;
- this._buffer = this._buffers[this._bufferIndex][0];
- }
- else {
- this._bufferIndex = -1;
- }
- }
- }
- /**
- * Updates the value of an uniform. The `update` method must be called afterwards to make it effective in the GPU.
- * @param uniformName Define the name of the uniform, as used in the uniform block in the shader.
- * @param data Define the flattened data
- * @param size Define the size of the data.
- */
- updateUniform(uniformName, data, size) {
- this._checkNewFrame();
- let location = this._uniformLocations[uniformName];
- if (location === undefined) {
- if (this._buffer) {
- // Cannot add an uniform if the buffer is already created
- Logger.Error("Cannot add an uniform after UBO has been created. uniformName=" + uniformName);
- return;
- }
- this.addUniform(uniformName, size);
- location = this._uniformLocations[uniformName];
- }
- if (!this._buffer) {
- this.create();
- }
- if (!this._dynamic) {
- // Cache for static uniform buffers
- let changed = false;
- for (let i = 0; i < size; i++) {
- // We are checking the matrix cache before calling updateUniform so we do not need to check it here
- // Hence the test for size === 16 to simply commit the matrix values
- if ((size === 16 && !this._engine._features.uniformBufferHardCheckMatrix) || this._bufferData[location + i] !== Math.fround(data[i])) {
- changed = true;
- if (this._createBufferOnWrite) {
- this._createNewBuffer();
- }
- this._bufferData[location + i] = data[i];
- }
- }
- this._needSync = this._needSync || changed;
- }
- else {
- // No cache for dynamic
- for (let i = 0; i < size; i++) {
- this._bufferData[location + i] = data[i];
- }
- }
- }
- /**
- * Updates the value of an uniform. The `update` method must be called afterwards to make it effective in the GPU.
- * @param uniformName Define the name of the uniform, as used in the uniform block in the shader.
- * @param data Define the flattened data
- * @param size Define the size of the data.
- */
- updateUniformArray(uniformName, data, size) {
- this._checkNewFrame();
- const location = this._uniformLocations[uniformName];
- if (location === undefined) {
- Logger.Error("Cannot add an uniform Array dynamically. Please, add it using addUniform and make sure that uniform buffers are supported by the current engine.");
- return;
- }
- if (!this._buffer) {
- this.create();
- }
- const arraySizes = this._uniformArraySizes[uniformName];
- if (!this._dynamic) {
- // Cache for static uniform buffers
- let changed = false;
- let countToFour = 0;
- let baseStride = 0;
- for (let i = 0; i < size; i++) {
- if (this._bufferData[location + baseStride * 4 + countToFour] !== Tools.FloatRound(data[i])) {
- changed = true;
- if (this._createBufferOnWrite) {
- this._createNewBuffer();
- }
- this._bufferData[location + baseStride * 4 + countToFour] = data[i];
- }
- countToFour++;
- if (countToFour === arraySizes.strideSize) {
- for (; countToFour < 4; countToFour++) {
- this._bufferData[location + baseStride * 4 + countToFour] = 0;
- }
- countToFour = 0;
- baseStride++;
- }
- }
- this._needSync = this._needSync || changed;
- }
- else {
- // No cache for dynamic
- for (let i = 0; i < size; i++) {
- this._bufferData[location + i] = data[i];
- }
- }
- }
- _cacheMatrix(name, matrix) {
- this._checkNewFrame();
- const cache = this._valueCache[name];
- const flag = matrix.updateFlag;
- if (cache !== undefined && cache === flag) {
- return false;
- }
- this._valueCache[name] = flag;
- return true;
- }
- // Update methods
- _updateMatrix3x3ForUniform(name, matrix) {
- // To match std140, matrix must be realigned
- for (let i = 0; i < 3; i++) {
- UniformBuffer._TempBuffer[i * 4] = matrix[i * 3];
- UniformBuffer._TempBuffer[i * 4 + 1] = matrix[i * 3 + 1];
- UniformBuffer._TempBuffer[i * 4 + 2] = matrix[i * 3 + 2];
- UniformBuffer._TempBuffer[i * 4 + 3] = 0.0;
- }
- this.updateUniform(name, UniformBuffer._TempBuffer, 12);
- }
- _updateMatrix3x3ForEffect(name, matrix) {
- this._currentEffect.setMatrix3x3(name, matrix);
- }
- _updateMatrix2x2ForEffect(name, matrix) {
- this._currentEffect.setMatrix2x2(name, matrix);
- }
- _updateMatrix2x2ForUniform(name, matrix) {
- // To match std140, matrix must be realigned
- for (let i = 0; i < 2; i++) {
- UniformBuffer._TempBuffer[i * 4] = matrix[i * 2];
- UniformBuffer._TempBuffer[i * 4 + 1] = matrix[i * 2 + 1];
- UniformBuffer._TempBuffer[i * 4 + 2] = 0.0;
- UniformBuffer._TempBuffer[i * 4 + 3] = 0.0;
- }
- this.updateUniform(name, UniformBuffer._TempBuffer, 8);
- }
- _updateFloatForEffect(name, x) {
- this._currentEffect.setFloat(name, x);
- }
- _updateFloatForUniform(name, x) {
- UniformBuffer._TempBuffer[0] = x;
- this.updateUniform(name, UniformBuffer._TempBuffer, 1);
- }
- _updateFloat2ForEffect(name, x, y, suffix = "") {
- this._currentEffect.setFloat2(name + suffix, x, y);
- }
- _updateFloat2ForUniform(name, x, y) {
- UniformBuffer._TempBuffer[0] = x;
- UniformBuffer._TempBuffer[1] = y;
- this.updateUniform(name, UniformBuffer._TempBuffer, 2);
- }
- _updateFloat3ForEffect(name, x, y, z, suffix = "") {
- this._currentEffect.setFloat3(name + suffix, x, y, z);
- }
- _updateFloat3ForUniform(name, x, y, z) {
- UniformBuffer._TempBuffer[0] = x;
- UniformBuffer._TempBuffer[1] = y;
- UniformBuffer._TempBuffer[2] = z;
- this.updateUniform(name, UniformBuffer._TempBuffer, 3);
- }
- _updateFloat4ForEffect(name, x, y, z, w, suffix = "") {
- this._currentEffect.setFloat4(name + suffix, x, y, z, w);
- }
- _updateFloat4ForUniform(name, x, y, z, w) {
- UniformBuffer._TempBuffer[0] = x;
- UniformBuffer._TempBuffer[1] = y;
- UniformBuffer._TempBuffer[2] = z;
- UniformBuffer._TempBuffer[3] = w;
- this.updateUniform(name, UniformBuffer._TempBuffer, 4);
- }
- _updateFloatArrayForEffect(name, array) {
- this._currentEffect.setFloatArray(name, array);
- }
- _updateFloatArrayForUniform(name, array) {
- this.updateUniformArray(name, array, array.length);
- }
- _updateArrayForEffect(name, array) {
- this._currentEffect.setArray(name, array);
- }
- _updateArrayForUniform(name, array) {
- this.updateUniformArray(name, array, array.length);
- }
- _updateIntArrayForEffect(name, array) {
- this._currentEffect.setIntArray(name, array);
- }
- _updateIntArrayForUniform(name, array) {
- UniformBuffer._TempBufferInt32View.set(array);
- this.updateUniformArray(name, UniformBuffer._TempBuffer, array.length);
- }
- _updateUIntArrayForEffect(name, array) {
- this._currentEffect.setUIntArray(name, array);
- }
- _updateUIntArrayForUniform(name, array) {
- UniformBuffer._TempBufferUInt32View.set(array);
- this.updateUniformArray(name, UniformBuffer._TempBuffer, array.length);
- }
- _updateMatrixForEffect(name, mat) {
- this._currentEffect.setMatrix(name, mat);
- }
- _updateMatrixForUniform(name, mat) {
- if (this._cacheMatrix(name, mat)) {
- this.updateUniform(name, mat.asArray(), 16);
- }
- }
- _updateMatricesForEffect(name, mat) {
- this._currentEffect.setMatrices(name, mat);
- }
- _updateMatricesForUniform(name, mat) {
- this.updateUniform(name, mat, mat.length);
- }
- _updateVector3ForEffect(name, vector) {
- this._currentEffect.setVector3(name, vector);
- }
- _updateVector3ForUniform(name, vector) {
- UniformBuffer._TempBuffer[0] = vector.x;
- UniformBuffer._TempBuffer[1] = vector.y;
- UniformBuffer._TempBuffer[2] = vector.z;
- this.updateUniform(name, UniformBuffer._TempBuffer, 3);
- }
- _updateVector4ForEffect(name, vector) {
- this._currentEffect.setVector4(name, vector);
- }
- _updateVector4ForUniform(name, vector) {
- UniformBuffer._TempBuffer[0] = vector.x;
- UniformBuffer._TempBuffer[1] = vector.y;
- UniformBuffer._TempBuffer[2] = vector.z;
- UniformBuffer._TempBuffer[3] = vector.w;
- this.updateUniform(name, UniformBuffer._TempBuffer, 4);
- }
- _updateColor3ForEffect(name, color, suffix = "") {
- this._currentEffect.setColor3(name + suffix, color);
- }
- _updateColor3ForUniform(name, color) {
- UniformBuffer._TempBuffer[0] = color.r;
- UniformBuffer._TempBuffer[1] = color.g;
- UniformBuffer._TempBuffer[2] = color.b;
- this.updateUniform(name, UniformBuffer._TempBuffer, 3);
- }
- _updateColor4ForEffect(name, color, alpha, suffix = "") {
- this._currentEffect.setColor4(name + suffix, color, alpha);
- }
- _updateDirectColor4ForEffect(name, color, suffix = "") {
- this._currentEffect.setDirectColor4(name + suffix, color);
- }
- _updateColor4ForUniform(name, color, alpha) {
- UniformBuffer._TempBuffer[0] = color.r;
- UniformBuffer._TempBuffer[1] = color.g;
- UniformBuffer._TempBuffer[2] = color.b;
- UniformBuffer._TempBuffer[3] = alpha;
- this.updateUniform(name, UniformBuffer._TempBuffer, 4);
- }
- _updateDirectColor4ForUniform(name, color) {
- UniformBuffer._TempBuffer[0] = color.r;
- UniformBuffer._TempBuffer[1] = color.g;
- UniformBuffer._TempBuffer[2] = color.b;
- UniformBuffer._TempBuffer[3] = color.a;
- this.updateUniform(name, UniformBuffer._TempBuffer, 4);
- }
- _updateIntForEffect(name, x, suffix = "") {
- this._currentEffect.setInt(name + suffix, x);
- }
- _updateIntForUniform(name, x) {
- UniformBuffer._TempBufferInt32View[0] = x;
- this.updateUniform(name, UniformBuffer._TempBuffer, 1);
- }
- _updateInt2ForEffect(name, x, y, suffix = "") {
- this._currentEffect.setInt2(name + suffix, x, y);
- }
- _updateInt2ForUniform(name, x, y) {
- UniformBuffer._TempBufferInt32View[0] = x;
- UniformBuffer._TempBufferInt32View[1] = y;
- this.updateUniform(name, UniformBuffer._TempBuffer, 2);
- }
- _updateInt3ForEffect(name, x, y, z, suffix = "") {
- this._currentEffect.setInt3(name + suffix, x, y, z);
- }
- _updateInt3ForUniform(name, x, y, z) {
- UniformBuffer._TempBufferInt32View[0] = x;
- UniformBuffer._TempBufferInt32View[1] = y;
- UniformBuffer._TempBufferInt32View[2] = z;
- this.updateUniform(name, UniformBuffer._TempBuffer, 3);
- }
- _updateInt4ForEffect(name, x, y, z, w, suffix = "") {
- this._currentEffect.setInt4(name + suffix, x, y, z, w);
- }
- _updateInt4ForUniform(name, x, y, z, w) {
- UniformBuffer._TempBufferInt32View[0] = x;
- UniformBuffer._TempBufferInt32View[1] = y;
- UniformBuffer._TempBufferInt32View[2] = z;
- UniformBuffer._TempBufferInt32View[3] = w;
- this.updateUniform(name, UniformBuffer._TempBuffer, 4);
- }
- _updateUIntForEffect(name, x, suffix = "") {
- this._currentEffect.setUInt(name + suffix, x);
- }
- _updateUIntForUniform(name, x) {
- UniformBuffer._TempBufferUInt32View[0] = x;
- this.updateUniform(name, UniformBuffer._TempBuffer, 1);
- }
- _updateUInt2ForEffect(name, x, y, suffix = "") {
- this._currentEffect.setUInt2(name + suffix, x, y);
- }
- _updateUInt2ForUniform(name, x, y) {
- UniformBuffer._TempBufferUInt32View[0] = x;
- UniformBuffer._TempBufferUInt32View[1] = y;
- this.updateUniform(name, UniformBuffer._TempBuffer, 2);
- }
- _updateUInt3ForEffect(name, x, y, z, suffix = "") {
- this._currentEffect.setUInt3(name + suffix, x, y, z);
- }
- _updateUInt3ForUniform(name, x, y, z) {
- UniformBuffer._TempBufferUInt32View[0] = x;
- UniformBuffer._TempBufferUInt32View[1] = y;
- UniformBuffer._TempBufferUInt32View[2] = z;
- this.updateUniform(name, UniformBuffer._TempBuffer, 3);
- }
- _updateUInt4ForEffect(name, x, y, z, w, suffix = "") {
- this._currentEffect.setUInt4(name + suffix, x, y, z, w);
- }
- _updateUInt4ForUniform(name, x, y, z, w) {
- UniformBuffer._TempBufferUInt32View[0] = x;
- UniformBuffer._TempBufferUInt32View[1] = y;
- UniformBuffer._TempBufferUInt32View[2] = z;
- UniformBuffer._TempBufferUInt32View[3] = w;
- this.updateUniform(name, UniformBuffer._TempBuffer, 4);
- }
- /**
- * Sets a sampler uniform on the effect.
- * @param name Define the name of the sampler.
- * @param texture Define the texture to set in the sampler
- */
- setTexture(name, texture) {
- this._currentEffect.setTexture(name, texture);
- }
- /**
- * Sets a sampler uniform on the effect.
- * @param name Define the name of the sampler.
- * @param texture Define the (internal) texture to set in the sampler
- */
- bindTexture(name, texture) {
- this._currentEffect._bindTexture(name, texture);
- }
- /**
- * Directly updates the value of the uniform in the cache AND on the GPU.
- * @param uniformName Define the name of the uniform, as used in the uniform block in the shader.
- * @param data Define the flattened data
- */
- updateUniformDirectly(uniformName, data) {
- this.updateUniform(uniformName, data, data.length);
- this.update();
- }
- /**
- * Associates an effect to this uniform buffer
- * @param effect Define the effect to associate the buffer to
- * @param name Name of the uniform block in the shader.
- */
- bindToEffect(effect, name) {
- this._currentEffect = effect;
- this._currentEffectName = name;
- }
- /**
- * Binds the current (GPU) buffer to the effect
- */
- bindUniformBuffer() {
- if (!this._noUBO && this._buffer && this._currentEffect) {
- this._currentEffect.bindUniformBuffer(this._buffer, this._currentEffectName);
- }
- }
- /**
- * Dissociates the current effect from this uniform buffer
- */
- unbindEffect() {
- this._currentEffect = undefined;
- this._currentEffectName = undefined;
- }
- /**
- * Sets the current state of the class (_bufferIndex, _buffer) to point to the data buffer passed in parameter if this buffer is one of the buffers handled by the class (meaning if it can be found in the _buffers array)
- * This method is meant to be able to update a buffer at any time: just call setDataBuffer to set the class in the right state, call some updateXXX methods and then call udpate() => that will update the GPU buffer on the graphic card
- * @param dataBuffer buffer to look for
- * @returns true if the buffer has been found and the class internal state points to it, else false
- */
- setDataBuffer(dataBuffer) {
- if (!this._buffers) {
- return this._buffer === dataBuffer;
- }
- for (let b = 0; b < this._buffers.length; ++b) {
- const buffer = this._buffers[b];
- if (buffer[0] === dataBuffer) {
- this._bufferIndex = b;
- this._buffer = dataBuffer;
- this._createBufferOnWrite = false;
- this._currentEffect = undefined;
- return true;
- }
- }
- return false;
- }
- /**
- * Disposes the uniform buffer.
- */
- dispose() {
- if (this._noUBO) {
- return;
- }
- const uniformBuffers = this._engine._uniformBuffers;
- const index = uniformBuffers.indexOf(this);
- if (index !== -1) {
- uniformBuffers[index] = uniformBuffers[uniformBuffers.length - 1];
- uniformBuffers.pop();
- }
- if (this._engine._features.trackUbosInFrame && this._buffers) {
- for (let i = 0; i < this._buffers.length; ++i) {
- const buffer = this._buffers[i][0];
- this._engine._releaseBuffer(buffer);
- }
- }
- else if (this._buffer && this._engine._releaseBuffer(this._buffer)) {
- this._buffer = null;
- }
- }
- }
- /** @internal */
- UniformBuffer._UpdatedUbosInFrame = {};
- // Pool for avoiding memory leaks
- UniformBuffer._MAX_UNIFORM_SIZE = 256;
- UniformBuffer._TempBuffer = new Float32Array(UniformBuffer._MAX_UNIFORM_SIZE);
- UniformBuffer._TempBufferInt32View = new Int32Array(UniformBuffer._TempBuffer.buffer);
- UniformBuffer._TempBufferUInt32View = new Uint32Array(UniformBuffer._TempBuffer.buffer);
- //# sourceMappingURL=uniformBuffer.js.map
|