123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954 |
- import { InternalTexture, InternalTextureSource } from "../Materials/Textures/internalTexture.js";
- import { EngineStore } from "./engineStore.js";
- import { ThinEngine } from "./thinEngine.js";
- import { PerformanceMonitor } from "../Misc/performanceMonitor.js";
- import { WebGLDataBuffer } from "../Meshes/WebGL/webGLDataBuffer.js";
- import { Logger } from "../Misc/logger.js";
- import { WebGLHardwareTexture } from "./WebGL/webGLHardwareTexture.js";
- import "./Extensions/engine.alpha.js";
- import "./Extensions/engine.readTexture.js";
- import "./Extensions/engine.dynamicBuffer.js";
- import "./AbstractEngine/abstractEngine.loadingScreen.js";
- import "./AbstractEngine/abstractEngine.dom.js";
- import "./AbstractEngine/abstractEngine.states.js";
- import "./AbstractEngine/abstractEngine.renderPass.js";
- import "./AbstractEngine/abstractEngine.texture.js";
- import { AbstractEngine } from "./abstractEngine.js";
- import { CreateImageBitmapFromSource, ExitFullscreen, ExitPointerlock, GetFontOffset, RequestFullscreen, RequestPointerlock, ResizeImageBitmap, _CommonDispose, _CommonInit, } from "./engine.common.js";
- import { PerfCounter } from "../Misc/perfCounter.js";
- import "../Audio/audioEngine.js";
- /**
- * The engine class is responsible for interfacing with all lower-level APIs such as WebGL and Audio
- */
- export class Engine extends ThinEngine {
- /**
- * Returns the current npm package of the sdk
- */
- // Not mixed with Version for tooling purpose.
- static get NpmPackage() {
- return AbstractEngine.NpmPackage;
- }
- /**
- * Returns the current version of the framework
- */
- static get Version() {
- return AbstractEngine.Version;
- }
- /** Gets the list of created engines */
- static get Instances() {
- return EngineStore.Instances;
- }
- /**
- * Gets the latest created engine
- */
- static get LastCreatedEngine() {
- return EngineStore.LastCreatedEngine;
- }
- /**
- * Gets the latest created scene
- */
- static get LastCreatedScene() {
- return EngineStore.LastCreatedScene;
- }
- /** @internal */
- /**
- * Will flag all materials in all scenes in all engines as dirty to trigger new shader compilation
- * @param flag defines which part of the materials must be marked as dirty
- * @param predicate defines a predicate used to filter which materials should be affected
- */
- static MarkAllMaterialsAsDirty(flag, predicate) {
- for (let engineIndex = 0; engineIndex < Engine.Instances.length; engineIndex++) {
- const engine = Engine.Instances[engineIndex];
- for (let sceneIndex = 0; sceneIndex < engine.scenes.length; sceneIndex++) {
- engine.scenes[sceneIndex].markAllMaterialsAsDirty(flag, predicate);
- }
- }
- }
- // eslint-disable-next-line jsdoc/require-returns-check
- /**
- * Method called to create the default loading screen.
- * This can be overridden in your own app.
- * @param canvas The rendering canvas element
- * @returns The loading screen
- */
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- static DefaultLoadingScreenFactory(canvas) {
- return AbstractEngine.DefaultLoadingScreenFactory(canvas);
- }
- get _supportsHardwareTextureRescaling() {
- return !!Engine._RescalePostProcessFactory;
- }
- _measureFps() {
- this._performanceMonitor.sampleFrame();
- this._fps = this._performanceMonitor.averageFPS;
- this._deltaTime = this._performanceMonitor.instantaneousFrameTime || 0;
- }
- /**
- * Gets the performance monitor attached to this engine
- * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/optimize_your_scene#engineinstrumentation
- */
- get performanceMonitor() {
- return this._performanceMonitor;
- }
- // Events
- /**
- * Creates a new engine
- * @param canvasOrContext defines the canvas or WebGL context to use for rendering. If you provide a WebGL context, Babylon.js will not hook events on the canvas (like pointers, keyboards, etc...) so no event observables will be available. This is mostly used when Babylon.js is used as a plugin on a system which already used the WebGL context
- * @param antialias defines enable antialiasing (default: false)
- * @param options defines further options to be sent to the getContext() function
- * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
- */
- constructor(canvasOrContext, antialias, options, adaptToDeviceRatio = false) {
- super(canvasOrContext, antialias, options, adaptToDeviceRatio);
- // Members
- /**
- * If set, will be used to request the next animation frame for the render loop
- */
- this.customAnimationFrameRequester = null;
- this._performanceMonitor = new PerformanceMonitor();
- this._drawCalls = new PerfCounter();
- if (!canvasOrContext) {
- return;
- }
- this._features.supportRenderPasses = true;
- options = this._creationOptions;
- if (canvasOrContext.getContext) {
- const canvas = canvasOrContext;
- this._sharedInit(canvas);
- }
- }
- _initGLContext() {
- super._initGLContext();
- this._rescalePostProcess = null;
- }
- /**
- * Shared initialization across engines types.
- * @param canvas The canvas associated with this instance of the engine.
- */
- _sharedInit(canvas) {
- super._sharedInit(canvas);
- _CommonInit(this, canvas, this._creationOptions);
- }
- /**
- * 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 ResizeImageBitmap(this, image, bufferWidth, bufferHeight);
- }
- /**
- * 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) {
- return CreateImageBitmapFromSource(this, imageSource, options);
- }
- /**
- * Toggle full screen mode
- * @param requestPointerLock defines if a pointer lock should be requested from the user
- */
- switchFullscreen(requestPointerLock) {
- if (this.isFullscreen) {
- this.exitFullscreen();
- }
- else {
- this.enterFullscreen(requestPointerLock);
- }
- }
- /**
- * Enters full screen mode
- * @param requestPointerLock defines if a pointer lock should be requested from the user
- */
- enterFullscreen(requestPointerLock) {
- if (!this.isFullscreen) {
- this._pointerLockRequested = requestPointerLock;
- if (this._renderingCanvas) {
- RequestFullscreen(this._renderingCanvas);
- }
- }
- }
- /**
- * Exits full screen mode
- */
- exitFullscreen() {
- if (this.isFullscreen) {
- ExitFullscreen();
- }
- }
- generateMipMapsForCubemap(texture, unbind = true) {
- if (texture.generateMipMaps) {
- const gl = this._gl;
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
- gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
- if (unbind) {
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
- }
- }
- }
- /** States */
- /**
- * Sets a boolean indicating if the dithering state is enabled or disabled
- * @param value defines the dithering state
- */
- setDitheringState(value) {
- if (value) {
- this._gl.enable(this._gl.DITHER);
- }
- else {
- this._gl.disable(this._gl.DITHER);
- }
- }
- /**
- * Sets a boolean indicating if the rasterizer state is enabled or disabled
- * @param value defines the rasterizer state
- */
- setRasterizerState(value) {
- if (value) {
- this._gl.disable(this._gl.RASTERIZER_DISCARD);
- }
- else {
- this._gl.enable(this._gl.RASTERIZER_DISCARD);
- }
- }
- /**
- * Directly set the WebGL Viewport
- * @param x defines the x coordinate of the viewport (in screen space)
- * @param y defines the y coordinate of the viewport (in screen space)
- * @param width defines the width of the viewport (in screen space)
- * @param height defines the height of the viewport (in screen space)
- * @returns the current viewport Object (if any) that is being replaced by this call. You can restore this viewport later on to go back to the original state
- */
- setDirectViewport(x, y, width, height) {
- const currentViewport = this._cachedViewport;
- this._cachedViewport = null;
- this._viewport(x, y, width, height);
- return currentViewport;
- }
- /**
- * Executes a scissor clear (ie. a clear on a specific portion of the screen)
- * @param x defines the x-coordinate of the bottom left corner of the clear rectangle
- * @param y defines the y-coordinate of the corner of the clear rectangle
- * @param width defines the width of the clear rectangle
- * @param height defines the height of the clear rectangle
- * @param clearColor defines the clear color
- */
- scissorClear(x, y, width, height, clearColor) {
- this.enableScissor(x, y, width, height);
- this.clear(clearColor, true, true, true);
- this.disableScissor();
- }
- /**
- * Enable scissor test on a specific rectangle (ie. render will only be executed on a specific portion of the screen)
- * @param x defines the x-coordinate of the bottom left corner of the clear rectangle
- * @param y defines the y-coordinate of the corner of the clear rectangle
- * @param width defines the width of the clear rectangle
- * @param height defines the height of the clear rectangle
- */
- enableScissor(x, y, width, height) {
- const gl = this._gl;
- // Change state
- gl.enable(gl.SCISSOR_TEST);
- gl.scissor(x, y, width, height);
- }
- /**
- * Disable previously set scissor test rectangle
- */
- disableScissor() {
- const gl = this._gl;
- gl.disable(gl.SCISSOR_TEST);
- }
- /**
- * @internal
- */
- _loadFileAsync(url, offlineProvider, useArrayBuffer) {
- return new Promise((resolve, reject) => {
- this._loadFile(url, (data) => {
- resolve(data);
- }, undefined, offlineProvider, useArrayBuffer, (request, exception) => {
- reject(exception);
- });
- });
- }
- /**
- * Gets the source code of the vertex shader associated with a specific webGL program
- * @param program defines the program to use
- * @returns a string containing the source code of the vertex shader associated with the program
- */
- getVertexShaderSource(program) {
- const shaders = this._gl.getAttachedShaders(program);
- if (!shaders) {
- return null;
- }
- return this._gl.getShaderSource(shaders[0]);
- }
- /**
- * Gets the source code of the fragment shader associated with a specific webGL program
- * @param program defines the program to use
- * @returns a string containing the source code of the fragment shader associated with the program
- */
- getFragmentShaderSource(program) {
- const shaders = this._gl.getAttachedShaders(program);
- if (!shaders) {
- return null;
- }
- return this._gl.getShaderSource(shaders[1]);
- }
- /**
- * Sets a depth stencil texture from a render target to the according uniform.
- * @param channel The texture channel
- * @param uniform The uniform to set
- * @param texture The render target texture containing the depth stencil texture to apply
- * @param name The texture name
- */
- setDepthStencilTexture(channel, uniform, texture, name) {
- if (channel === undefined) {
- return;
- }
- if (uniform) {
- this._boundUniforms[channel] = uniform;
- }
- if (!texture || !texture.depthStencilTexture) {
- this._setTexture(channel, null, undefined, undefined, name);
- }
- else {
- this._setTexture(channel, texture, false, true, name);
- }
- }
- /**
- * Sets a texture to the context from a postprocess
- * @param channel defines the channel to use
- * @param postProcess defines the source postprocess
- * @param name name of the channel
- */
- setTextureFromPostProcess(channel, postProcess, name) {
- let postProcessInput = null;
- if (postProcess) {
- if (postProcess._forcedOutputTexture) {
- postProcessInput = postProcess._forcedOutputTexture;
- }
- else if (postProcess._textures.data[postProcess._currentRenderTextureInd]) {
- postProcessInput = postProcess._textures.data[postProcess._currentRenderTextureInd];
- }
- }
- this._bindTexture(channel, postProcessInput?.texture ?? null, name);
- }
- /**
- * Binds the output of the passed in post process to the texture channel specified
- * @param channel The channel the texture should be bound to
- * @param postProcess The post process which's output should be bound
- * @param name name of the channel
- */
- setTextureFromPostProcessOutput(channel, postProcess, name) {
- this._bindTexture(channel, postProcess?._outputTexture?.texture ?? null, name);
- }
- /**
- * sets the object from which width and height will be taken from when getting render width and height
- * Will fallback to the gl object
- * @param dimensions the framebuffer width and height that will be used.
- */
- set framebufferDimensionsObject(dimensions) {
- this._framebufferDimensionsObject = dimensions;
- if (this._framebufferDimensionsObject) {
- this.onResizeObservable.notifyObservers(this);
- }
- }
- _rebuildBuffers() {
- // Index / Vertex
- for (const scene of this.scenes) {
- scene.resetCachedMaterial();
- scene._rebuildGeometries();
- }
- for (const scene of this._virtualScenes) {
- scene.resetCachedMaterial();
- scene._rebuildGeometries();
- }
- super._rebuildBuffers();
- }
- /**
- * Get Font size information
- * @param font font name
- * @returns an object containing ascent, height and descent
- */
- getFontOffset(font) {
- return GetFontOffset(font);
- }
- /** @internal */
- _renderFrame() {
- for (let index = 0; index < this._activeRenderLoops.length; index++) {
- const renderFunction = this._activeRenderLoops[index];
- renderFunction();
- }
- }
- _cancelFrame() {
- if (this.customAnimationFrameRequester) {
- if (this._frameHandler !== 0) {
- this._frameHandler = 0;
- const { cancelAnimationFrame } = this.customAnimationFrameRequester;
- if (cancelAnimationFrame) {
- cancelAnimationFrame(this.customAnimationFrameRequester.requestID);
- }
- }
- }
- else {
- super._cancelFrame();
- }
- }
- _renderLoop() {
- this._frameHandler = 0;
- if (!this._contextWasLost) {
- let shouldRender = true;
- if (this.isDisposed || (!this.renderEvenInBackground && this._windowIsBackground)) {
- shouldRender = false;
- }
- if (shouldRender) {
- // Start new frame
- this.beginFrame();
- // Child canvases
- if (!this._renderViews()) {
- // Main frame
- this._renderFrame();
- }
- // Present
- this.endFrame();
- }
- }
- if (this._frameHandler === 0) {
- // Register new frame
- if (this.customAnimationFrameRequester) {
- this.customAnimationFrameRequester.requestID = this._queueNewFrame(this.customAnimationFrameRequester.renderFunction || this._boundRenderFunction, this.customAnimationFrameRequester);
- this._frameHandler = this.customAnimationFrameRequester.requestID;
- }
- else {
- this._frameHandler = this._queueNewFrame(this._boundRenderFunction, this.getHostWindow());
- }
- }
- }
- /** @internal */
- _renderViews() {
- return false;
- }
- /**
- * Enters Pointerlock mode
- */
- enterPointerlock() {
- if (this._renderingCanvas) {
- RequestPointerlock(this._renderingCanvas);
- }
- }
- /**
- * Exits Pointerlock mode
- */
- exitPointerlock() {
- ExitPointerlock();
- }
- /**
- * Begin a new frame
- */
- beginFrame() {
- this._measureFps();
- super.beginFrame();
- }
- /**
- * Force a specific size of the canvas
- * @param width defines the new canvas' width
- * @param height defines the new canvas' height
- * @param forceSetSize true to force setting the sizes of the underlying canvas
- * @returns true if the size was changed
- */
- setSize(width, height, forceSetSize = false) {
- if (!this._renderingCanvas) {
- return false;
- }
- if (!super.setSize(width, height, forceSetSize)) {
- return false;
- }
- if (this.scenes) {
- for (let index = 0; index < this.scenes.length; index++) {
- const scene = this.scenes[index];
- for (let camIndex = 0; camIndex < scene.cameras.length; camIndex++) {
- const cam = scene.cameras[camIndex];
- cam._currentRenderId = 0;
- }
- }
- if (this.onResizeObservable.hasObservers()) {
- this.onResizeObservable.notifyObservers(this);
- }
- }
- return true;
- }
- _deletePipelineContext(pipelineContext) {
- const webGLPipelineContext = pipelineContext;
- if (webGLPipelineContext && webGLPipelineContext.program) {
- if (webGLPipelineContext.transformFeedback) {
- this.deleteTransformFeedback(webGLPipelineContext.transformFeedback);
- webGLPipelineContext.transformFeedback = null;
- }
- }
- super._deletePipelineContext(pipelineContext);
- }
- createShaderProgram(pipelineContext, vertexCode, fragmentCode, defines, context, transformFeedbackVaryings = null) {
- context = context || this._gl;
- this.onBeforeShaderCompilationObservable.notifyObservers(this);
- const program = super.createShaderProgram(pipelineContext, vertexCode, fragmentCode, defines, context, transformFeedbackVaryings);
- this.onAfterShaderCompilationObservable.notifyObservers(this);
- return program;
- }
- _createShaderProgram(pipelineContext, vertexShader, fragmentShader, context, transformFeedbackVaryings = null) {
- const shaderProgram = context.createProgram();
- pipelineContext.program = shaderProgram;
- if (!shaderProgram) {
- throw new Error("Unable to create program");
- }
- context.attachShader(shaderProgram, vertexShader);
- context.attachShader(shaderProgram, fragmentShader);
- if (this.webGLVersion > 1 && transformFeedbackVaryings) {
- const transformFeedback = this.createTransformFeedback();
- this.bindTransformFeedback(transformFeedback);
- this.setTranformFeedbackVaryings(shaderProgram, transformFeedbackVaryings);
- pipelineContext.transformFeedback = transformFeedback;
- }
- context.linkProgram(shaderProgram);
- if (this.webGLVersion > 1 && transformFeedbackVaryings) {
- this.bindTransformFeedback(null);
- }
- pipelineContext.context = context;
- pipelineContext.vertexShader = vertexShader;
- pipelineContext.fragmentShader = fragmentShader;
- if (!pipelineContext.isParallelCompiled) {
- this._finalizePipelineContext(pipelineContext);
- }
- return shaderProgram;
- }
- /**
- * @internal
- */
- _releaseTexture(texture) {
- super._releaseTexture(texture);
- }
- /**
- * @internal
- */
- _releaseRenderTargetWrapper(rtWrapper) {
- super._releaseRenderTargetWrapper(rtWrapper);
- // Set output texture of post process to null if the framebuffer has been released/disposed
- this.scenes.forEach((scene) => {
- scene.postProcesses.forEach((postProcess) => {
- if (postProcess._outputTexture === rtWrapper) {
- postProcess._outputTexture = null;
- }
- });
- scene.cameras.forEach((camera) => {
- camera._postProcesses.forEach((postProcess) => {
- if (postProcess) {
- if (postProcess._outputTexture === rtWrapper) {
- postProcess._outputTexture = null;
- }
- }
- });
- });
- });
- }
- /**
- * @internal
- * Rescales a texture
- * @param source input texture
- * @param destination destination texture
- * @param scene scene to use to render the resize
- * @param internalFormat format to use when resizing
- * @param onComplete callback to be called when resize has completed
- */
- _rescaleTexture(source, destination, scene, internalFormat, onComplete) {
- this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, this._gl.LINEAR);
- this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, this._gl.LINEAR);
- this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.CLAMP_TO_EDGE);
- this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._gl.CLAMP_TO_EDGE);
- const rtt = this.createRenderTargetTexture({
- width: destination.width,
- height: destination.height,
- }, {
- generateMipMaps: false,
- type: 0,
- samplingMode: 2,
- generateDepthBuffer: false,
- generateStencilBuffer: false,
- });
- if (!this._rescalePostProcess && Engine._RescalePostProcessFactory) {
- this._rescalePostProcess = Engine._RescalePostProcessFactory(this);
- }
- if (this._rescalePostProcess) {
- this._rescalePostProcess.externalTextureSamplerBinding = true;
- this._rescalePostProcess.getEffect().executeWhenCompiled(() => {
- this._rescalePostProcess.onApply = function (effect) {
- effect._bindTexture("textureSampler", source);
- };
- let hostingScene = scene;
- if (!hostingScene) {
- hostingScene = this.scenes[this.scenes.length - 1];
- }
- hostingScene.postProcessManager.directRender([this._rescalePostProcess], rtt, true);
- this._bindTextureDirectly(this._gl.TEXTURE_2D, destination, true);
- this._gl.copyTexImage2D(this._gl.TEXTURE_2D, 0, internalFormat, 0, 0, destination.width, destination.height, 0);
- this.unBindFramebuffer(rtt);
- rtt.dispose();
- if (onComplete) {
- onComplete();
- }
- });
- }
- }
- /**
- * Wraps an external web gl texture in a Babylon texture.
- * @param texture defines the external texture
- * @param hasMipMaps defines whether the external texture has mip maps (default: false)
- * @param samplingMode defines the sampling mode for the external texture (default: 3)
- * @param width defines the width for the external texture (default: 0)
- * @param height defines the height for the external texture (default: 0)
- * @returns the babylon internal texture
- */
- wrapWebGLTexture(texture, hasMipMaps = false, samplingMode = 3, width = 0, height = 0) {
- const hardwareTexture = new WebGLHardwareTexture(texture, this._gl);
- const internalTexture = new InternalTexture(this, InternalTextureSource.Unknown, true);
- internalTexture._hardwareTexture = hardwareTexture;
- internalTexture.baseWidth = width;
- internalTexture.baseHeight = height;
- internalTexture.width = width;
- internalTexture.height = height;
- internalTexture.isReady = true;
- internalTexture.useMipMaps = hasMipMaps;
- this.updateTextureSamplingMode(samplingMode, internalTexture);
- return internalTexture;
- }
- /**
- * @internal
- */
- _uploadImageToTexture(texture, image, faceIndex = 0, lod = 0) {
- const gl = this._gl;
- const textureType = this._getWebGLTextureType(texture.type);
- const format = this._getInternalFormat(texture.format);
- const internalFormat = this._getRGBABufferInternalSizedFormat(texture.type, format);
- const bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
- this._bindTextureDirectly(bindTarget, texture, true);
- this._unpackFlipY(texture.invertY);
- let target = gl.TEXTURE_2D;
- if (texture.isCube) {
- target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
- }
- gl.texImage2D(target, lod, internalFormat, format, textureType, image);
- this._bindTextureDirectly(bindTarget, null, true);
- }
- /**
- * Updates a depth texture Comparison Mode and Function.
- * If the comparison Function is equal to 0, the mode will be set to none.
- * Otherwise, this only works in webgl 2 and requires a shadow sampler in the shader.
- * @param texture The texture to set the comparison function for
- * @param comparisonFunction The comparison function to set, 0 if no comparison required
- */
- updateTextureComparisonFunction(texture, comparisonFunction) {
- if (this.webGLVersion === 1) {
- Logger.Error("WebGL 1 does not support texture comparison.");
- return;
- }
- const gl = this._gl;
- if (texture.isCube) {
- this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture, true);
- if (comparisonFunction === 0) {
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, 515);
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.NONE);
- }
- else {
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, comparisonFunction);
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
- }
- this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
- }
- else {
- this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
- if (comparisonFunction === 0) {
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, 515);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.NONE);
- }
- else {
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, comparisonFunction);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
- }
- this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
- }
- texture._comparisonFunction = comparisonFunction;
- }
- /**
- * Creates a webGL buffer to use with instantiation
- * @param capacity defines the size of the buffer
- * @returns the webGL buffer
- */
- createInstancesBuffer(capacity) {
- const buffer = this._gl.createBuffer();
- if (!buffer) {
- throw new Error("Unable to create instance buffer");
- }
- const result = new WebGLDataBuffer(buffer);
- result.capacity = capacity;
- this.bindArrayBuffer(result);
- this._gl.bufferData(this._gl.ARRAY_BUFFER, capacity, this._gl.DYNAMIC_DRAW);
- result.references = 1;
- return result;
- }
- /**
- * Delete a webGL buffer used with instantiation
- * @param buffer defines the webGL buffer to delete
- */
- deleteInstancesBuffer(buffer) {
- this._gl.deleteBuffer(buffer);
- }
- _clientWaitAsync(sync, flags = 0, intervalms = 10) {
- const gl = this._gl;
- return new Promise((resolve, reject) => {
- const check = () => {
- const res = gl.clientWaitSync(sync, flags, 0);
- if (res == gl.WAIT_FAILED) {
- reject();
- return;
- }
- if (res == gl.TIMEOUT_EXPIRED) {
- setTimeout(check, intervalms);
- return;
- }
- resolve();
- };
- check();
- });
- }
- /**
- * @internal
- */
- _readPixelsAsync(x, y, w, h, format, type, outputBuffer) {
- if (this._webGLVersion < 2) {
- throw new Error("_readPixelsAsync only work on WebGL2+");
- }
- const gl = this._gl;
- const buf = gl.createBuffer();
- gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);
- gl.bufferData(gl.PIXEL_PACK_BUFFER, outputBuffer.byteLength, gl.STREAM_READ);
- gl.readPixels(x, y, w, h, format, type, 0);
- gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
- const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
- if (!sync) {
- return null;
- }
- gl.flush();
- return this._clientWaitAsync(sync, 0, 10).then(() => {
- gl.deleteSync(sync);
- gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);
- gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, outputBuffer);
- gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
- gl.deleteBuffer(buf);
- return outputBuffer;
- });
- }
- dispose() {
- // Rescale PP
- if (this._rescalePostProcess) {
- this._rescalePostProcess.dispose();
- }
- _CommonDispose(this, this._renderingCanvas);
- super.dispose();
- }
- }
- // Const statics
- /** Defines that alpha blending is disabled */
- Engine.ALPHA_DISABLE = 0;
- /** Defines that alpha blending to SRC ALPHA * SRC + DEST */
- Engine.ALPHA_ADD = 1;
- /** Defines that alpha blending to SRC ALPHA * SRC + (1 - SRC ALPHA) * DEST */
- Engine.ALPHA_COMBINE = 2;
- /** Defines that alpha blending to DEST - SRC * DEST */
- Engine.ALPHA_SUBTRACT = 3;
- /** Defines that alpha blending to SRC * DEST */
- Engine.ALPHA_MULTIPLY = 4;
- /** Defines that alpha blending to SRC ALPHA * SRC + (1 - SRC) * DEST */
- Engine.ALPHA_MAXIMIZED = 5;
- /** Defines that alpha blending to SRC + DEST */
- Engine.ALPHA_ONEONE = 6;
- /** Defines that alpha blending to SRC + (1 - SRC ALPHA) * DEST */
- Engine.ALPHA_PREMULTIPLIED = 7;
- /**
- * Defines that alpha blending to SRC + (1 - SRC ALPHA) * DEST
- * Alpha will be set to (1 - SRC ALPHA) * DEST ALPHA
- */
- Engine.ALPHA_PREMULTIPLIED_PORTERDUFF = 8;
- /** Defines that alpha blending to CST * SRC + (1 - CST) * DEST */
- Engine.ALPHA_INTERPOLATE = 9;
- /**
- * Defines that alpha blending to SRC + (1 - SRC) * DEST
- * Alpha will be set to SRC ALPHA + (1 - SRC ALPHA) * DEST ALPHA
- */
- Engine.ALPHA_SCREENMODE = 10;
- /** Defines that the resource is not delayed*/
- Engine.DELAYLOADSTATE_NONE = 0;
- /** Defines that the resource was successfully delay loaded */
- Engine.DELAYLOADSTATE_LOADED = 1;
- /** Defines that the resource is currently delay loading */
- Engine.DELAYLOADSTATE_LOADING = 2;
- /** Defines that the resource is delayed and has not started loading */
- Engine.DELAYLOADSTATE_NOTLOADED = 4;
- // Depht or Stencil test Constants.
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will never pass. i.e. Nothing will be drawn */
- Engine.NEVER = 512;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will always pass. i.e. Pixels will be drawn in the order they are drawn */
- Engine.ALWAYS = 519;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is less than the stored value */
- Engine.LESS = 513;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is equals to the stored value */
- Engine.EQUAL = 514;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is less than or equal to the stored value */
- Engine.LEQUAL = 515;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than the stored value */
- Engine.GREATER = 516;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value */
- Engine.GEQUAL = 518;
- /** Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value */
- Engine.NOTEQUAL = 517;
- // Stencil Actions Constants.
- /** Passed to stencilOperation to specify that stencil value must be kept */
- Engine.KEEP = 7680;
- /** Passed to stencilOperation to specify that stencil value must be replaced */
- Engine.REPLACE = 7681;
- /** Passed to stencilOperation to specify that stencil value must be incremented */
- Engine.INCR = 7682;
- /** Passed to stencilOperation to specify that stencil value must be decremented */
- Engine.DECR = 7683;
- /** Passed to stencilOperation to specify that stencil value must be inverted */
- Engine.INVERT = 5386;
- /** Passed to stencilOperation to specify that stencil value must be incremented with wrapping */
- Engine.INCR_WRAP = 34055;
- /** Passed to stencilOperation to specify that stencil value must be decremented with wrapping */
- Engine.DECR_WRAP = 34056;
- /** Texture is not repeating outside of 0..1 UVs */
- Engine.TEXTURE_CLAMP_ADDRESSMODE = 0;
- /** Texture is repeating outside of 0..1 UVs */
- Engine.TEXTURE_WRAP_ADDRESSMODE = 1;
- /** Texture is repeating and mirrored */
- Engine.TEXTURE_MIRROR_ADDRESSMODE = 2;
- /** ALPHA */
- Engine.TEXTUREFORMAT_ALPHA = 0;
- /** LUMINANCE */
- Engine.TEXTUREFORMAT_LUMINANCE = 1;
- /** LUMINANCE_ALPHA */
- Engine.TEXTUREFORMAT_LUMINANCE_ALPHA = 2;
- /** RGB */
- Engine.TEXTUREFORMAT_RGB = 4;
- /** RGBA */
- Engine.TEXTUREFORMAT_RGBA = 5;
- /** RED */
- Engine.TEXTUREFORMAT_RED = 6;
- /** RED (2nd reference) */
- Engine.TEXTUREFORMAT_R = 6;
- /** RG */
- Engine.TEXTUREFORMAT_RG = 7;
- /** RED_INTEGER */
- Engine.TEXTUREFORMAT_RED_INTEGER = 8;
- /** RED_INTEGER (2nd reference) */
- Engine.TEXTUREFORMAT_R_INTEGER = 8;
- /** RG_INTEGER */
- Engine.TEXTUREFORMAT_RG_INTEGER = 9;
- /** RGB_INTEGER */
- Engine.TEXTUREFORMAT_RGB_INTEGER = 10;
- /** RGBA_INTEGER */
- Engine.TEXTUREFORMAT_RGBA_INTEGER = 11;
- /** UNSIGNED_BYTE */
- Engine.TEXTURETYPE_UNSIGNED_BYTE = 0;
- /** UNSIGNED_BYTE (2nd reference) */
- Engine.TEXTURETYPE_UNSIGNED_INT = 0;
- /** FLOAT */
- Engine.TEXTURETYPE_FLOAT = 1;
- /** HALF_FLOAT */
- Engine.TEXTURETYPE_HALF_FLOAT = 2;
- /** BYTE */
- Engine.TEXTURETYPE_BYTE = 3;
- /** SHORT */
- Engine.TEXTURETYPE_SHORT = 4;
- /** UNSIGNED_SHORT */
- Engine.TEXTURETYPE_UNSIGNED_SHORT = 5;
- /** INT */
- Engine.TEXTURETYPE_INT = 6;
- /** UNSIGNED_INT */
- Engine.TEXTURETYPE_UNSIGNED_INTEGER = 7;
- /** UNSIGNED_SHORT_4_4_4_4 */
- Engine.TEXTURETYPE_UNSIGNED_SHORT_4_4_4_4 = 8;
- /** UNSIGNED_SHORT_5_5_5_1 */
- Engine.TEXTURETYPE_UNSIGNED_SHORT_5_5_5_1 = 9;
- /** UNSIGNED_SHORT_5_6_5 */
- Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5 = 10;
- /** UNSIGNED_INT_2_10_10_10_REV */
- Engine.TEXTURETYPE_UNSIGNED_INT_2_10_10_10_REV = 11;
- /** UNSIGNED_INT_24_8 */
- Engine.TEXTURETYPE_UNSIGNED_INT_24_8 = 12;
- /** UNSIGNED_INT_10F_11F_11F_REV */
- Engine.TEXTURETYPE_UNSIGNED_INT_10F_11F_11F_REV = 13;
- /** UNSIGNED_INT_5_9_9_9_REV */
- Engine.TEXTURETYPE_UNSIGNED_INT_5_9_9_9_REV = 14;
- /** FLOAT_32_UNSIGNED_INT_24_8_REV */
- Engine.TEXTURETYPE_FLOAT_32_UNSIGNED_INT_24_8_REV = 15;
- /** nearest is mag = nearest and min = nearest and mip = none */
- Engine.TEXTURE_NEAREST_SAMPLINGMODE = 1;
- /** Bilinear is mag = linear and min = linear and mip = nearest */
- Engine.TEXTURE_BILINEAR_SAMPLINGMODE = 2;
- /** Trilinear is mag = linear and min = linear and mip = linear */
- Engine.TEXTURE_TRILINEAR_SAMPLINGMODE = 3;
- /** nearest is mag = nearest and min = nearest and mip = linear */
- Engine.TEXTURE_NEAREST_NEAREST_MIPLINEAR = 8;
- /** Bilinear is mag = linear and min = linear and mip = nearest */
- Engine.TEXTURE_LINEAR_LINEAR_MIPNEAREST = 11;
- /** Trilinear is mag = linear and min = linear and mip = linear */
- Engine.TEXTURE_LINEAR_LINEAR_MIPLINEAR = 3;
- /** mag = nearest and min = nearest and mip = nearest */
- Engine.TEXTURE_NEAREST_NEAREST_MIPNEAREST = 4;
- /** mag = nearest and min = linear and mip = nearest */
- Engine.TEXTURE_NEAREST_LINEAR_MIPNEAREST = 5;
- /** mag = nearest and min = linear and mip = linear */
- Engine.TEXTURE_NEAREST_LINEAR_MIPLINEAR = 6;
- /** mag = nearest and min = linear and mip = none */
- Engine.TEXTURE_NEAREST_LINEAR = 7;
- /** mag = nearest and min = nearest and mip = none */
- Engine.TEXTURE_NEAREST_NEAREST = 1;
- /** mag = linear and min = nearest and mip = nearest */
- Engine.TEXTURE_LINEAR_NEAREST_MIPNEAREST = 9;
- /** mag = linear and min = nearest and mip = linear */
- Engine.TEXTURE_LINEAR_NEAREST_MIPLINEAR = 10;
- /** mag = linear and min = linear and mip = none */
- Engine.TEXTURE_LINEAR_LINEAR = 2;
- /** mag = linear and min = nearest and mip = none */
- Engine.TEXTURE_LINEAR_NEAREST = 12;
- /** Explicit coordinates mode */
- Engine.TEXTURE_EXPLICIT_MODE = 0;
- /** Spherical coordinates mode */
- Engine.TEXTURE_SPHERICAL_MODE = 1;
- /** Planar coordinates mode */
- Engine.TEXTURE_PLANAR_MODE = 2;
- /** Cubic coordinates mode */
- Engine.TEXTURE_CUBIC_MODE = 3;
- /** Projection coordinates mode */
- Engine.TEXTURE_PROJECTION_MODE = 4;
- /** Skybox coordinates mode */
- Engine.TEXTURE_SKYBOX_MODE = 5;
- /** Inverse Cubic coordinates mode */
- Engine.TEXTURE_INVCUBIC_MODE = 6;
- /** Equirectangular coordinates mode */
- Engine.TEXTURE_EQUIRECTANGULAR_MODE = 7;
- /** Equirectangular Fixed coordinates mode */
- Engine.TEXTURE_FIXED_EQUIRECTANGULAR_MODE = 8;
- /** Equirectangular Fixed Mirrored coordinates mode */
- Engine.TEXTURE_FIXED_EQUIRECTANGULAR_MIRRORED_MODE = 9;
- // Texture rescaling mode
- /** Defines that texture rescaling will use a floor to find the closer power of 2 size */
- Engine.SCALEMODE_FLOOR = 1;
- /** Defines that texture rescaling will look for the nearest power of 2 size */
- Engine.SCALEMODE_NEAREST = 2;
- /** Defines that texture rescaling will use a ceil to find the closer power of 2 size */
- Engine.SCALEMODE_CEILING = 3;
- //# sourceMappingURL=engine.js.map
|