@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
208 lines (207 loc) • 10.6 kB
JavaScript
import { InternalTexture } from "../../Materials/Textures/internalTexture.js";
import { Logger } from "../../Misc/logger.js";
import { ThinEngine } from "../thinEngine.js";
import { WebGLRenderTargetWrapper } from "../WebGL/webGLRenderTargetWrapper.js";
import { HasStencilAspect } from "../../Materials/Textures/textureHelper.functions.js";
import "../AbstractEngine/abstractEngine.texture.js";
ThinEngine.prototype._createHardwareRenderTargetWrapper = function (isMulti, isCube, size) {
const rtWrapper = new WebGLRenderTargetWrapper(isMulti, isCube, size, this, this._gl);
this._renderTargetWrapperCache.push(rtWrapper);
return rtWrapper;
};
ThinEngine.prototype.createRenderTargetTexture = function (size, options) {
const rtWrapper = this._createHardwareRenderTargetWrapper(false, false, size);
let generateDepthBuffer = true;
let generateStencilBuffer = false;
let noColorAttachment = false;
let colorAttachment = undefined;
let samples = 1;
let label = undefined;
if (options !== undefined && typeof options === "object") {
generateDepthBuffer = options.generateDepthBuffer ?? true;
generateStencilBuffer = !!options.generateStencilBuffer;
noColorAttachment = !!options.noColorAttachment;
colorAttachment = options.colorAttachment;
samples = options.samples ?? 1;
label = options.label;
}
const texture = colorAttachment || (noColorAttachment ? null : this._createInternalTexture(size, options, true, 5 /* InternalTextureSource.RenderTarget */));
const width = size.width || size;
const height = size.height || size;
const currentFrameBuffer = this._currentFramebuffer;
const gl = this._gl;
// Create the framebuffer
const framebuffer = gl.createFramebuffer();
this._bindUnboundFramebuffer(framebuffer);
rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, width, height);
// No need to rebind on every frame
if (texture && !texture.is2DArray && !texture.is3D) {
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._hardwareTexture.underlyingResource, 0);
}
this._bindUnboundFramebuffer(currentFrameBuffer);
rtWrapper.label = label ?? "RenderTargetWrapper";
rtWrapper._framebuffer = framebuffer;
rtWrapper._generateDepthBuffer = generateDepthBuffer;
rtWrapper._generateStencilBuffer = generateStencilBuffer;
rtWrapper.setTextures(texture);
if (!colorAttachment) {
this.updateRenderTargetTextureSampleCount(rtWrapper, samples);
}
else {
rtWrapper._samples = colorAttachment.samples;
if (colorAttachment.samples > 1) {
const msaaRenderBuffer = colorAttachment._hardwareTexture.getMSAARenderBuffer(0);
rtWrapper._MSAAFramebuffer = gl.createFramebuffer();
this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msaaRenderBuffer);
this._bindUnboundFramebuffer(null);
}
}
return rtWrapper;
};
ThinEngine.prototype._createDepthStencilTexture = function (size, options, rtWrapper) {
const gl = this._gl;
const layers = size.layers || 0;
const depth = size.depth || 0;
let target = gl.TEXTURE_2D;
if (layers !== 0) {
target = gl.TEXTURE_2D_ARRAY;
}
else if (depth !== 0) {
target = gl.TEXTURE_3D;
}
const internalTexture = new InternalTexture(this, 12 /* InternalTextureSource.DepthStencil */);
internalTexture.label = options.label;
if (!this._caps.depthTextureExtension) {
Logger.Error("Depth texture is not supported by your browser or hardware.");
return internalTexture;
}
const internalOptions = {
bilinearFiltering: false,
comparisonFunction: 0,
generateStencil: false,
...options,
};
this._bindTextureDirectly(target, internalTexture, true);
this._setupDepthStencilTexture(internalTexture, size, internalOptions.comparisonFunction === 0 ? false : internalOptions.bilinearFiltering, internalOptions.comparisonFunction, internalOptions.samples);
if (internalOptions.depthTextureFormat !== undefined) {
if (internalOptions.depthTextureFormat !== 15 &&
internalOptions.depthTextureFormat !== 16 &&
internalOptions.depthTextureFormat !== 17 &&
internalOptions.depthTextureFormat !== 13 &&
internalOptions.depthTextureFormat !== 14 &&
internalOptions.depthTextureFormat !== 18) {
Logger.Error(`Depth texture ${internalOptions.depthTextureFormat} format is not supported.`);
return internalTexture;
}
internalTexture.format = internalOptions.depthTextureFormat;
}
else {
internalTexture.format = internalOptions.generateStencil ? 13 : 16;
}
const hasStencil = HasStencilAspect(internalTexture.format);
const type = this._getWebGLTextureTypeFromDepthTextureFormat(internalTexture.format);
const format = hasStencil ? gl.DEPTH_STENCIL : gl.DEPTH_COMPONENT;
const internalFormat = this._getInternalFormatFromDepthTextureFormat(internalTexture.format, true, hasStencil);
if (internalTexture.is2DArray) {
gl.texImage3D(target, 0, internalFormat, internalTexture.width, internalTexture.height, layers, 0, format, type, null);
}
else if (internalTexture.is3D) {
gl.texImage3D(target, 0, internalFormat, internalTexture.width, internalTexture.height, depth, 0, format, type, null);
}
else {
gl.texImage2D(target, 0, internalFormat, internalTexture.width, internalTexture.height, 0, format, type, null);
}
this._bindTextureDirectly(target, null);
this._internalTexturesCache.push(internalTexture);
if (rtWrapper._depthStencilBuffer) {
gl.deleteRenderbuffer(rtWrapper._depthStencilBuffer);
rtWrapper._depthStencilBuffer = null;
}
this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer ?? rtWrapper._framebuffer);
rtWrapper._generateStencilBuffer = hasStencil;
rtWrapper._depthStencilTextureWithStencil = hasStencil;
rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(rtWrapper._generateStencilBuffer, rtWrapper._generateDepthBuffer, rtWrapper.width, rtWrapper.height, rtWrapper.samples, internalTexture.format);
this._bindUnboundFramebuffer(null);
return internalTexture;
};
ThinEngine.prototype.updateRenderTargetTextureSampleCount = function (rtWrapper, samples) {
if (this.webGLVersion < 2 || !rtWrapper) {
return 1;
}
if (rtWrapper.samples === samples) {
return samples;
}
const gl = this._gl;
samples = Math.min(samples, this.getCaps().maxMSAASamples);
// Dispose previous render buffers
if (rtWrapper._depthStencilBuffer) {
gl.deleteRenderbuffer(rtWrapper._depthStencilBuffer);
rtWrapper._depthStencilBuffer = null;
}
if (rtWrapper._MSAAFramebuffer) {
gl.deleteFramebuffer(rtWrapper._MSAAFramebuffer);
rtWrapper._MSAAFramebuffer = null;
}
const hardwareTexture = rtWrapper.texture?._hardwareTexture;
hardwareTexture?.releaseMSAARenderBuffers();
if (rtWrapper.texture && samples > 1 && typeof gl.renderbufferStorageMultisample === "function") {
const framebuffer = gl.createFramebuffer();
if (!framebuffer) {
throw new Error("Unable to create multi sampled framebuffer");
}
rtWrapper._MSAAFramebuffer = framebuffer;
this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer);
const colorRenderbuffer = this._createRenderBuffer(rtWrapper.texture.width, rtWrapper.texture.height, samples, -1 /* not used */, this._getRGBABufferInternalSizedFormat(rtWrapper.texture.type, rtWrapper.texture.format, rtWrapper.texture._useSRGBBuffer), gl.COLOR_ATTACHMENT0, false);
if (!colorRenderbuffer) {
throw new Error("Unable to create multi sampled framebuffer");
}
hardwareTexture?.addMSAARenderBuffer(colorRenderbuffer);
}
this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer ?? rtWrapper._framebuffer);
if (rtWrapper.texture) {
rtWrapper.texture.samples = samples;
}
rtWrapper._samples = samples;
const depthFormat = rtWrapper._depthStencilTexture ? rtWrapper._depthStencilTexture.format : undefined;
rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(rtWrapper._generateStencilBuffer, rtWrapper._generateDepthBuffer, rtWrapper.width, rtWrapper.height, samples, depthFormat);
this._bindUnboundFramebuffer(null);
return samples;
};
ThinEngine.prototype._setupDepthStencilTexture = function (internalTexture, size, bilinearFiltering, comparisonFunction, samples = 1) {
const width = size.width ?? size;
const height = size.height ?? size;
const layers = size.layers || 0;
const depth = size.depth || 0;
internalTexture.baseWidth = width;
internalTexture.baseHeight = height;
internalTexture.width = width;
internalTexture.height = height;
internalTexture.is2DArray = layers > 0;
internalTexture.depth = layers || depth;
internalTexture.isReady = true;
internalTexture.samples = samples;
internalTexture.generateMipMaps = false;
internalTexture.samplingMode = bilinearFiltering ? 2 : 1;
internalTexture.type = 0;
internalTexture._comparisonFunction = comparisonFunction;
const gl = this._gl;
const target = this._getTextureTarget(internalTexture);
const samplingParameters = this._getSamplingParameters(internalTexture.samplingMode, false);
gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, samplingParameters.mag);
gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, samplingParameters.min);
gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// TEXTURE_COMPARE_FUNC/MODE are only availble in WebGL2.
if (this.webGLVersion > 1) {
if (comparisonFunction === 0) {
gl.texParameteri(target, gl.TEXTURE_COMPARE_FUNC, 515);
gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.NONE);
}
else {
gl.texParameteri(target, gl.TEXTURE_COMPARE_FUNC, comparisonFunction);
gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
}
}
};
//# sourceMappingURL=engine.renderTarget.js.map