Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGLRenderer: Enable subframe upload in copyTextureToTexture, align API to 3d version #28281

Merged
merged 17 commits into from
May 7, 2024
Merged
11 changes: 6 additions & 5 deletions docs/api/en/renderers/WebGLRenderer.html
Original file line number Diff line number Diff line change
Expand Up @@ -376,19 +376,20 @@ <h3>
</p>

<h3>
[method:undefined copyTextureToTexture]( [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )
[method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion], [param:Vector2 dstPosition], [param:Number level] )
</h3>
<p>
Copies all pixels of a texture to an existing texture starting from the
given position. Enables access to
Copies the pixels of a texture in the bounds '[page:Box2 srcRegion]' in
the destination texture starting from the given position. Enables access
to
[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D WebGLRenderingContext.texSubImage2D].
</p>

<h3>
[method:undefined copyTextureToTexture3D]( [param:Box3 sourceBox], [param:Vector3 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )
[method:undefined copyTextureToTexture3D]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box3 srcRegion], [param:Vector3 dstPosition], [param:Number level] )
</h3>
<p>
Copies the pixels of a texture in the bounds '[page:Box3 sourceBox]' in
Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in
the destination texture starting from the given position. Enables access
to
[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D].
Expand Down
2 changes: 1 addition & 1 deletion examples/webgl2_materials_texture3d_partialupdate.html
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@
const scaleFactor = ( Math.random() + 0.5 ) * 0.5;
const source = generateCloudTexture( perElementPaddedSize, scaleFactor );

renderer.copyTextureToTexture3D( box, position, source, cloudTexture );
renderer.copyTextureToTexture3D( source, cloudTexture, box, position );

prevTime = time;

Expand Down
2 changes: 1 addition & 1 deletion examples/webgl_materials_texture_partialupdate.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@

// perform copy from src to dest texture to a random position

renderer.copyTextureToTexture( position, dataTexture, diffuseMap );
renderer.copyTextureToTexture( dataTexture, diffuseMap, null, position );

}

Expand Down
163 changes: 135 additions & 28 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2371,10 +2371,52 @@ class WebGLRenderer {

};

this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {

// support previous signature with source box first
Copy link
Owner

@mrdoob mrdoob May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be like this?

// support previous signature with dstPosition first

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah - copy paste error

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ( srcTexture.isTexture !== true ) {

// @deprecated, r165
console.warn( 'WebGLRenderer: copyTextureToTexture function signature has changed.' );

dstPosition = arguments[ 0 ] || null;
srcTexture = arguments[ 1 ];
dstTexture = arguments[ 2 ];
level = arguments[ 3 ] || 0;
srcRegion = null;

}

let width, height, minX, minY;
let dstX, dstY;
if ( srcRegion !== null ) {

width = srcRegion.max.x - srcRegion.min.x;
height = srcRegion.max.y - srcRegion.min.y;
minX = srcRegion.min.x;
minY = srcRegion.min.y;

} else {

width = srcTexture.image.width;
height = srcTexture.image.height;
minX = 0;
minY = 0;

}

if ( dstPosition !== null ) {

dstX = dstPosition.x;
dstY = dstPosition.y;

} else {

dstX = 0;
dstY = 0;

}

const width = srcTexture.image.width;
const height = srcTexture.image.height;
const glFormat = utils.convert( dstTexture.format );
const glType = utils.convert( dstTexture.type );

Expand All @@ -2386,36 +2428,103 @@ class WebGLRenderer {
_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );

const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );

gkjohnson marked this conversation as resolved.
Show resolved Hide resolved
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;

_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );

if ( srcTexture.isDataTexture ) {

_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );

} else {

if ( srcTexture.isCompressedTexture ) {

_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );

} else {

_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image );
_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, glFormat, glType, image );

}

}

_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );

// Generate mipmaps only when copying level 0
if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );

state.unbindTexture();

};

this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) {
this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {

// support previous signature with source box first
if ( srcTexture.isTexture !== true ) {

// @deprecated, r165
console.warn( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' );

srcRegion = arguments[ 0 ] || null;
dstPosition = arguments[ 1 ] || null;
srcTexture = arguments[ 2 ];
dstTexture = arguments[ 3 ];
level = arguments[ 4 ] || 0;

}

let width, height, depth, minX, minY, minZ;
let dstX, dstY, dstZ;
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
if ( srcRegion !== null ) {

width = srcRegion.max.x - srcRegion.min.x;
height = srcRegion.max.y - srcRegion.min.y;
depth = srcRegion.max.z - srcRegion.min.z;
minX = srcRegion.min.x;
minY = srcRegion.min.y;
minZ = srcRegion.min.z;

} else {

width = image.width;
height = image.height;
depth = image.depth;
minX = 0;
minY = 0;
minZ = 0;

}

if ( dstPosition !== null ) {

dstX = dstPosition.x;
dstY = dstPosition.y;
dstZ = dstPosition.z;

} else {

dstX = 0;
dstY = 0;
dstZ = 0;

}

const width = sourceBox.max.x - sourceBox.min.x;
const height = sourceBox.max.y - sourceBox.min.y;
const depth = sourceBox.max.z - sourceBox.min.z;
const glFormat = utils.convert( dstTexture.format );
const glType = utils.convert( dstTexture.type );
let glTarget;
Expand All @@ -2441,43 +2550,41 @@ class WebGLRenderer {
_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );

const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );

const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );

_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x );
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y );
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );

if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {

_gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data );
_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );

} else {

if ( dstTexture.isCompressedArrayTexture ) {

_gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data );
_gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );

} else {

_gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image );
_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );

}

}

_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen );
_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels );
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows );
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages );
_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );

// Generate mipmaps only when copying level 0
if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
Expand Down