-
Notifications
You must be signed in to change notification settings - Fork 351
Set PenSkin silhouette data directly #475
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
Set PenSkin silhouette data directly #475
Conversation
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 is awesome.
During loading performance optimizations we found that passing an ImageData to a webgl texture instead of a canvas was both much faster and used much less memory. It made sense to add ImageData as an accepted type to update since we were always producing the ImageData outside Silhouette. But we overlooked updating PenSkin when those changes were made.
@@ -612,6 +618,9 @@ class PenSkin extends Skin { | |||
gl.clearColor(0, 0, 0, 0); | |||
gl.clear(gl.COLOR_BUFFER_BIT); | |||
|
|||
this._silhouettePixels = new Uint8Array(Math.floor(width * height * 4)); | |||
this._silhouetteImageData = this._canvas.getContext('2d').createImageData(width, height); |
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.
Yes. We should definitely reuse these.
src/PenSkin.js
Outdated
); | ||
|
||
this._silhouetteImageData.data.set(this._silhouettePixels); | ||
this._silhouette.update(this._silhouetteImageData); |
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.
Its great to see this updated to use the ImageData api change.
357d684
to
b194394
Compare
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.
😎
@@ -597,6 +603,9 @@ class PenSkin extends Skin { | |||
gl.clearColor(0, 0, 0, 0); | |||
gl.clear(gl.COLOR_BUFFER_BIT); | |||
|
|||
this._silhouettePixels = new Uint8Array(Math.floor(width * height * 4)); |
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.
Nit: the math.floor
isn't necessary here
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.
It seems to be used in every other place in the codebase that constructs a Uint8Array
, specifically to prevent issues with Edge.
If I removed it here, I don't think it would cause any trouble (width
and height
should be integers), and newer versions of Edge (I tested it on Microsoft Edge 44.18362.449.0, Microsoft EdgeHTML 18.18363) have no trouble with floating-point values in typed array constructors, but it'd break the convention that the rest of the codebase is using. Is that okay?
(P.S. it may be worth revisiting this in the future by either testing whether Edge 15, the minimum version Scratch officially supports, supports floating-point values in TypedArray
constructors, or by bumping the minimum supported Edge version in the FAQ to something newer.)
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.
Oops - thanks for the reminder! I had completely forgotten about that.
Proposed Changes
ImageData
and an array forgl.readPixels
forPenSkin
s.PenSkin
'sSilhouette
directly from the skin'sImageData
.Reason for Changes
The previous texture > silhouette pipeline for
PenSkin
was:gl.readPixels
of thePenSkin
's framebuffer into a newly createdUint8Array
.ImageData
object from the array.ImageData
to thePenSkin
's canvas.Silhouette
, which:ImageData
and stores it.The new pipeline is:
gl.readPixels
of thePenSkin
's framebuffer into a previously allocatedUint8Array
.ImageData
object.ImageData
to theSilhouette
, which uses it directly.By only creating a new array and
ImageData
object when thePenSkin
's canvas size is changed, and passing theSilhouette
theImageData
directly, we can greatly improve the speed of silhouette updates as shown in this benchmark:develop