|
@@ -9,6 +9,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
const maxCubemapSize = capabilities.maxCubemapSize;
|
|
const maxCubemapSize = capabilities.maxCubemapSize;
|
|
const maxTextureSize = capabilities.maxTextureSize;
|
|
const maxTextureSize = capabilities.maxTextureSize;
|
|
const maxSamples = capabilities.maxSamples;
|
|
const maxSamples = capabilities.maxSamples;
|
|
|
|
+ const hasMultisampledRenderToTexture = extensions.has( 'WEBGL_multisampled_render_to_texture' );
|
|
|
|
+ const MultisampledRenderToTextureExtension = hasMultisampledRenderToTexture ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : undefined;
|
|
|
|
|
|
const _videoTextures = new WeakMap();
|
|
const _videoTextures = new WeakMap();
|
|
let _canvas;
|
|
let _canvas;
|
|
@@ -901,23 +903,38 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
const glFormat = utils.convert( texture.format );
|
|
const glFormat = utils.convert( texture.format );
|
|
const glType = utils.convert( texture.type );
|
|
const glType = utils.convert( texture.type );
|
|
const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
|
|
const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
|
|
|
|
+ const renderTargetProperties = properties.get( renderTarget );
|
|
|
|
|
|
- if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) {
|
|
|
|
|
|
+ if ( ! renderTargetProperties.__hasExternalTextures ) {
|
|
|
|
|
|
- state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null );
|
|
|
|
|
|
+ if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) {
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
|
|
|
|
|
|
- state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
|
|
state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
|
|
- _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 );
|
|
|
|
|
|
+ if ( renderTarget.useRenderToTexture ) {
|
|
|
|
+
|
|
|
|
+ MultisampledRenderToTextureExtension.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
state.bindFramebuffer( _gl.FRAMEBUFFER, null );
|
|
state.bindFramebuffer( _gl.FRAMEBUFFER, null );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
|
|
// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
|
|
function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
|
|
function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
|
|
|
|
|
|
@@ -927,7 +944,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
let glInternalFormat = _gl.DEPTH_COMPONENT16;
|
|
let glInternalFormat = _gl.DEPTH_COMPONENT16;
|
|
|
|
|
|
- if ( isMultisample ) {
|
|
|
|
|
|
+ if ( isMultisample || renderTarget.useRenderToTexture ) {
|
|
|
|
|
|
const depthTexture = renderTarget.depthTexture;
|
|
const depthTexture = renderTarget.depthTexture;
|
|
|
|
|
|
@@ -947,7 +964,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
const samples = getRenderTargetSamples( renderTarget );
|
|
const samples = getRenderTargetSamples( renderTarget );
|
|
|
|
|
|
- _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
|
|
|
|
+ if ( renderTarget.useRenderToTexture ) {
|
|
|
|
+
|
|
|
|
+ MultisampledRenderToTextureExtension.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
@@ -959,12 +984,16 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
|
|
} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
|
|
|
|
|
|
- if ( isMultisample ) {
|
|
|
|
|
|
+ const samples = getRenderTargetSamples( renderTarget );
|
|
|
|
|
|
- const samples = getRenderTargetSamples( renderTarget );
|
|
|
|
|
|
+ if ( isMultisample && renderTarget.useRenderbuffer ) {
|
|
|
|
|
|
_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
|
|
_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
|
|
|
|
|
|
|
|
+ } else if ( renderTarget.useRenderToTexture ) {
|
|
|
|
+
|
|
|
|
+ MultisampledRenderToTextureExtension.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
|
|
|
|
+
|
|
} else {
|
|
} else {
|
|
|
|
|
|
_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
|
|
_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
|
|
@@ -982,13 +1011,16 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
const glFormat = utils.convert( texture.format );
|
|
const glFormat = utils.convert( texture.format );
|
|
const glType = utils.convert( texture.type );
|
|
const glType = utils.convert( texture.type );
|
|
const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
|
|
const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
|
|
|
|
+ const samples = getRenderTargetSamples( renderTarget );
|
|
|
|
|
|
- if ( isMultisample ) {
|
|
|
|
-
|
|
|
|
- const samples = getRenderTargetSamples( renderTarget );
|
|
|
|
|
|
+ if ( isMultisample && renderTarget.useRenderbuffer ) {
|
|
|
|
|
|
_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
|
|
|
|
|
|
+ } else if ( renderTarget.useRenderToTexture ) {
|
|
|
|
+
|
|
|
|
+ MultisampledRenderToTextureExtension.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
|
|
+
|
|
} else {
|
|
} else {
|
|
|
|
|
|
_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
|
|
@@ -1029,14 +1061,31 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
setTexture2D( renderTarget.depthTexture, 0 );
|
|
setTexture2D( renderTarget.depthTexture, 0 );
|
|
|
|
|
|
const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
|
|
const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
|
|
|
|
+ const samples = getRenderTargetSamples( renderTarget );
|
|
|
|
|
|
if ( renderTarget.depthTexture.format === DepthFormat ) {
|
|
if ( renderTarget.depthTexture.format === DepthFormat ) {
|
|
|
|
|
|
- _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
|
|
|
|
|
|
+ if ( renderTarget.useRenderToTexture ) {
|
|
|
|
+
|
|
|
|
+ MultisampledRenderToTextureExtension.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
|
|
} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
|
|
|
|
|
|
- _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
|
|
|
|
|
|
+ if ( renderTarget.useRenderToTexture ) {
|
|
|
|
+
|
|
|
|
+ MultisampledRenderToTextureExtension.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
@@ -1050,10 +1099,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
function setupDepthRenderbuffer( renderTarget ) {
|
|
function setupDepthRenderbuffer( renderTarget ) {
|
|
|
|
|
|
const renderTargetProperties = properties.get( renderTarget );
|
|
const renderTargetProperties = properties.get( renderTarget );
|
|
-
|
|
|
|
const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
|
|
const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
|
|
|
|
|
|
- if ( renderTarget.depthTexture ) {
|
|
|
|
|
|
+ if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) {
|
|
|
|
|
|
if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
|
|
if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
|
|
|
|
|
|
@@ -1087,6 +1135,25 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // rebind framebuffer with external textures
|
|
|
|
+ function rebindTextures( renderTarget, colorTexture, depthTexture ) {
|
|
|
|
+
|
|
|
|
+ const renderTargetProperties = properties.get( renderTarget );
|
|
|
|
+
|
|
|
|
+ if ( colorTexture !== undefined ) {
|
|
|
|
+
|
|
|
|
+ setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( depthTexture !== undefined ) {
|
|
|
|
+
|
|
|
|
+ setupDepthRenderbuffer( renderTarget );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
// Set up GL resources for the render target
|
|
// Set up GL resources for the render target
|
|
function setupRenderTarget( renderTarget ) {
|
|
function setupRenderTarget( renderTarget ) {
|
|
|
|
|
|
@@ -1099,7 +1166,12 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
if ( renderTarget.isWebGLMultipleRenderTargets !== true ) {
|
|
if ( renderTarget.isWebGLMultipleRenderTargets !== true ) {
|
|
|
|
|
|
- textureProperties.__webglTexture = _gl.createTexture();
|
|
|
|
|
|
+ if ( textureProperties.__webglTexture === undefined ) {
|
|
|
|
+
|
|
|
|
+ textureProperties.__webglTexture = _gl.createTexture();
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
textureProperties.__version = texture.version;
|
|
textureProperties.__version = texture.version;
|
|
info.memory.textures ++;
|
|
info.memory.textures ++;
|
|
|
|
|
|
@@ -1107,7 +1179,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
|
|
const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
|
|
const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
|
|
const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
|
|
- const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
|
|
|
|
const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray;
|
|
const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray;
|
|
const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
|
|
const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
|
|
|
|
|
|
@@ -1163,7 +1234,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- } else if ( isMultisample ) {
|
|
|
|
|
|
+ } else if ( renderTarget.useRenderbuffer ) {
|
|
|
|
|
|
if ( isWebGL2 ) {
|
|
if ( isWebGL2 ) {
|
|
|
|
|
|
@@ -1318,23 +1389,43 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
function updateMultisampleRenderTarget( renderTarget ) {
|
|
function updateMultisampleRenderTarget( renderTarget ) {
|
|
|
|
|
|
- if ( renderTarget.isWebGLMultisampleRenderTarget ) {
|
|
|
|
|
|
+ if ( renderTarget.useRenderbuffer ) {
|
|
|
|
|
|
if ( isWebGL2 ) {
|
|
if ( isWebGL2 ) {
|
|
|
|
|
|
const width = renderTarget.width;
|
|
const width = renderTarget.width;
|
|
const height = renderTarget.height;
|
|
const height = renderTarget.height;
|
|
let mask = _gl.COLOR_BUFFER_BIT;
|
|
let mask = _gl.COLOR_BUFFER_BIT;
|
|
|
|
+ const invalidationArray = [ _gl.COLOR_ATTACHMENT0 ];
|
|
|
|
+ const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
|
|
|
|
+
|
|
|
|
+ if ( renderTarget.depthBuffer ) {
|
|
|
|
+
|
|
|
|
+ invalidationArray.push( depthStyle );
|
|
|
|
|
|
- if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;
|
|
|
|
- if ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT;
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( ! renderTarget.ignoreDepthForMultisampleCopy ) {
|
|
|
|
+
|
|
|
|
+ if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;
|
|
|
|
+ if ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
const renderTargetProperties = properties.get( renderTarget );
|
|
const renderTargetProperties = properties.get( renderTarget );
|
|
|
|
|
|
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
|
|
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
|
|
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
|
|
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
|
|
|
|
|
|
|
|
+ if ( renderTarget.ignoreDepthForMultisampleCopy ) {
|
|
|
|
+
|
|
|
|
+ _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] );
|
|
|
|
+ _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );
|
|
_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );
|
|
|
|
+ _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray );
|
|
|
|
|
|
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
|
|
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
|
|
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
|
|
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
|
|
@@ -1351,7 +1442,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
function getRenderTargetSamples( renderTarget ) {
|
|
function getRenderTargetSamples( renderTarget ) {
|
|
|
|
|
|
- return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
|
|
|
|
|
|
+ return ( isWebGL2 && ( renderTarget.useRenderbuffer || renderTarget.useRenderToTexture ) ) ?
|
|
Math.min( maxSamples, renderTarget.samples ) : 0;
|
|
Math.min( maxSamples, renderTarget.samples ) : 0;
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1424,9 +1515,12 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
this.setTexture2DArray = setTexture2DArray;
|
|
this.setTexture2DArray = setTexture2DArray;
|
|
this.setTexture3D = setTexture3D;
|
|
this.setTexture3D = setTexture3D;
|
|
this.setTextureCube = setTextureCube;
|
|
this.setTextureCube = setTextureCube;
|
|
|
|
+ this.rebindTextures = rebindTextures;
|
|
this.setupRenderTarget = setupRenderTarget;
|
|
this.setupRenderTarget = setupRenderTarget;
|
|
this.updateRenderTargetMipmap = updateRenderTargetMipmap;
|
|
this.updateRenderTargetMipmap = updateRenderTargetMipmap;
|
|
this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
|
|
this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
|
|
|
|
+ this.setupDepthRenderbuffer = setupDepthRenderbuffer;
|
|
|
|
+ this.setupFrameBufferTexture = setupFrameBufferTexture;
|
|
|
|
|
|
this.safeSetTexture2D = safeSetTexture2D;
|
|
this.safeSetTexture2D = safeSetTexture2D;
|
|
this.safeSetTextureCube = safeSetTextureCube;
|
|
this.safeSetTextureCube = safeSetTextureCube;
|