-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
copyTextureToTexture sourcebox, flipY from source #21986
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
Conversation
|
/cc @DavidPeicho |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point those methods are so complex than I am wondering if they shouldn't even be merged as a single one...
The only notable differences to me are:
- The depth component
- The unpacking
- The name of the function to upload the data
I think we can work a bit on simplifying the function while keeping the features added.
| if ( ! srcTexture.isTexture ) { | ||
|
|
||
| console.warn( 'THREE.WebGLRenderer: .copyTextureToTexture() now expects (srcTexture, dstTexture, dstPosition, srcBox, dstLevel, srcLevel).' ); | ||
| return this.copyTextureToTexture( arguments[ 1 ], arguments[ 2 ], arguments[ 0 ], undefined, arguments[ 3 ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you use arguments here instead of the named parameters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arguments are out of order, so the named parameters would be more confusing IMHO this.copyTextureToTexture(dstTexture, dstPosition, srcTexture, undefined, srcBox)
|
|
||
| } | ||
|
|
||
| const image = srcTexture.mipmaps[ srcLevel ] || ( srcLevel == 0 ? srcTexture.image : null ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, how should we differentiate base texture from mipmap 0? @mrdoob
Here what's happening is a bit weird to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that I only guessed from code that textures either had mipmaps or a single image (which would act as mipmap level 0). Is that true ? could a texture have both ? could image refer to a mipmap level different than 0 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense actually. If you have mipmaps, level 0 should be the normal textures... But that's confusing
|
|
||
| } | ||
|
|
||
| let skipPixels = srcBox ? srcBox.min.x : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not too important, but here we can initialize all variables to the default value, and then perform the condition once:
srcBox !== undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true. just tell me which coding style you prefer in three.
| let y = dstPosition ? dstPosition.y : 0; | ||
|
|
||
| // ensure skipPixels, skipRows, x and y >= 0 | ||
| if ( skipPixels < 0 || x < 0 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both of those conditions aren't needed and should work the same way srcBox is clamped to 0 when negative.
They add a lot of code for something the user should clearly not do. We can add a little disclaimer in the doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code selects the biggest valid box inside the srcBox for copy : srcbox is shrunk so that it is contained in the source texture and the dstBox ={ min: dstPosition, max = dstPosition-srcBoxmin+srcBox.max} is contained in the destination texture.
as said in the PR, the alternative is to pass directly srcBox and dstPosition to webGL and let it crash if it is not valid. Both are fine to me, but the one we chose should be documented.
|
|
||
| } | ||
|
|
||
| const width = Math.min( dstTexture.image.width - x, srcBox ? Math.min( image.width, srcBox.max.x + 1 ) - skipPixels : image.width ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we decide to remove the above two conditions, then we also need to update that part because it will not be valid anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, they will simplify : const width = srcBox.max.x - srcBox.min.x + 1;
mbredif
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @DavidPeicho for the review. I gave your ideas a try, merging the two functions notably : dev...mbredif:copyTextureToTexture_merged .
Is that what you had in mind ? @mrdoob and @Mugen87, do you prefer this second approach ?
| if ( ! srcTexture.isTexture ) { | ||
|
|
||
| console.warn( 'THREE.WebGLRenderer: .copyTextureToTexture() now expects (srcTexture, dstTexture, dstPosition, srcBox, dstLevel, srcLevel).' ); | ||
| return this.copyTextureToTexture( arguments[ 1 ], arguments[ 2 ], arguments[ 0 ], undefined, arguments[ 3 ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arguments are out of order, so the named parameters would be more confusing IMHO this.copyTextureToTexture(dstTexture, dstPosition, srcTexture, undefined, srcBox)
|
|
||
| } | ||
|
|
||
| const image = srcTexture.mipmaps[ srcLevel ] || ( srcLevel == 0 ? srcTexture.image : null ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that I only guessed from code that textures either had mipmaps or a single image (which would act as mipmap level 0). Is that true ? could a texture have both ? could image refer to a mipmap level different than 0 ?
|
|
||
| } | ||
|
|
||
| let skipPixels = srcBox ? srcBox.min.x : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true. just tell me which coding style you prefer in three.
| let y = dstPosition ? dstPosition.y : 0; | ||
|
|
||
| // ensure skipPixels, skipRows, x and y >= 0 | ||
| if ( skipPixels < 0 || x < 0 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code selects the biggest valid box inside the srcBox for copy : srcbox is shrunk so that it is contained in the source texture and the dstBox ={ min: dstPosition, max = dstPosition-srcBoxmin+srcBox.max} is contained in the destination texture.
as said in the PR, the alternative is to pass directly srcBox and dstPosition to webGL and let it crash if it is not valid. Both are fine to me, but the one we chose should be documented.
|
|
||
| } | ||
|
|
||
| const width = Math.min( dstTexture.image.width - x, srcBox ? Math.min( image.width, srcBox.max.x + 1 ) - skipPixels : image.width ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, they will simplify : const width = srcBox.max.x - srcBox.min.x + 1;
Mugen87
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I initially added copyTextureToTexture(), it was important to me to cover the most basic use cases and keep the method simple. Now it is enhanced to cover more advanced use cases but that makes the implementation as well as the signature more complex.
TBH, as long as there is no more demand for such features I would prefer to keep the method simple. And let advanced users monkey-patch the method if necessary.
|
What about this version ? https://github.com/mbredif/three.js/blob/copyTextureToTexture_merged/src/renderers/WebGLRenderer.js#L2083-L2227 . As @DavidPeicho mentioned, the 2 copy functions could be merged to factor common code. I also removed the box shrinking code to simplify the implementation. |
|
I quite like the second version! Thanks! It's indeed a bit of code, but that's the issue with abstracting a method that has so many options. |
|
The most important part of this PR (copying sub parts of an input 2D texture) was implemented in #28281. I would leave the other features out for now and only add them if they are frequently requested. |
Related issue: #21942
Description
This PR aligns the apis of copyTextureToTexture and copyTextureToTexture3D in the WebGLRenderer :
( srcTexture, dstTexture, dstPosition = undefined, srcBox = undefined, dstLevel = 0, srcLevel = 0 )as all parameters but textures have sensible defaults (destination position at origin, full source box and levels at 0).examples/webgl_materials_texture_partialupdate.html
The box is reduced so that it points to valid pixels in both the source and destination textures. As an alternative, this code could be simplified if this burden is given to the user (big boxes will trigger webgl error).
finally, the UNPACK parameters are now taken from the source texture rather than the destination texture. It makes more sense in my use cases (otherwise I always end up at least copying flipY and unpackAlignment from the srcTexture to the dstTexture before the copy as a workaround)