|
@@ -1920,6 +1920,60 @@
|
|
|
|
|
|
WebGLRenderTarget.prototype.isWebGLRenderTarget = true;
|
|
|
|
|
|
+ class WebGLMultipleRenderTargets extends WebGLRenderTarget {
|
|
|
+ constructor(width, height, count) {
|
|
|
+ super(width, height);
|
|
|
+ const texture = this.texture;
|
|
|
+ this.texture = [];
|
|
|
+
|
|
|
+ for (let i = 0; i < count; i++) {
|
|
|
+ this.texture[i] = texture.clone();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ setSize(width, height, depth = 1) {
|
|
|
+ if (this.width !== width || this.height !== height || this.depth !== depth) {
|
|
|
+ this.width = width;
|
|
|
+ this.height = height;
|
|
|
+ this.depth = depth;
|
|
|
+
|
|
|
+ for (let i = 0, il = this.texture.length; i < il; i++) {
|
|
|
+ this.texture[i].image.width = width;
|
|
|
+ this.texture[i].image.height = height;
|
|
|
+ this.texture[i].image.depth = depth;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.viewport.set(0, 0, width, height);
|
|
|
+ this.scissor.set(0, 0, width, height);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ copy(source) {
|
|
|
+ this.dispose();
|
|
|
+ this.width = source.width;
|
|
|
+ this.height = source.height;
|
|
|
+ this.depth = source.depth;
|
|
|
+ this.viewport.set(0, 0, this.width, this.height);
|
|
|
+ this.scissor.set(0, 0, this.width, this.height);
|
|
|
+ this.depthBuffer = source.depthBuffer;
|
|
|
+ this.stencilBuffer = source.stencilBuffer;
|
|
|
+ this.depthTexture = source.depthTexture;
|
|
|
+ this.texture.length = 0;
|
|
|
+
|
|
|
+ for (let i = 0, il = source.texture.length; i < il; i++) {
|
|
|
+ this.texture[i] = source.texture[i].clone();
|
|
|
+ }
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ WebGLMultipleRenderTargets.prototype.isWebGLMultipleRenderTargets = true;
|
|
|
+
|
|
|
class WebGLMultisampleRenderTarget extends WebGLRenderTarget {
|
|
|
constructor(width, height, options) {
|
|
|
super(width, height, options);
|
|
@@ -11124,6 +11178,7 @@
|
|
|
precision = maxPrecision;
|
|
|
}
|
|
|
|
|
|
+ const drawBuffers = isWebGL2 || extensions.has('WEBGL_draw_buffers');
|
|
|
const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
|
|
|
const maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
|
|
|
const maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
|
|
@@ -11139,6 +11194,7 @@
|
|
|
const maxSamples = isWebGL2 ? gl.getParameter(gl.MAX_SAMPLES) : 0;
|
|
|
return {
|
|
|
isWebGL2: isWebGL2,
|
|
|
+ drawBuffers: drawBuffers,
|
|
|
getMaxAnisotropy: getMaxAnisotropy,
|
|
|
getMaxPrecision: getMaxPrecision,
|
|
|
precision: precision,
|
|
@@ -14669,7 +14725,11 @@
|
|
|
currentBoundFramebuffers[gl.DRAW_FRAMEBUFFER] = framebuffer;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
+
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
function useProgram(program) {
|
|
@@ -15220,7 +15280,6 @@
|
|
|
const renderTarget = event.target;
|
|
|
renderTarget.removeEventListener('dispose', onRenderTargetDispose);
|
|
|
deallocateRenderTarget(renderTarget);
|
|
|
- info.memory.textures--;
|
|
|
} //
|
|
|
|
|
|
|
|
@@ -15241,6 +15300,8 @@
|
|
|
|
|
|
if (textureProperties.__webglTexture !== undefined) {
|
|
|
_gl.deleteTexture(textureProperties.__webglTexture);
|
|
|
+
|
|
|
+ info.memory.textures--;
|
|
|
}
|
|
|
|
|
|
if (renderTarget.depthTexture) {
|
|
@@ -15262,6 +15323,20 @@
|
|
|
if (renderTargetProperties.__webglDepthRenderbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer);
|
|
|
}
|
|
|
|
|
|
+ if (renderTarget.isWebGLMultipleRenderTargets) {
|
|
|
+ for (let i = 0, il = texture.length; i < il; i++) {
|
|
|
+ const attachmentProperties = properties.get(texture[i]);
|
|
|
+
|
|
|
+ if (attachmentProperties.__webglTexture) {
|
|
|
+ _gl.deleteTexture(attachmentProperties.__webglTexture);
|
|
|
+
|
|
|
+ info.memory.textures--;
|
|
|
+ }
|
|
|
+
|
|
|
+ properties.remove(texture[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
properties.remove(texture);
|
|
|
properties.remove(renderTarget);
|
|
|
} //
|
|
@@ -15643,8 +15718,7 @@
|
|
|
// Setup storage for target texture and bind it to correct framebuffer
|
|
|
|
|
|
|
|
|
- function setupFrameBufferTexture(framebuffer, renderTarget, attachment, textureTarget) {
|
|
|
- const texture = renderTarget.texture;
|
|
|
+ function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget) {
|
|
|
const glFormat = utils.convert(texture.format);
|
|
|
const glType = utils.convert(texture.type);
|
|
|
const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
@@ -15699,7 +15773,8 @@
|
|
|
|
|
|
_gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
|
|
|
} else {
|
|
|
- const texture = renderTarget.texture;
|
|
|
+ // Use the first texture for MRT so far
|
|
|
+ const texture = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture[0] : renderTarget.texture;
|
|
|
const glFormat = utils.convert(texture.format);
|
|
|
const glType = utils.convert(texture.type);
|
|
|
const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
@@ -15779,10 +15854,15 @@
|
|
|
const renderTargetProperties = properties.get(renderTarget);
|
|
|
const textureProperties = properties.get(texture);
|
|
|
renderTarget.addEventListener('dispose', onRenderTargetDispose);
|
|
|
- textureProperties.__webglTexture = _gl.createTexture();
|
|
|
- textureProperties.__version = texture.version;
|
|
|
- info.memory.textures++;
|
|
|
+
|
|
|
+ if (renderTarget.isWebGLMultipleRenderTargets !== true) {
|
|
|
+ textureProperties.__webglTexture = _gl.createTexture();
|
|
|
+ textureProperties.__version = texture.version;
|
|
|
+ info.memory.textures++;
|
|
|
+ }
|
|
|
+
|
|
|
const isCube = renderTarget.isWebGLCubeRenderTarget === true;
|
|
|
+ const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true;
|
|
|
const isMultisample = renderTarget.isWebGLMultisampleRenderTarget === true;
|
|
|
const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray;
|
|
|
const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; // Handles WebGL2 RGBFormat fallback - #18858
|
|
@@ -15802,7 +15882,22 @@
|
|
|
} else {
|
|
|
renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
|
|
|
|
|
|
- if (isMultisample) {
|
|
|
+ if (isMultipleRenderTargets) {
|
|
|
+ if (capabilities.drawBuffers) {
|
|
|
+ const textures = renderTarget.texture;
|
|
|
+
|
|
|
+ for (let i = 0, il = textures.length; i < il; i++) {
|
|
|
+ const attachmentProperties = properties.get(textures[i]);
|
|
|
+
|
|
|
+ if (attachmentProperties.__webglTexture === undefined) {
|
|
|
+ attachmentProperties.__webglTexture = _gl.createTexture();
|
|
|
+ info.memory.textures++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.warn('THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.');
|
|
|
+ }
|
|
|
+ } else if (isMultisample) {
|
|
|
if (isWebGL2) {
|
|
|
renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
|
|
|
renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
|
|
@@ -15840,7 +15935,7 @@
|
|
|
setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, supportsMips);
|
|
|
|
|
|
for (let i = 0; i < 6; i++) {
|
|
|
- setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);
|
|
|
+ setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);
|
|
|
}
|
|
|
|
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
@@ -15848,6 +15943,22 @@
|
|
|
}
|
|
|
|
|
|
state.bindTexture(_gl.TEXTURE_CUBE_MAP, null);
|
|
|
+ } else if (isMultipleRenderTargets) {
|
|
|
+ const textures = renderTarget.texture;
|
|
|
+
|
|
|
+ for (let i = 0, il = textures.length; i < il; i++) {
|
|
|
+ const attachment = textures[i];
|
|
|
+ const attachmentProperties = properties.get(attachment);
|
|
|
+ state.bindTexture(_gl.TEXTURE_2D, attachmentProperties.__webglTexture);
|
|
|
+ setTextureParameters(_gl.TEXTURE_2D, attachment, supportsMips);
|
|
|
+ setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D);
|
|
|
+
|
|
|
+ if (textureNeedsGenerateMipmaps(attachment, supportsMips)) {
|
|
|
+ generateMipmap(_gl.TEXTURE_2D, attachment, renderTarget.width, renderTarget.height);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ state.bindTexture(_gl.TEXTURE_2D, null);
|
|
|
} else {
|
|
|
let glTextureType = _gl.TEXTURE_2D;
|
|
|
|
|
@@ -15863,7 +15974,7 @@
|
|
|
|
|
|
state.bindTexture(glTextureType, textureProperties.__webglTexture);
|
|
|
setTextureParameters(glTextureType, texture, supportsMips);
|
|
|
- setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, glTextureType);
|
|
|
+ setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType);
|
|
|
|
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
|
generateMipmap(_gl.TEXTURE_2D, texture, renderTarget.width, renderTarget.height);
|
|
@@ -15879,17 +15990,21 @@
|
|
|
}
|
|
|
|
|
|
function updateRenderTargetMipmap(renderTarget) {
|
|
|
- const texture = renderTarget.texture;
|
|
|
const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2;
|
|
|
+ const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture];
|
|
|
|
|
|
- if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
|
- const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
|
|
|
+ for (let i = 0, il = textures.length; i < il; i++) {
|
|
|
+ const texture = textures[i];
|
|
|
|
|
|
- const webglTexture = properties.get(texture).__webglTexture;
|
|
|
+ if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
|
+ const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
|
|
|
+
|
|
|
+ const webglTexture = properties.get(texture).__webglTexture;
|
|
|
|
|
|
- state.bindTexture(target, webglTexture);
|
|
|
- generateMipmap(target, texture, renderTarget.width, renderTarget.height);
|
|
|
- state.bindTexture(target, null);
|
|
|
+ state.bindTexture(target, webglTexture);
|
|
|
+ generateMipmap(target, texture, renderTarget.width, renderTarget.height);
|
|
|
+ state.bindTexture(target, null);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -17245,7 +17360,9 @@
|
|
|
|
|
|
const _scissor = new Vector4(0, 0, _width, _height);
|
|
|
|
|
|
- let _scissorTest = false; // frustum
|
|
|
+ let _scissorTest = false; //
|
|
|
+
|
|
|
+ const _currentDrawBuffers = []; // frustum
|
|
|
|
|
|
const _frustum = new Frustum(); // clipping
|
|
|
|
|
@@ -17345,6 +17462,7 @@
|
|
|
extensions.init(capabilities);
|
|
|
utils = new WebGLUtils(_gl, extensions, capabilities);
|
|
|
state = new WebGLState(_gl, extensions, capabilities);
|
|
|
+ _currentDrawBuffers[0] = _gl.BACK;
|
|
|
info = new WebGLInfo(_gl);
|
|
|
properties = new WebGLProperties();
|
|
|
textures = new WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info);
|
|
@@ -18390,7 +18508,47 @@
|
|
|
_currentScissorTest = _scissorTest;
|
|
|
}
|
|
|
|
|
|
- state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
|
|
|
+ const framebufferBound = state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
|
|
|
+
|
|
|
+ if (framebufferBound && capabilities.drawBuffers) {
|
|
|
+ let needsUpdate = false;
|
|
|
+
|
|
|
+ if (renderTarget) {
|
|
|
+ if (renderTarget.isWebGLMultipleRenderTargets) {
|
|
|
+ const textures = renderTarget.texture;
|
|
|
+
|
|
|
+ if (_currentDrawBuffers.length !== textures.length || _currentDrawBuffers[0] !== _gl.COLOR_ATTACHMENT0) {
|
|
|
+ for (let i = 0, il = textures.length; i < il; i++) {
|
|
|
+ _currentDrawBuffers[i] = _gl.COLOR_ATTACHMENT0 + i;
|
|
|
+ }
|
|
|
+
|
|
|
+ _currentDrawBuffers.length = textures.length;
|
|
|
+ needsUpdate = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (_currentDrawBuffers.length !== 1 || _currentDrawBuffers[0] !== _gl.COLOR_ATTACHMENT0) {
|
|
|
+ _currentDrawBuffers[0] = _gl.COLOR_ATTACHMENT0;
|
|
|
+ _currentDrawBuffers.length = 1;
|
|
|
+ needsUpdate = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (_currentDrawBuffers.length !== 1 || _currentDrawBuffers[0] !== _gl.BACK) {
|
|
|
+ _currentDrawBuffers[0] = _gl.BACK;
|
|
|
+ _currentDrawBuffers.length = 1;
|
|
|
+ needsUpdate = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (needsUpdate) {
|
|
|
+ if (capabilities.isWebGL2) {
|
|
|
+ _gl.drawBuffers(_currentDrawBuffers);
|
|
|
+ } else {
|
|
|
+ extensions.get('WEBGL_draw_buffers').drawBuffersWEBGL(_currentDrawBuffers);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
state.viewport(_currentViewport);
|
|
|
state.scissor(_currentScissor);
|
|
|
state.setScissorTest(_currentScissorTest);
|
|
@@ -35920,6 +36078,7 @@
|
|
|
exports.VideoTexture = VideoTexture;
|
|
|
exports.WebGL1Renderer = WebGL1Renderer;
|
|
|
exports.WebGLCubeRenderTarget = WebGLCubeRenderTarget;
|
|
|
+ exports.WebGLMultipleRenderTargets = WebGLMultipleRenderTargets;
|
|
|
exports.WebGLMultisampleRenderTarget = WebGLMultisampleRenderTarget;
|
|
|
exports.WebGLRenderTarget = WebGLRenderTarget;
|
|
|
exports.WebGLRenderTargetCube = WebGLRenderTargetCube;
|