12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039 |
- import { Engine } from "../Engines/engine.js";
- import { InternalTexture, InternalTextureSource } from "../Materials/Textures/internalTexture.js";
- import { Texture } from "../Materials/Textures/texture.js";
- import { DataBuffer } from "../Buffers/dataBuffer.js";
- import { Tools } from "../Misc/tools.js";
- import { Observable } from "../Misc/observable.js";
- import { CreateImageDataArrayBufferViews, GetEnvInfo, UploadEnvSpherical } from "../Misc/environmentTextureTools.js";
- import { Logger } from "../Misc/logger.js";
- import { ThinEngine } from "./thinEngine.js";
- import { EngineStore } from "./engineStore.js";
- import { ShaderCodeInliner } from "./Processors/shaderCodeInliner.js";
- import { WebGL2ShaderProcessor } from "../Engines/WebGL/webGL2ShaderProcessors.js";
- import { NativeDataStream } from "./Native/nativeDataStream.js";
- import { NativePipelineContext } from "./Native/nativePipelineContext.js";
- import { NativeRenderTargetWrapper } from "./Native/nativeRenderTargetWrapper.js";
- import { NativeHardwareTexture } from "./Native/nativeHardwareTexture.js";
- import { getNativeAlphaMode, getNativeAttribType, getNativeSamplingMode, getNativeTextureFormat, getNativeStencilDepthFail, getNativeStencilDepthPass, getNativeStencilFunc, getNativeStencilOpFail, getNativeAddressMode, } from "./Native/nativeHelpers.js";
- import { AbstractEngine } from "./abstractEngine.js";
- const onNativeObjectInitialized = new Observable();
- if (typeof self !== "undefined" && !Object.prototype.hasOwnProperty.call(self, "_native")) {
- let __native;
- Object.defineProperty(self, "_native", {
- get: () => __native,
- set: (value) => {
- __native = value;
- if (__native) {
- onNativeObjectInitialized.notifyObservers(__native);
- }
- },
- });
- }
- /**
- * Returns _native only after it has been defined by BabylonNative.
- * @internal
- */
- export function AcquireNativeObjectAsync() {
- return new Promise((resolve) => {
- if (typeof _native === "undefined") {
- onNativeObjectInitialized.addOnce((nativeObject) => resolve(nativeObject));
- }
- else {
- resolve(_native);
- }
- });
- }
- /**
- * Registers a constructor on the _native object. See NativeXRFrame for an example.
- * @internal
- */
- export async function RegisterNativeTypeAsync(typeName, constructor) {
- (await AcquireNativeObjectAsync())[typeName] = constructor;
- }
- /**
- * Container for accessors for natively-stored mesh data buffers.
- */
- class NativeDataBuffer extends DataBuffer {
- }
- /** @internal */
- class CommandBufferEncoder {
- constructor(_engine) {
- this._engine = _engine;
- this._pending = new Array();
- this._isCommandBufferScopeActive = false;
- this._commandStream = NativeEngine._createNativeDataStream();
- this._engine.setCommandDataStream(this._commandStream);
- }
- beginCommandScope() {
- if (this._isCommandBufferScopeActive) {
- throw new Error("Command scope already active.");
- }
- this._isCommandBufferScopeActive = true;
- }
- endCommandScope() {
- if (!this._isCommandBufferScopeActive) {
- throw new Error("Command scope is not active.");
- }
- this._isCommandBufferScopeActive = false;
- this._submit();
- }
- startEncodingCommand(command) {
- this._commandStream.writeNativeData(command);
- }
- encodeCommandArgAsUInt32(commandArg) {
- this._commandStream.writeUint32(commandArg);
- }
- encodeCommandArgAsUInt32s(commandArg) {
- this._commandStream.writeUint32Array(commandArg);
- }
- encodeCommandArgAsInt32(commandArg) {
- this._commandStream.writeInt32(commandArg);
- }
- encodeCommandArgAsInt32s(commandArg) {
- this._commandStream.writeInt32Array(commandArg);
- }
- encodeCommandArgAsFloat32(commandArg) {
- this._commandStream.writeFloat32(commandArg);
- }
- encodeCommandArgAsFloat32s(commandArg) {
- this._commandStream.writeFloat32Array(commandArg);
- }
- encodeCommandArgAsNativeData(commandArg) {
- this._commandStream.writeNativeData(commandArg);
- this._pending.push(commandArg);
- }
- finishEncodingCommand() {
- if (!this._isCommandBufferScopeActive) {
- this._submit();
- }
- }
- _submit() {
- this._engine.submitCommands();
- this._pending.length = 0;
- }
- }
- /** @internal */
- export class NativeEngine extends Engine {
- setHardwareScalingLevel(level) {
- super.setHardwareScalingLevel(level);
- this._engine.setHardwareScalingLevel(level);
- }
- constructor(options = {}) {
- super(null, false, undefined, options.adaptToDeviceRatio);
- this._engine = new _native.Engine();
- this._camera = _native.Camera ? new _native.Camera() : null;
- this._commandBufferEncoder = new CommandBufferEncoder(this._engine);
- this._boundBuffersVertexArray = null;
- this._currentDepthTest = _native.Engine.DEPTH_TEST_LEQUAL;
- this._stencilTest = false;
- this._stencilMask = 255;
- this._stencilFunc = 519;
- this._stencilFuncRef = 0;
- this._stencilFuncMask = 255;
- this._stencilOpStencilFail = 7680;
- this._stencilOpDepthFail = 7680;
- this._stencilOpStencilDepthPass = 7681;
- this._zOffset = 0;
- this._zOffsetUnits = 0;
- this._depthWrite = true;
- if (_native.Engine.PROTOCOL_VERSION !== NativeEngine.PROTOCOL_VERSION) {
- throw new Error(`Protocol version mismatch: ${_native.Engine.PROTOCOL_VERSION} (Native) !== ${NativeEngine.PROTOCOL_VERSION} (JS)`);
- }
- if (this._engine.setDeviceLostCallback) {
- this._engine.setDeviceLostCallback(() => {
- this.onContextLostObservable.notifyObservers(this);
- this._contextWasLost = true;
- this._restoreEngineAfterContextLost();
- });
- }
- this._webGLVersion = 2;
- this.disableUniformBuffers = true;
- this._shaderPlatformName = "NATIVE";
- // TODO: Initialize this more correctly based on the hardware capabilities.
- // Init caps
- this._caps = {
- maxTexturesImageUnits: 16,
- maxVertexTextureImageUnits: 16,
- maxCombinedTexturesImageUnits: 32,
- maxTextureSize: _native.Engine.CAPS_LIMITS_MAX_TEXTURE_SIZE,
- maxCubemapTextureSize: 512,
- maxRenderTextureSize: 512,
- maxVertexAttribs: 16,
- maxVaryingVectors: 16,
- maxFragmentUniformVectors: 16,
- maxVertexUniformVectors: 16,
- standardDerivatives: true,
- astc: null,
- pvrtc: null,
- etc1: null,
- etc2: null,
- bptc: null,
- maxAnisotropy: 16,
- uintIndices: true,
- fragmentDepthSupported: false,
- highPrecisionShaderSupported: true,
- colorBufferFloat: false,
- supportFloatTexturesResolve: false,
- rg11b10ufColorRenderable: false,
- textureFloat: true,
- textureFloatLinearFiltering: false,
- textureFloatRender: true,
- textureHalfFloat: true,
- textureHalfFloatLinearFiltering: false,
- textureHalfFloatRender: true,
- textureLOD: true,
- texelFetch: false,
- drawBuffersExtension: false,
- depthTextureExtension: false,
- vertexArrayObject: true,
- instancedArrays: true,
- supportOcclusionQuery: false,
- canUseTimestampForTimerQuery: false,
- blendMinMax: false,
- maxMSAASamples: 16,
- canUseGLInstanceID: true,
- canUseGLVertexID: true,
- supportComputeShaders: false,
- supportSRGBBuffers: true,
- supportTransformFeedbacks: false,
- textureMaxLevel: false,
- texture2DArrayMaxLayerCount: _native.Engine.CAPS_LIMITS_MAX_TEXTURE_LAYERS,
- disableMorphTargetTexture: false,
- parallelShaderCompile: { COMPLETION_STATUS_KHR: 0 },
- };
- this._features = {
- forceBitmapOverHTMLImageElement: true,
- supportRenderAndCopyToLodForFloatTextures: false,
- supportDepthStencilTexture: false,
- supportShadowSamplers: false,
- uniformBufferHardCheckMatrix: false,
- allowTexturePrefiltering: false,
- trackUbosInFrame: false,
- checkUbosContentBeforeUpload: false,
- supportCSM: false,
- basisNeedsPOT: false,
- support3DTextures: false,
- needTypeSuffixInShaderConstants: false,
- supportMSAA: true,
- supportSSAO2: false,
- supportExtendedTextureFormats: false,
- supportSwitchCaseInShader: false,
- supportSyncTextureRead: false,
- needsInvertingBitmap: true,
- useUBOBindingCache: true,
- needShaderCodeInlining: true,
- needToAlwaysBindUniformBuffers: false,
- supportRenderPasses: true,
- supportSpriteInstancing: false,
- forceVertexBufferStrideAndOffsetMultiple4Bytes: false,
- _collectUbosUpdatedInFrame: false,
- };
- Tools.Log("Babylon Native (v" + Engine.Version + ") launched");
- Tools.LoadScript = function (scriptUrl, onSuccess, onError, scriptId) {
- Tools.LoadFile(scriptUrl, (data) => {
- Function(data).apply(null);
- if (onSuccess) {
- onSuccess();
- }
- }, undefined, undefined, false, (request, exception) => {
- if (onError) {
- onError("LoadScript Error", exception);
- }
- });
- };
- // Wrappers
- if (typeof URL === "undefined") {
- window.URL = {
- createObjectURL: function () { },
- revokeObjectURL: function () { },
- };
- }
- if (typeof Blob === "undefined") {
- window.Blob = function (v) {
- return v;
- };
- }
- // polyfill for Chakra
- if (!Array.prototype.flat) {
- Object.defineProperty(Array.prototype, "flat", {
- configurable: true,
- value: function flat() {
- const depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]);
- return depth
- ? Array.prototype.reduce.call(this, function (acc, cur) {
- if (Array.isArray(cur)) {
- acc.push.apply(acc, flat.call(cur, depth - 1));
- }
- else {
- acc.push(cur);
- }
- return acc;
- }, [])
- : Array.prototype.slice.call(this);
- },
- writable: true,
- });
- }
- // Currently we do not fully configure the ThinEngine on construction of NativeEngine.
- // Setup resolution scaling based on display settings.
- const devicePixelRatio = window ? window.devicePixelRatio || 1.0 : 1.0;
- this._hardwareScalingLevel = options.adaptToDeviceRatio ? 1.0 / devicePixelRatio : 1.0;
- this._engine.setHardwareScalingLevel(this._hardwareScalingLevel);
- this._lastDevicePixelRatio = devicePixelRatio;
- this.resize();
- const currentDepthFunction = this.getDepthFunction();
- if (currentDepthFunction) {
- this.setDepthFunction(currentDepthFunction);
- }
- // Shader processor
- this._shaderProcessor = new WebGL2ShaderProcessor();
- this.onNewSceneAddedObservable.add((scene) => {
- const originalRender = scene.render;
- scene.render = (...args) => {
- this._commandBufferEncoder.beginCommandScope();
- originalRender.apply(scene, args);
- this._commandBufferEncoder.endCommandScope();
- };
- });
- }
- dispose() {
- super.dispose();
- if (this._boundBuffersVertexArray) {
- this._deleteVertexArray(this._boundBuffersVertexArray);
- }
- this._engine.dispose();
- }
- /** @internal */
- static _createNativeDataStream() {
- return new NativeDataStream();
- }
- /**
- * Can be used to override the current requestAnimationFrame requester.
- * @internal
- */
- _queueNewFrame(bindedRenderFunction, requester) {
- // Use the provided requestAnimationFrame, unless the requester is the window. In that case, we will default to the Babylon Native version of requestAnimationFrame.
- if (requester.requestAnimationFrame && requester !== window) {
- requester.requestAnimationFrame(bindedRenderFunction);
- }
- else {
- this._engine.requestAnimationFrame(bindedRenderFunction);
- }
- return 0;
- }
- _restoreEngineAfterContextLost() {
- this._clearEmptyResources();
- const depthTest = this._depthCullingState.depthTest; // backup those values because the call to initEngine / wipeCaches will reset them
- const depthFunc = this._depthCullingState.depthFunc;
- const depthMask = this._depthCullingState.depthMask;
- const stencilTest = this._stencilState.stencilTest;
- this._rebuildGraphicsResources();
- this._depthCullingState.depthTest = depthTest;
- this._depthCullingState.depthFunc = depthFunc;
- this._depthCullingState.depthMask = depthMask;
- this._stencilState.stencilTest = stencilTest;
- this._flagContextRestored();
- }
- /**
- * Override default engine behavior.
- * @param framebuffer
- */
- _bindUnboundFramebuffer(framebuffer) {
- if (this._currentFramebuffer !== framebuffer) {
- if (this._currentFramebuffer) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_UNBINDFRAMEBUFFER);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(this._currentFramebuffer);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- if (framebuffer) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_BINDFRAMEBUFFER);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(framebuffer);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- this._currentFramebuffer = framebuffer;
- }
- }
- /**
- * Gets host document
- * @returns the host document object
- */
- getHostDocument() {
- return null;
- }
- clear(color, backBuffer, depth, stencil = false) {
- if (this.useReverseDepthBuffer) {
- throw new Error("reverse depth buffer is not currently implemented");
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_CLEAR);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(backBuffer && color ? 1 : 0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.r : 0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.g : 0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.b : 0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.a : 1);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(depth ? 1 : 0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(1);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(stencil ? 1 : 0);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(0);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- createIndexBuffer(indices, updateable, _label) {
- const data = this._normalizeIndexData(indices);
- const buffer = new NativeDataBuffer();
- buffer.references = 1;
- buffer.is32Bits = data.BYTES_PER_ELEMENT === 4;
- if (data.byteLength) {
- buffer.nativeIndexBuffer = this._engine.createIndexBuffer(data.buffer, data.byteOffset, data.byteLength, buffer.is32Bits, updateable ?? false);
- }
- return buffer;
- }
- createVertexBuffer(vertices, updateable, _label) {
- const data = ArrayBuffer.isView(vertices) ? vertices : new Float32Array(vertices);
- const buffer = new NativeDataBuffer();
- buffer.references = 1;
- if (data.byteLength) {
- buffer.nativeVertexBuffer = this._engine.createVertexBuffer(data.buffer, data.byteOffset, data.byteLength, updateable ?? false);
- }
- return buffer;
- }
- _recordVertexArrayObject(vertexArray, vertexBuffers, indexBuffer, effect, overrideVertexBuffers) {
- if (indexBuffer) {
- this._engine.recordIndexBuffer(vertexArray, indexBuffer.nativeIndexBuffer);
- }
- const attributes = effect.getAttributesNames();
- for (let index = 0; index < attributes.length; index++) {
- const location = effect.getAttributeLocation(index);
- if (location >= 0) {
- const kind = attributes[index];
- let vertexBuffer = null;
- if (overrideVertexBuffers) {
- vertexBuffer = overrideVertexBuffers[kind];
- }
- if (!vertexBuffer) {
- vertexBuffer = vertexBuffers[kind];
- }
- if (vertexBuffer) {
- const buffer = vertexBuffer.getBuffer();
- if (buffer && buffer.nativeVertexBuffer) {
- this._engine.recordVertexBuffer(vertexArray, buffer.nativeVertexBuffer, location, vertexBuffer.byteOffset, vertexBuffer.byteStride, vertexBuffer.getSize(), getNativeAttribType(vertexBuffer.type), vertexBuffer.normalized, vertexBuffer.getInstanceDivisor());
- }
- }
- }
- }
- }
- bindBuffers(vertexBuffers, indexBuffer, effect) {
- if (this._boundBuffersVertexArray) {
- this._deleteVertexArray(this._boundBuffersVertexArray);
- }
- this._boundBuffersVertexArray = this._engine.createVertexArray();
- this._recordVertexArrayObject(this._boundBuffersVertexArray, vertexBuffers, indexBuffer, effect);
- this.bindVertexArrayObject(this._boundBuffersVertexArray);
- }
- recordVertexArrayObject(vertexBuffers, indexBuffer, effect, overrideVertexBuffers) {
- const vertexArray = this._engine.createVertexArray();
- this._recordVertexArrayObject(vertexArray, vertexBuffers, indexBuffer, effect, overrideVertexBuffers);
- return vertexArray;
- }
- _deleteVertexArray(vertexArray) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DELETEVERTEXARRAY);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(vertexArray);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- bindVertexArrayObject(vertexArray) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_BINDVERTEXARRAY);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(vertexArray);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- releaseVertexArrayObject(vertexArray) {
- this._deleteVertexArray(vertexArray);
- }
- getAttributes(pipelineContext, attributesNames) {
- const nativePipelineContext = pipelineContext;
- return this._engine.getAttributes(nativePipelineContext.program, attributesNames);
- }
- /**
- * Draw a list of indexed primitives
- * @param fillMode defines the primitive to use
- * @param indexStart defines the starting index
- * @param indexCount defines the number of index to draw
- * @param instancesCount defines the number of instances to draw (if instantiation is enabled)
- */
- drawElementsType(fillMode, indexStart, indexCount, instancesCount) {
- // Apply states
- this._drawCalls.addCount(1, false);
- if (instancesCount && _native.Engine.COMMAND_DRAWINDEXEDINSTANCED) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DRAWINDEXEDINSTANCED);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(fillMode);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(indexStart);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(indexCount);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(instancesCount);
- }
- else {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DRAWINDEXED);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(fillMode);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(indexStart);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(indexCount);
- }
- this._commandBufferEncoder.finishEncodingCommand();
- // }
- }
- /**
- * Draw a list of unindexed primitives
- * @param fillMode defines the primitive to use
- * @param verticesStart defines the index of first vertex to draw
- * @param verticesCount defines the count of vertices to draw
- * @param instancesCount defines the number of instances to draw (if instantiation is enabled)
- */
- drawArraysType(fillMode, verticesStart, verticesCount, instancesCount) {
- // Apply states
- this._drawCalls.addCount(1, false);
- if (instancesCount && _native.Engine.COMMAND_DRAWINSTANCED) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DRAWINSTANCED);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(fillMode);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(verticesStart);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(verticesCount);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(instancesCount);
- }
- else {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DRAW);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(fillMode);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(verticesStart);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(verticesCount);
- }
- this._commandBufferEncoder.finishEncodingCommand();
- // }
- }
- createPipelineContext() {
- const isAsync = !!(this._caps.parallelShaderCompile && this._engine.createProgramAsync);
- return new NativePipelineContext(this, isAsync);
- }
- createMaterialContext() {
- return undefined;
- }
- createDrawContext() {
- return undefined;
- }
- /**
- * @internal
- */
- _preparePipelineContext(pipelineContext, vertexSourceCode, fragmentSourceCode, createAsRaw, _rawVertexSourceCode, _rawFragmentSourceCode, _rebuildRebind, defines) {
- if (createAsRaw) {
- this.createRawShaderProgram();
- }
- else {
- this.createShaderProgram(pipelineContext, vertexSourceCode, fragmentSourceCode, defines);
- }
- }
- /**
- * @internal
- */
- _executeWhenRenderingStateIsCompiled(pipelineContext, action) {
- const nativePipelineContext = pipelineContext;
- if (nativePipelineContext.isAsync) {
- if (nativePipelineContext.onCompiled) {
- const oldHandler = nativePipelineContext.onCompiled;
- nativePipelineContext.onCompiled = () => {
- oldHandler();
- action();
- };
- }
- else {
- nativePipelineContext.onCompiled = action;
- }
- }
- else {
- action();
- }
- }
- createRawShaderProgram() {
- throw new Error("Not Supported");
- }
- createShaderProgram(pipelineContext, vertexCode, fragmentCode, defines) {
- const nativePipelineContext = pipelineContext;
- this.onBeforeShaderCompilationObservable.notifyObservers(this);
- const vertexInliner = new ShaderCodeInliner(vertexCode);
- vertexInliner.processCode();
- vertexCode = vertexInliner.code;
- const fragmentInliner = new ShaderCodeInliner(fragmentCode);
- fragmentInliner.processCode();
- fragmentCode = fragmentInliner.code;
- vertexCode = ThinEngine._ConcatenateShader(vertexCode, defines);
- fragmentCode = ThinEngine._ConcatenateShader(fragmentCode, defines);
- const onSuccess = () => {
- nativePipelineContext.isCompiled = true;
- nativePipelineContext.onCompiled?.();
- this.onAfterShaderCompilationObservable.notifyObservers(this);
- };
- if (pipelineContext.isAsync) {
- nativePipelineContext.program = this._engine.createProgramAsync(vertexCode, fragmentCode, onSuccess, (error) => {
- nativePipelineContext.compilationError = error;
- });
- }
- else {
- try {
- nativePipelineContext.program = this._engine.createProgram(vertexCode, fragmentCode);
- onSuccess();
- }
- catch (e) {
- const message = e?.message;
- throw new Error("SHADER ERROR" + (typeof message === "string" ? "\n" + message : ""));
- }
- }
- return nativePipelineContext.program;
- }
- /**
- * Inline functions in shader code that are marked to be inlined
- * @param code code to inline
- * @returns inlined code
- */
- inlineShaderCode(code) {
- const sci = new ShaderCodeInliner(code);
- sci.debug = false;
- sci.processCode();
- return sci.code;
- }
- _setProgram(program) {
- if (this._currentProgram !== program) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETPROGRAM);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(program);
- this._commandBufferEncoder.finishEncodingCommand();
- this._currentProgram = program;
- }
- }
- _deletePipelineContext(pipelineContext) {
- const nativePipelineContext = pipelineContext;
- if (nativePipelineContext && nativePipelineContext.program) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DELETEPROGRAM);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(nativePipelineContext.program);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- }
- getUniforms(pipelineContext, uniformsNames) {
- const nativePipelineContext = pipelineContext;
- return this._engine.getUniforms(nativePipelineContext.program, uniformsNames);
- }
- bindUniformBlock(pipelineContext, blockName, index) {
- // TODO
- throw new Error("Not Implemented");
- }
- bindSamplers(effect) {
- const nativePipelineContext = effect.getPipelineContext();
- this._setProgram(nativePipelineContext.program);
- // TODO: share this with engine?
- const samplers = effect.getSamplers();
- for (let index = 0; index < samplers.length; index++) {
- const uniform = effect.getUniform(samplers[index]);
- if (uniform) {
- this._boundUniforms[index] = uniform;
- }
- }
- this._currentEffect = null;
- }
- getRenderWidth(useScreen = false) {
- if (!useScreen && this._currentRenderTarget) {
- return this._currentRenderTarget.width;
- }
- return this._engine.getRenderWidth();
- }
- getRenderHeight(useScreen = false) {
- if (!useScreen && this._currentRenderTarget) {
- return this._currentRenderTarget.height;
- }
- return this._engine.getRenderHeight();
- }
- setViewport(viewport, requiredWidth, requiredHeight) {
- this._cachedViewport = viewport;
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETVIEWPORT);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(viewport.x);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(viewport.y);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(viewport.width);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(viewport.height);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- enableScissor(x, y, width, height) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETSCISSOR);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(x);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(y);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(width);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(height);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- disableScissor() {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETSCISSOR);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(0);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- setState(culling, zOffset = 0, force, reverseSide = false, cullBackFaces, stencil, zOffsetUnits = 0) {
- this._zOffset = zOffset;
- this._zOffsetUnits = zOffsetUnits;
- if (this._zOffset !== 0) {
- Tools.Warn("zOffset is not supported in Native engine.");
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETSTATE);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(culling ? 1 : 0);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(zOffset);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(zOffsetUnits);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(this.cullBackFaces ?? cullBackFaces ?? true ? 1 : 0);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(reverseSide ? 1 : 0);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- /**
- * Gets the client rect of native canvas. Needed for InputManager.
- * @returns a client rectangle
- */
- getInputElementClientRect() {
- const rect = {
- bottom: this.getRenderHeight(),
- height: this.getRenderHeight(),
- left: 0,
- right: this.getRenderWidth(),
- top: 0,
- width: this.getRenderWidth(),
- x: 0,
- y: 0,
- toJSON: () => { },
- };
- return rect;
- }
- /**
- * Set the z offset Factor to apply to current rendering
- * @param value defines the offset to apply
- */
- setZOffset(value) {
- if (value !== this._zOffset) {
- this._zOffset = value;
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETZOFFSET);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(this.useReverseDepthBuffer ? -value : value);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- }
- /**
- * Gets the current value of the zOffset Factor
- * @returns the current zOffset Factor state
- */
- getZOffset() {
- return this._zOffset;
- }
- /**
- * Set the z offset Units to apply to current rendering
- * @param value defines the offset to apply
- */
- setZOffsetUnits(value) {
- if (value !== this._zOffsetUnits) {
- this._zOffsetUnits = value;
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETZOFFSETUNITS);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(this.useReverseDepthBuffer ? -value : value);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- }
- /**
- * Gets the current value of the zOffset Units
- * @returns the current zOffset Units state
- */
- getZOffsetUnits() {
- return this._zOffsetUnits;
- }
- /**
- * Enable or disable depth buffering
- * @param enable defines the state to set
- */
- setDepthBuffer(enable) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETDEPTHTEST);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(enable ? this._currentDepthTest : _native.Engine.DEPTH_TEST_ALWAYS);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- /**
- * Gets a boolean indicating if depth writing is enabled
- * @returns the current depth writing state
- */
- getDepthWrite() {
- return this._depthWrite;
- }
- getDepthFunction() {
- switch (this._currentDepthTest) {
- case _native.Engine.DEPTH_TEST_NEVER:
- return 512;
- case _native.Engine.DEPTH_TEST_ALWAYS:
- return 519;
- case _native.Engine.DEPTH_TEST_GREATER:
- return 516;
- case _native.Engine.DEPTH_TEST_GEQUAL:
- return 518;
- case _native.Engine.DEPTH_TEST_NOTEQUAL:
- return 517;
- case _native.Engine.DEPTH_TEST_EQUAL:
- return 514;
- case _native.Engine.DEPTH_TEST_LESS:
- return 513;
- case _native.Engine.DEPTH_TEST_LEQUAL:
- return 515;
- }
- return null;
- }
- setDepthFunction(depthFunc) {
- let nativeDepthFunc = 0;
- switch (depthFunc) {
- case 512:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_NEVER;
- break;
- case 519:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_ALWAYS;
- break;
- case 516:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_GREATER;
- break;
- case 518:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_GEQUAL;
- break;
- case 517:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_NOTEQUAL;
- break;
- case 514:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_EQUAL;
- break;
- case 513:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_LESS;
- break;
- case 515:
- nativeDepthFunc = _native.Engine.DEPTH_TEST_LEQUAL;
- break;
- }
- this._currentDepthTest = nativeDepthFunc;
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETDEPTHTEST);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(this._currentDepthTest);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- /**
- * Enable or disable depth writing
- * @param enable defines the state to set
- */
- setDepthWrite(enable) {
- this._depthWrite = enable;
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETDEPTHWRITE);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(Number(enable));
- this._commandBufferEncoder.finishEncodingCommand();
- }
- /**
- * Enable or disable color writing
- * @param enable defines the state to set
- */
- setColorWrite(enable) {
- this._colorWrite = enable;
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETCOLORWRITE);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(Number(enable));
- this._commandBufferEncoder.finishEncodingCommand();
- }
- /**
- * Gets a boolean indicating if color writing is enabled
- * @returns the current color writing state
- */
- getColorWrite() {
- return this._colorWrite;
- }
- applyStencil() {
- this._setStencil(this._stencilMask, getNativeStencilOpFail(this._stencilOpStencilFail), getNativeStencilDepthFail(this._stencilOpDepthFail), getNativeStencilDepthPass(this._stencilOpStencilDepthPass), getNativeStencilFunc(this._stencilFunc), this._stencilFuncRef);
- }
- _setStencil(mask, stencilOpFail, depthOpFail, depthOpPass, func, ref) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETSTENCIL);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(mask);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(stencilOpFail);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(depthOpFail);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(depthOpPass);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(func);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(ref);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- /**
- * Enable or disable the stencil buffer
- * @param enable defines if the stencil buffer must be enabled or disabled
- */
- setStencilBuffer(enable) {
- this._stencilTest = enable;
- if (enable) {
- this.applyStencil();
- }
- else {
- this._setStencil(255, _native.Engine.STENCIL_OP_FAIL_S_KEEP, _native.Engine.STENCIL_OP_FAIL_Z_KEEP, _native.Engine.STENCIL_OP_PASS_Z_KEEP, _native.Engine.STENCIL_TEST_ALWAYS, 0);
- }
- }
- /**
- * Gets a boolean indicating if stencil buffer is enabled
- * @returns the current stencil buffer state
- */
- getStencilBuffer() {
- return this._stencilTest;
- }
- /**
- * Gets the current stencil operation when stencil passes
- * @returns a number defining stencil operation to use when stencil passes
- */
- getStencilOperationPass() {
- return this._stencilOpStencilDepthPass;
- }
- /**
- * Sets the stencil operation to use when stencil passes
- * @param operation defines the stencil operation to use when stencil passes
- */
- setStencilOperationPass(operation) {
- this._stencilOpStencilDepthPass = operation;
- this.applyStencil();
- }
- /**
- * Sets the current stencil mask
- * @param mask defines the new stencil mask to use
- */
- setStencilMask(mask) {
- this._stencilMask = mask;
- this.applyStencil();
- }
- /**
- * Sets the current stencil function
- * @param stencilFunc defines the new stencil function to use
- */
- setStencilFunction(stencilFunc) {
- this._stencilFunc = stencilFunc;
- this.applyStencil();
- }
- /**
- * Sets the current stencil reference
- * @param reference defines the new stencil reference to use
- */
- setStencilFunctionReference(reference) {
- this._stencilFuncRef = reference;
- this.applyStencil();
- }
- /**
- * Sets the current stencil mask
- * @param mask defines the new stencil mask to use
- */
- setStencilFunctionMask(mask) {
- this._stencilFuncMask = mask;
- }
- /**
- * Sets the stencil operation to use when stencil fails
- * @param operation defines the stencil operation to use when stencil fails
- */
- setStencilOperationFail(operation) {
- this._stencilOpStencilFail = operation;
- this.applyStencil();
- }
- /**
- * Sets the stencil operation to use when depth fails
- * @param operation defines the stencil operation to use when depth fails
- */
- setStencilOperationDepthFail(operation) {
- this._stencilOpDepthFail = operation;
- this.applyStencil();
- }
- /**
- * Gets the current stencil mask
- * @returns a number defining the new stencil mask to use
- */
- getStencilMask() {
- return this._stencilMask;
- }
- /**
- * Gets the current stencil function
- * @returns a number defining the stencil function to use
- */
- getStencilFunction() {
- return this._stencilFunc;
- }
- /**
- * Gets the current stencil reference value
- * @returns a number defining the stencil reference value to use
- */
- getStencilFunctionReference() {
- return this._stencilFuncRef;
- }
- /**
- * Gets the current stencil mask
- * @returns a number defining the stencil mask to use
- */
- getStencilFunctionMask() {
- return this._stencilFuncMask;
- }
- /**
- * Gets the current stencil operation when stencil fails
- * @returns a number defining stencil operation to use when stencil fails
- */
- getStencilOperationFail() {
- return this._stencilOpStencilFail;
- }
- /**
- * Gets the current stencil operation when depth fails
- * @returns a number defining stencil operation to use when depth fails
- */
- getStencilOperationDepthFail() {
- return this._stencilOpDepthFail;
- }
- /**
- * Sets alpha constants used by some alpha blending modes
- * @param r defines the red component
- * @param g defines the green component
- * @param b defines the blue component
- * @param a defines the alpha component
- */
- setAlphaConstants(r, g, b, a) {
- throw new Error("Setting alpha blend constant color not yet implemented.");
- }
- /**
- * Sets the current alpha mode
- * @param mode defines the mode to use (one of the BABYLON.undefined)
- * @param noDepthWriteChange defines if depth writing state should remains unchanged (false by default)
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/advanced/transparent_rendering
- */
- setAlphaMode(mode, noDepthWriteChange = false) {
- if (this._alphaMode === mode) {
- return;
- }
- const nativeMode = getNativeAlphaMode(mode);
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETBLENDMODE);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(nativeMode);
- this._commandBufferEncoder.finishEncodingCommand();
- if (!noDepthWriteChange) {
- this.setDepthWrite(mode === 0);
- }
- this._alphaMode = mode;
- }
- /**
- * Gets the current alpha mode
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/advanced/transparent_rendering
- * @returns the current alpha mode
- */
- getAlphaMode() {
- return this._alphaMode;
- }
- setInt(uniform, int) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETINT);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsInt32(int);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setIntArray(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETINTARRAY);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsInt32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setIntArray2(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETINTARRAY2);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsInt32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setIntArray3(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETINTARRAY3);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsInt32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setIntArray4(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETINTARRAY4);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsInt32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloatArray(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOATARRAY);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloatArray2(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOATARRAY2);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloatArray3(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOATARRAY3);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloatArray4(uniform, array) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOATARRAY4);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(array);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setArray(uniform, array) {
- if (!uniform) {
- return false;
- }
- return this.setFloatArray(uniform, new Float32Array(array));
- }
- setArray2(uniform, array) {
- if (!uniform) {
- return false;
- }
- return this.setFloatArray2(uniform, new Float32Array(array));
- }
- setArray3(uniform, array) {
- if (!uniform) {
- return false;
- }
- return this.setFloatArray3(uniform, new Float32Array(array));
- }
- setArray4(uniform, array) {
- if (!uniform) {
- return false;
- }
- return this.setFloatArray4(uniform, new Float32Array(array));
- }
- setMatrices(uniform, matrices) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETMATRICES);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(matrices);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setMatrix3x3(uniform, matrix) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETMATRIX3X3);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(matrix);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setMatrix2x2(uniform, matrix) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETMATRIX2X2);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32s(matrix);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloat(uniform, value) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOAT);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(value);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloat2(uniform, x, y) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOAT2);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(x);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(y);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloat3(uniform, x, y, z) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOAT3);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(x);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(y);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(z);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setFloat4(uniform, x, y, z, w) {
- if (!uniform) {
- return false;
- }
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETFLOAT4);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(x);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(y);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(z);
- this._commandBufferEncoder.encodeCommandArgAsFloat32(w);
- this._commandBufferEncoder.finishEncodingCommand();
- return true;
- }
- setColor3(uniform, color3) {
- if (!uniform) {
- return false;
- }
- this.setFloat3(uniform, color3.r, color3.g, color3.b);
- return true;
- }
- setColor4(uniform, color3, alpha) {
- if (!uniform) {
- return false;
- }
- this.setFloat4(uniform, color3.r, color3.g, color3.b, alpha);
- return true;
- }
- wipeCaches(bruteForce) {
- if (this.preventCacheWipeBetweenFrames) {
- return;
- }
- this.resetTextureCache();
- this._currentEffect = null;
- if (bruteForce) {
- this._currentProgram = null;
- this._stencilStateComposer.reset();
- this._depthCullingState.reset();
- this._alphaState.reset();
- }
- this._cachedVertexBuffers = null;
- this._cachedIndexBuffer = null;
- this._cachedEffectForVertexBuffers = null;
- }
- _createTexture() {
- return this._engine.createTexture();
- }
- _deleteTexture(texture) {
- if (texture) {
- this._engine.deleteTexture(texture);
- }
- }
- /**
- * Update the content of a dynamic texture
- * @param texture defines the texture to update
- * @param canvas defines the canvas containing the source
- * @param invertY defines if data must be stored with Y axis inverted
- * @param premulAlpha defines if alpha is stored as premultiplied
- * @param format defines the format of the data
- */
- updateDynamicTexture(texture, canvas, invertY, premulAlpha = false, format) {
- if (premulAlpha === void 0) {
- premulAlpha = false;
- }
- if (!!texture && !!texture._hardwareTexture) {
- const source = canvas.getCanvasTexture();
- const destination = texture._hardwareTexture.underlyingResource;
- this._engine.copyTexture(destination, source);
- texture.isReady = true;
- }
- }
- createDynamicTexture(width, height, generateMipMaps, samplingMode) {
- // it's not possible to create 0x0 texture sized. Many bgfx methods assume texture size is at least 1x1(best case).
- // Worst case is getting a crash/assert.
- width = Math.max(width, 1);
- height = Math.max(height, 1);
- return this.createRawTexture(new Uint8Array(width * height * 4), width, height, 5, false, false, samplingMode);
- }
- createVideoElement(constraints) {
- // create native object depending on stream. Only NativeCamera is supported for now.
- if (this._camera) {
- return this._camera.createVideo(constraints);
- }
- return null;
- }
- updateVideoTexture(texture, video, invertY) {
- if (texture && texture._hardwareTexture && this._camera) {
- const webGLTexture = texture._hardwareTexture.underlyingResource;
- this._camera.updateVideoTexture(webGLTexture, video, invertY);
- }
- }
- createRawTexture(data, width, height, format, generateMipMaps, invertY, samplingMode, compression = null, type = 0, creationFlags = 0, useSRGBBuffer = false) {
- const texture = new InternalTexture(this, InternalTextureSource.Raw);
- texture.format = format;
- texture.generateMipMaps = generateMipMaps;
- texture.samplingMode = samplingMode;
- texture.invertY = invertY;
- texture.baseWidth = width;
- texture.baseHeight = height;
- texture.width = texture.baseWidth;
- texture.height = texture.baseHeight;
- texture._compression = compression;
- texture.type = type;
- texture._useSRGBBuffer = this._getUseSRGBBuffer(useSRGBBuffer, !generateMipMaps);
- this.updateRawTexture(texture, data, format, invertY, compression, type, texture._useSRGBBuffer);
- if (texture._hardwareTexture) {
- const webGLTexture = texture._hardwareTexture.underlyingResource;
- const filter = getNativeSamplingMode(samplingMode);
- this._setTextureSampling(webGLTexture, filter);
- }
- this._internalTexturesCache.push(texture);
- return texture;
- }
- createRawTexture2DArray(data, width, height, depth, format, generateMipMaps, invertY, samplingMode, compression = null, textureType = 0) {
- const texture = new InternalTexture(this, InternalTextureSource.Raw2DArray);
- texture.baseWidth = width;
- texture.baseHeight = height;
- texture.baseDepth = depth;
- texture.width = width;
- texture.height = height;
- texture.depth = depth;
- texture.format = format;
- texture.type = textureType;
- texture.generateMipMaps = generateMipMaps;
- texture.samplingMode = samplingMode;
- texture.is2DArray = true;
- if (texture._hardwareTexture) {
- const nativeTexture = texture._hardwareTexture.underlyingResource;
- this._engine.loadRawTexture2DArray(nativeTexture, data, width, height, depth, getNativeTextureFormat(format, textureType), generateMipMaps, invertY);
- const filter = getNativeSamplingMode(samplingMode);
- this._setTextureSampling(nativeTexture, filter);
- }
- texture.isReady = true;
- this._internalTexturesCache.push(texture);
- return texture;
- }
- updateRawTexture(texture, bufferView, format, invertY, compression = null, type = 0, useSRGBBuffer = false) {
- if (!texture) {
- return;
- }
- if (bufferView && texture._hardwareTexture) {
- const underlyingResource = texture._hardwareTexture.underlyingResource;
- this._engine.loadRawTexture(underlyingResource, bufferView, texture.width, texture.height, getNativeTextureFormat(format, type), texture.generateMipMaps, texture.invertY);
- }
- texture.isReady = true;
- }
- // TODO: Refactor to share more logic with babylon.engine.ts version.
- /**
- * Usually called from Texture.ts.
- * Passed information to create a NativeTexture
- * @param url defines a value which contains one of the following:
- * * A conventional http URL, e.g. 'http://...' or 'file://...'
- * * A base64 string of in-line texture data, e.g. 'data:image/jpg;base64,/...'
- * * An indicator that data being passed using the buffer parameter, e.g. 'data:mytexture.jpg'
- * @param noMipmap defines a boolean indicating that no mipmaps shall be generated. Ignored for compressed textures. They must be in the file
- * @param invertY when true, image is flipped when loaded. You probably want true. Certain compressed textures may invert this if their default is inverted (eg. ktx)
- * @param scene needed for loading to the correct scene
- * @param samplingMode mode with should be used sample / access the texture (Default: Texture.TRILINEAR_SAMPLINGMODE)
- * @param onLoad optional callback to be called upon successful completion
- * @param onError optional callback to be called upon failure
- * @param buffer a source of a file previously fetched as either a base64 string, an ArrayBuffer (compressed or image format), HTMLImageElement (image format), or a Blob
- * @param fallback an internal argument in case the function must be called again, due to etc1 not having alpha capabilities
- * @param format internal format. Default: RGB when extension is '.jpg' else RGBA. Ignored for compressed textures
- * @param forcedExtension defines the extension to use to pick the right loader
- * @param mimeType defines an optional mime type
- * @param loaderOptions options to be passed to the loader
- * @param creationFlags specific flags to use when creating the texture (1 for storage textures, for eg)
- * @param useSRGBBuffer defines if the texture must be loaded in a sRGB GPU buffer (if supported by the GPU).
- * @returns a InternalTexture for assignment back into BABYLON.Texture
- */
- createTexture(url, noMipmap, invertY, scene, samplingMode = 3, onLoad = null, onError = null, buffer = null, fallback = null, format = null, forcedExtension = null, mimeType, loaderOptions, creationFlags, useSRGBBuffer = false) {
- url = url || "";
- const fromData = url.substr(0, 5) === "data:";
- //const fromBlob = url.substr(0, 5) === "blob:";
- const isBase64 = fromData && url.indexOf(";base64,") !== -1;
- const texture = fallback ? fallback : new InternalTexture(this, InternalTextureSource.Url);
- const originalUrl = url;
- if (this._transformTextureUrl && !isBase64 && !fallback && !buffer) {
- url = this._transformTextureUrl(url);
- }
- // establish the file extension, if possible
- const lastDot = url.lastIndexOf(".");
- const extension = forcedExtension ? forcedExtension : lastDot > -1 ? url.substring(lastDot).toLowerCase() : "";
- let loader = null;
- for (const availableLoader of AbstractEngine._TextureLoaders) {
- if (availableLoader.canLoad(extension)) {
- loader = availableLoader;
- break;
- }
- }
- if (scene) {
- scene.addPendingData(texture);
- }
- texture.url = url;
- texture.generateMipMaps = !noMipmap;
- texture.samplingMode = samplingMode;
- texture.invertY = invertY;
- texture._useSRGBBuffer = this._getUseSRGBBuffer(useSRGBBuffer, noMipmap);
- if (!this.doNotHandleContextLost) {
- // Keep a link to the buffer only if we plan to handle context lost
- texture._buffer = buffer;
- }
- let onLoadObserver = null;
- if (onLoad && !fallback) {
- onLoadObserver = texture.onLoadedObservable.add(onLoad);
- }
- if (!fallback) {
- this._internalTexturesCache.push(texture);
- }
- const onInternalError = (message, exception) => {
- if (scene) {
- scene.removePendingData(texture);
- }
- if (url === originalUrl) {
- if (onLoadObserver) {
- texture.onLoadedObservable.remove(onLoadObserver);
- }
- if (EngineStore.UseFallbackTexture) {
- this.createTexture(EngineStore.FallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
- }
- if (onError) {
- onError((message || "Unknown error") + (EngineStore.UseFallbackTexture ? " - Fallback texture was used" : ""), exception);
- }
- }
- else {
- // fall back to the original url if the transformed url fails to load
- Logger.Warn(`Failed to load ${url}, falling back to ${originalUrl}`);
- this.createTexture(originalUrl, noMipmap, texture.invertY, scene, samplingMode, onLoad, onError, buffer, texture, format, forcedExtension, mimeType, loaderOptions);
- }
- };
- // processing for non-image formats
- if (loader) {
- throw new Error("Loading textures from IInternalTextureLoader not yet implemented.");
- }
- else {
- const onload = (data) => {
- if (!texture._hardwareTexture) {
- if (scene) {
- scene.removePendingData(texture);
- }
- return;
- }
- const underlyingResource = texture._hardwareTexture.underlyingResource;
- this._engine.loadTexture(underlyingResource, data, !noMipmap, invertY, texture._useSRGBBuffer, () => {
- texture.baseWidth = this._engine.getTextureWidth(underlyingResource);
- texture.baseHeight = this._engine.getTextureHeight(underlyingResource);
- texture.width = texture.baseWidth;
- texture.height = texture.baseHeight;
- texture.isReady = true;
- const filter = getNativeSamplingMode(samplingMode);
- this._setTextureSampling(underlyingResource, filter);
- if (scene) {
- scene.removePendingData(texture);
- }
- texture.onLoadedObservable.notifyObservers(texture);
- texture.onLoadedObservable.clear();
- }, () => {
- throw new Error("Could not load a native texture.");
- });
- };
- if (fromData && buffer) {
- if (buffer instanceof ArrayBuffer) {
- onload(new Uint8Array(buffer));
- }
- else if (ArrayBuffer.isView(buffer)) {
- onload(buffer);
- }
- else if (typeof buffer === "string") {
- onload(new Uint8Array(Tools.DecodeBase64(buffer)));
- }
- else {
- throw new Error("Unsupported buffer type");
- }
- }
- else {
- if (isBase64) {
- onload(new Uint8Array(Tools.DecodeBase64(url)));
- }
- else {
- this._loadFile(url, (data) => onload(new Uint8Array(data)), undefined, undefined, true, (request, exception) => {
- onInternalError("Unable to load " + (request ? request.responseURL : url, exception));
- });
- }
- }
- }
- return texture;
- }
- /**
- * Wraps an external native texture in a Babylon texture.
- * @param texture defines the external texture
- * @param hasMipMaps defines whether the external texture has mip maps
- * @param samplingMode defines the sampling mode for the external texture (default: 3)
- * @returns the babylon internal texture
- */
- wrapNativeTexture(texture, hasMipMaps = false, samplingMode = 3) {
- const hardwareTexture = new NativeHardwareTexture(texture, this._engine);
- const internalTexture = new InternalTexture(this, InternalTextureSource.Unknown, true);
- internalTexture._hardwareTexture = hardwareTexture;
- internalTexture.baseWidth = this._engine.getTextureWidth(texture);
- internalTexture.baseHeight = this._engine.getTextureHeight(texture);
- internalTexture.width = internalTexture.baseWidth;
- internalTexture.height = internalTexture.baseHeight;
- internalTexture.isReady = true;
- internalTexture.useMipMaps = hasMipMaps;
- this.updateTextureSamplingMode(samplingMode, internalTexture);
- return internalTexture;
- }
- // eslint-disable-next-line jsdoc/require-returns-check
- /**
- * Wraps an external web gl texture in a Babylon texture.
- * @returns the babylon internal texture
- */
- wrapWebGLTexture() {
- throw new Error("wrapWebGLTexture is not supported, use wrapNativeTexture instead.");
- }
- _createDepthStencilTexture(size, options, rtWrapper) {
- // TODO: handle other options?
- const generateStencil = options.generateStencil || false;
- const samples = options.samples || 1;
- const nativeRTWrapper = rtWrapper;
- const texture = new InternalTexture(this, InternalTextureSource.DepthStencil);
- const width = size.width ?? size;
- const height = size.height ?? size;
- const framebuffer = this._engine.createFrameBuffer(texture._hardwareTexture.underlyingResource, width, height, generateStencil, true, samples);
- nativeRTWrapper._framebufferDepthStencil = framebuffer;
- return texture;
- }
- /**
- * @internal
- */
- _releaseFramebufferObjects(framebuffer) {
- if (framebuffer) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DELETEFRAMEBUFFER);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(framebuffer);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- }
- /**
- * @internal Engine abstraction for loading and creating an image bitmap from a given source string.
- * @param imageSource source to load the image from.
- * @param options An object that sets options for the image's extraction.
- * @returns ImageBitmap
- */
- _createImageBitmapFromSource(imageSource, options) {
- const promise = new Promise((resolve, reject) => {
- const image = this.createCanvasImage();
- image.onload = () => {
- try {
- const imageBitmap = this._engine.createImageBitmap(image);
- resolve(imageBitmap);
- }
- catch (error) {
- reject(`Error loading image ${image.src} with exception: ${error}`);
- }
- };
- image.onerror = (error) => {
- reject(`Error loading image ${image.src} with exception: ${error}`);
- };
- image.src = imageSource;
- });
- return promise;
- }
- /**
- * Engine abstraction for createImageBitmap
- * @param image source for image
- * @param options An object that sets options for the image's extraction.
- * @returns ImageBitmap
- */
- createImageBitmap(image, options) {
- return new Promise((resolve, reject) => {
- if (Array.isArray(image)) {
- const arr = image;
- if (arr.length) {
- const image = this._engine.createImageBitmap(arr[0]);
- if (image) {
- resolve(image);
- return;
- }
- }
- }
- reject(`Unsupported data for createImageBitmap.`);
- });
- }
- /**
- * Resize an image and returns the image data as an uint8array
- * @param image image to resize
- * @param bufferWidth destination buffer width
- * @param bufferHeight destination buffer height
- * @returns an uint8array containing RGBA values of bufferWidth * bufferHeight size
- */
- resizeImageBitmap(image, bufferWidth, bufferHeight) {
- return this._engine.resizeImageBitmap(image, bufferWidth, bufferHeight);
- }
- /**
- * Creates a cube texture
- * @param rootUrl defines the url where the files to load is located
- * @param scene defines the current scene
- * @param files defines the list of files to load (1 per face)
- * @param noMipmap defines a boolean indicating that no mipmaps shall be generated (false by default)
- * @param onLoad defines an optional callback raised when the texture is loaded
- * @param onError defines an optional callback raised if there is an issue to load the texture
- * @param format defines the format of the data
- * @param forcedExtension defines the extension to use to pick the right loader
- * @param createPolynomials if a polynomial sphere should be created for the cube texture
- * @param lodScale defines the scale applied to environment texture. This manages the range of LOD level used for IBL according to the roughness
- * @param lodOffset defines the offset applied to environment texture. This manages first LOD level used for IBL according to the roughness
- * @param fallback defines texture to use while falling back when (compressed) texture file not found.
- * @param loaderOptions options to be passed to the loader
- * @param useSRGBBuffer defines if the texture must be loaded in a sRGB GPU buffer (if supported by the GPU).
- * @returns the cube texture as an InternalTexture
- */
- createCubeTexture(rootUrl, scene, files, noMipmap, onLoad = null, onError = null, format, forcedExtension = null, createPolynomials = false, lodScale = 0, lodOffset = 0, fallback = null, loaderOptions, useSRGBBuffer = false) {
- const texture = fallback ? fallback : new InternalTexture(this, InternalTextureSource.Cube);
- texture.isCube = true;
- texture.url = rootUrl;
- texture.generateMipMaps = !noMipmap;
- texture._lodGenerationScale = lodScale;
- texture._lodGenerationOffset = lodOffset;
- texture._useSRGBBuffer = this._getUseSRGBBuffer(useSRGBBuffer, !!noMipmap);
- if (!this._doNotHandleContextLost) {
- texture._extension = forcedExtension;
- texture._files = files;
- }
- const lastDot = rootUrl.lastIndexOf(".");
- const extension = forcedExtension ? forcedExtension : lastDot > -1 ? rootUrl.substring(lastDot).toLowerCase() : "";
- // TODO: use texture loader to load env files?
- if (extension === ".env") {
- const onloaddata = (data) => {
- const info = GetEnvInfo(data);
- texture.width = info.width;
- texture.height = info.width;
- UploadEnvSpherical(texture, info);
- const specularInfo = info.specular;
- if (!specularInfo) {
- throw new Error(`Nothing else parsed so far`);
- }
- texture._lodGenerationScale = specularInfo.lodGenerationScale;
- const imageData = CreateImageDataArrayBufferViews(data, info);
- texture.format = 5;
- texture.type = 0;
- texture.generateMipMaps = true;
- texture.getEngine().updateTextureSamplingMode(Texture.TRILINEAR_SAMPLINGMODE, texture);
- texture._isRGBD = true;
- texture.invertY = true;
- this._engine.loadCubeTextureWithMips(texture._hardwareTexture.underlyingResource, imageData, false, texture._useSRGBBuffer, () => {
- texture.isReady = true;
- if (onLoad) {
- onLoad();
- }
- }, () => {
- throw new Error("Could not load a native cube texture.");
- });
- };
- if (files && files.length === 6) {
- throw new Error(`Multi-file loading not allowed on env files.`);
- }
- else {
- const onInternalError = (request, exception) => {
- if (onError && request) {
- onError(request.status + " " + request.statusText, exception);
- }
- };
- this._loadFile(rootUrl, (data) => {
- onloaddata(new Uint8Array(data, 0, data.byteLength));
- }, undefined, undefined, true, onInternalError);
- }
- }
- else {
- if (!files || files.length !== 6) {
- throw new Error("Cannot load cubemap because 6 files were not defined");
- }
- // Reorder from [+X, +Y, +Z, -X, -Y, -Z] to [+X, -X, +Y, -Y, +Z, -Z].
- const reorderedFiles = [files[0], files[3], files[1], files[4], files[2], files[5]];
- Promise.all(reorderedFiles.map((file) => this._loadFileAsync(file, undefined, true).then((data) => new Uint8Array(data, 0, data.byteLength))))
- .then((data) => {
- return new Promise((resolve, reject) => {
- this._engine.loadCubeTexture(texture._hardwareTexture.underlyingResource, data, !noMipmap, true, texture._useSRGBBuffer, resolve, reject);
- });
- })
- .then(() => {
- texture.isReady = true;
- if (onLoad) {
- onLoad();
- }
- }, (error) => {
- if (onError) {
- onError(`Failed to load cubemap: ${error.message}`, error);
- }
- });
- }
- this._internalTexturesCache.push(texture);
- return texture;
- }
- /** @internal */
- _createHardwareTexture() {
- return new NativeHardwareTexture(this._createTexture(), this._engine);
- }
- /** @internal */
- _createHardwareRenderTargetWrapper(isMulti, isCube, size) {
- const rtWrapper = new NativeRenderTargetWrapper(isMulti, isCube, size, this);
- this._renderTargetWrapperCache.push(rtWrapper);
- return rtWrapper;
- }
- /** @internal */
- _createInternalTexture(size, options, _delayGPUTextureCreation = true, source = InternalTextureSource.Unknown) {
- let generateMipMaps = false;
- let type = 0;
- let samplingMode = 3;
- let format = 5;
- let useSRGBBuffer = false;
- let samples = 1;
- let label;
- if (options !== undefined && typeof options === "object") {
- generateMipMaps = !!options.generateMipMaps;
- type = options.type === undefined ? 0 : options.type;
- samplingMode = options.samplingMode === undefined ? 3 : options.samplingMode;
- format = options.format === undefined ? 5 : options.format;
- useSRGBBuffer = options.useSRGBBuffer === undefined ? false : options.useSRGBBuffer;
- samples = options.samples ?? 1;
- label = options.label;
- }
- else {
- generateMipMaps = !!options;
- }
- useSRGBBuffer = this._getUseSRGBBuffer(useSRGBBuffer, !generateMipMaps);
- if (type === 1 && !this._caps.textureFloatLinearFiltering) {
- // if floating point linear (gl.FLOAT) then force to NEAREST_SAMPLINGMODE
- samplingMode = 1;
- }
- else if (type === 2 && !this._caps.textureHalfFloatLinearFiltering) {
- // if floating point linear (HALF_FLOAT) then force to NEAREST_SAMPLINGMODE
- samplingMode = 1;
- }
- if (type === 1 && !this._caps.textureFloat) {
- type = 0;
- Logger.Warn("Float textures are not supported. Type forced to TEXTURETYPE_UNSIGNED_BYTE");
- }
- const texture = new InternalTexture(this, source);
- const width = size.width ?? size;
- const height = size.height ?? size;
- const layers = size.layers || 0;
- if (layers !== 0) {
- throw new Error("Texture layers are not supported in Babylon Native");
- }
- const nativeTexture = texture._hardwareTexture.underlyingResource;
- const nativeTextureFormat = getNativeTextureFormat(format, type);
- // REVIEW: We are always setting the renderTarget flag as we don't know whether the texture will be used as a render target.
- this._engine.initializeTexture(nativeTexture, width, height, generateMipMaps, nativeTextureFormat, true, useSRGBBuffer, samples);
- this._setTextureSampling(nativeTexture, getNativeSamplingMode(samplingMode));
- texture._useSRGBBuffer = useSRGBBuffer;
- texture.baseWidth = width;
- texture.baseHeight = height;
- texture.width = width;
- texture.height = height;
- texture.depth = layers;
- texture.isReady = true;
- texture.samples = samples;
- texture.generateMipMaps = generateMipMaps;
- texture.samplingMode = samplingMode;
- texture.type = type;
- texture.format = format;
- texture.label = label;
- this._internalTexturesCache.push(texture);
- return texture;
- }
- createRenderTargetTexture(size, options) {
- const rtWrapper = this._createHardwareRenderTargetWrapper(false, false, size);
- let generateDepthBuffer = true;
- let generateStencilBuffer = false;
- let noColorAttachment = false;
- let colorAttachment = undefined;
- let samples = 1;
- if (options !== undefined && typeof options === "object") {
- generateDepthBuffer = options.generateDepthBuffer ?? true;
- generateStencilBuffer = !!options.generateStencilBuffer;
- noColorAttachment = !!options.noColorAttachment;
- colorAttachment = options.colorAttachment;
- samples = options.samples ?? 1;
- }
- const texture = colorAttachment || (noColorAttachment ? null : this._createInternalTexture(size, options, true, InternalTextureSource.RenderTarget));
- const width = size.width ?? size;
- const height = size.height ?? size;
- const framebuffer = this._engine.createFrameBuffer(texture ? texture._hardwareTexture.underlyingResource : null, width, height, generateStencilBuffer, generateDepthBuffer, samples);
- rtWrapper._framebuffer = framebuffer;
- rtWrapper._generateDepthBuffer = generateDepthBuffer;
- rtWrapper._generateStencilBuffer = generateStencilBuffer;
- rtWrapper._samples = samples;
- rtWrapper.setTextures(texture);
- return rtWrapper;
- }
- updateRenderTargetTextureSampleCount(rtWrapper, samples) {
- Logger.Warn("Updating render target sample count is not currently supported");
- return rtWrapper.samples;
- }
- updateTextureSamplingMode(samplingMode, texture) {
- if (texture._hardwareTexture) {
- const filter = getNativeSamplingMode(samplingMode);
- this._setTextureSampling(texture._hardwareTexture.underlyingResource, filter);
- }
- texture.samplingMode = samplingMode;
- }
- bindFramebuffer(texture, faceIndex, requiredWidth, requiredHeight, forceFullscreenViewport) {
- const nativeRTWrapper = texture;
- if (this._currentRenderTarget) {
- this.unBindFramebuffer(this._currentRenderTarget);
- }
- this._currentRenderTarget = texture;
- if (faceIndex) {
- throw new Error("Cuboid frame buffers are not yet supported in NativeEngine.");
- }
- if (requiredWidth || requiredHeight) {
- throw new Error("Required width/height for frame buffers not yet supported in NativeEngine.");
- }
- if (forceFullscreenViewport) {
- //Not supported yet but don't stop rendering
- }
- if (nativeRTWrapper._framebufferDepthStencil) {
- this._bindUnboundFramebuffer(nativeRTWrapper._framebufferDepthStencil);
- }
- else {
- this._bindUnboundFramebuffer(nativeRTWrapper._framebuffer);
- }
- }
- unBindFramebuffer(texture, disableGenerateMipMaps = false, onBeforeUnbind) {
- // NOTE: Disabling mipmap generation is not yet supported in NativeEngine.
- this._currentRenderTarget = null;
- if (onBeforeUnbind) {
- onBeforeUnbind();
- }
- this._bindUnboundFramebuffer(null);
- }
- createDynamicVertexBuffer(data) {
- return this.createVertexBuffer(data, true);
- }
- updateDynamicIndexBuffer(indexBuffer, indices, offset = 0) {
- const buffer = indexBuffer;
- const data = this._normalizeIndexData(indices);
- buffer.is32Bits = data.BYTES_PER_ELEMENT === 4;
- this._engine.updateDynamicIndexBuffer(buffer.nativeIndexBuffer, data.buffer, data.byteOffset, data.byteLength, offset);
- }
- updateDynamicVertexBuffer(vertexBuffer, data, byteOffset = 0, byteLength) {
- const buffer = vertexBuffer;
- const dataView = data instanceof Array ? new Float32Array(data) : data instanceof ArrayBuffer ? new Uint8Array(data) : data;
- const byteView = new Uint8Array(dataView.buffer, dataView.byteOffset, byteLength ?? dataView.byteLength);
- this._engine.updateDynamicVertexBuffer(buffer.nativeVertexBuffer, byteView.buffer, byteView.byteOffset, byteView.byteLength, byteOffset);
- }
- // TODO: Refactor to share more logic with base Engine implementation.
- _setTexture(channel, texture, isPartOfTextureArray = false, depthStencilTexture = false) {
- const uniform = this._boundUniforms[channel];
- if (!uniform) {
- return false;
- }
- // Not ready?
- if (!texture) {
- if (this._boundTexturesCache[channel] != null) {
- this._activeChannel = channel;
- this._boundTexturesCache[channel] = null;
- }
- return false;
- }
- // Video
- if (texture.video) {
- this._activeChannel = channel;
- texture.update();
- }
- else if (texture.delayLoadState === 4) {
- // Delay loading
- texture.delayLoad();
- return false;
- }
- let internalTexture;
- if (depthStencilTexture) {
- internalTexture = texture.depthStencilTexture;
- }
- else if (texture.isReady()) {
- internalTexture = texture.getInternalTexture();
- }
- else if (texture.isCube) {
- internalTexture = this.emptyCubeTexture;
- }
- else if (texture.is3D) {
- internalTexture = this.emptyTexture3D;
- }
- else if (texture.is2DArray) {
- internalTexture = this.emptyTexture2DArray;
- }
- else {
- internalTexture = this.emptyTexture;
- }
- this._activeChannel = channel;
- if (!internalTexture || !internalTexture._hardwareTexture) {
- return false;
- }
- this._setTextureWrapMode(internalTexture._hardwareTexture.underlyingResource, getNativeAddressMode(texture.wrapU), getNativeAddressMode(texture.wrapV), getNativeAddressMode(texture.wrapR));
- this._updateAnisotropicLevel(texture);
- this._setTextureCore(uniform, internalTexture._hardwareTexture.underlyingResource);
- return true;
- }
- // filter is a NativeFilter.XXXX value.
- _setTextureSampling(texture, filter) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETTEXTURESAMPLING);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(texture);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(filter);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- // addressModes are NativeAddressMode.XXXX values.
- _setTextureWrapMode(texture, addressModeU, addressModeV, addressModeW) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETTEXTUREWRAPMODE);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(texture);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(addressModeU);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(addressModeV);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(addressModeW);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- _setTextureCore(uniform, texture) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETTEXTURE);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(uniform);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(texture);
- this._commandBufferEncoder.finishEncodingCommand();
- }
- // TODO: Share more of this logic with the base implementation.
- // TODO: Rename to match naming in base implementation once refactoring allows different parameters.
- _updateAnisotropicLevel(texture) {
- const internalTexture = texture.getInternalTexture();
- const value = texture.anisotropicFilteringLevel;
- if (!internalTexture || !internalTexture._hardwareTexture) {
- return;
- }
- if (internalTexture._cachedAnisotropicFilteringLevel !== value) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETTEXTUREANISOTROPICLEVEL);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(internalTexture._hardwareTexture.underlyingResource);
- this._commandBufferEncoder.encodeCommandArgAsUInt32(value);
- this._commandBufferEncoder.finishEncodingCommand();
- internalTexture._cachedAnisotropicFilteringLevel = value;
- }
- }
- /**
- * @internal
- */
- _bindTexture(channel, texture) {
- const uniform = this._boundUniforms[channel];
- if (!uniform) {
- return;
- }
- if (texture && texture._hardwareTexture) {
- const underlyingResource = texture._hardwareTexture.underlyingResource;
- this._setTextureCore(uniform, underlyingResource);
- }
- }
- _deleteBuffer(buffer) {
- if (buffer.nativeIndexBuffer) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DELETEINDEXBUFFER);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(buffer.nativeIndexBuffer);
- this._commandBufferEncoder.finishEncodingCommand();
- delete buffer.nativeIndexBuffer;
- }
- if (buffer.nativeVertexBuffer) {
- this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DELETEVERTEXBUFFER);
- this._commandBufferEncoder.encodeCommandArgAsNativeData(buffer.nativeVertexBuffer);
- this._commandBufferEncoder.finishEncodingCommand();
- delete buffer.nativeVertexBuffer;
- }
- }
- /**
- * Create a canvas
- * @param width width
- * @param height height
- * @returns ICanvas interface
- */
- createCanvas(width, height) {
- if (!_native.Canvas) {
- throw new Error("Native Canvas plugin not available.");
- }
- const canvas = new _native.Canvas();
- canvas.width = width;
- canvas.height = height;
- return canvas;
- }
- /**
- * Create an image to use with canvas
- * @returns IImage interface
- */
- createCanvasImage() {
- if (!_native.Canvas) {
- throw new Error("Native Canvas plugin not available.");
- }
- const image = new _native.Image();
- return image;
- }
- /**
- * Update a portion of an internal texture
- * @param texture defines the texture to update
- * @param imageData defines the data to store into the texture
- * @param xOffset defines the x coordinates of the update rectangle
- * @param yOffset defines the y coordinates of the update rectangle
- * @param width defines the width of the update rectangle
- * @param height defines the height of the update rectangle
- * @param faceIndex defines the face index if texture is a cube (0 by default)
- * @param lod defines the lod level to update (0 by default)
- * @param generateMipMaps defines whether to generate mipmaps or not
- */
- updateTextureData(texture, imageData, xOffset, yOffset, width, height, faceIndex = 0, lod = 0, generateMipMaps = false) {
- throw new Error("updateTextureData not implemented.");
- }
- /**
- * @internal
- */
- _uploadCompressedDataToTextureDirectly(texture, internalFormat, width, height, data, faceIndex = 0, lod = 0) {
- throw new Error("_uploadCompressedDataToTextureDirectly not implemented.");
- }
- /**
- * @internal
- */
- _uploadDataToTextureDirectly(texture, imageData, faceIndex = 0, lod = 0) {
- throw new Error("_uploadDataToTextureDirectly not implemented.");
- }
- /**
- * @internal
- */
- _uploadArrayBufferViewToTexture(texture, imageData, faceIndex = 0, lod = 0) {
- throw new Error("_uploadArrayBufferViewToTexture not implemented.");
- }
- /**
- * @internal
- */
- _uploadImageToTexture(texture, image, faceIndex = 0, lod = 0) {
- throw new Error("_uploadArrayBufferViewToTexture not implemented.");
- }
- getFontOffset(font) {
- // TODO
- const result = { ascent: 0, height: 0, descent: 0 };
- return result;
- }
- /**
- * No equivalent for native. Do nothing.
- */
- flushFramebuffer() { }
- _readTexturePixels(texture, width, height, faceIndex, level, buffer, _flushRenderer, _noDataConversion, x, y) {
- if (faceIndex !== undefined && faceIndex !== -1) {
- throw new Error(`Reading cubemap faces is not supported, but faceIndex is ${faceIndex}.`);
- }
- return this._engine
- .readTexture(texture._hardwareTexture?.underlyingResource, level ?? 0, x ?? 0, y ?? 0, width, height, buffer?.buffer ?? null, buffer?.byteOffset ?? 0, buffer?.byteLength ?? 0)
- .then((rawBuffer) => {
- if (!buffer) {
- buffer = new Uint8Array(rawBuffer);
- }
- return buffer;
- });
- }
- }
- // This must match the protocol version in NativeEngine.cpp
- NativeEngine.PROTOCOL_VERSION = 8;
- //# sourceMappingURL=nativeEngine.js.map
|