@@ -706,7 +706,10 @@ class RenderWebGL extends EventEmitter {
706706 gl . clearColor ( ...this . _backgroundColor4f ) ;
707707 gl . clear ( gl . COLOR_BUFFER_BIT ) ;
708708
709- this . _drawThese ( this . _drawList , ShaderManager . DRAW_MODE . default , this . _projection ) ;
709+ this . _drawThese ( this . _drawList , ShaderManager . DRAW_MODE . default , this . _projection , {
710+ framebufferWidth : gl . canvas . width ,
711+ framebufferHeight : gl . canvas . height
712+ } ) ;
710713 if ( this . _snapshotCallbacks . length > 0 ) {
711714 const snapshot = gl . canvas . toDataURL ( ) ;
712715 this . _snapshotCallbacks . forEach ( cb => cb ( snapshot ) ) ;
@@ -1186,114 +1189,6 @@ class RenderWebGL extends EventEmitter {
11861189 return Number ( hit ) ;
11871190 }
11881191
1189- /**
1190- * @typedef DrawableExtractionOld
1191- * @property {Uint8Array } data Raw pixel data for the drawable
1192- * @property {int } width Drawable bounding box width
1193- * @property {int } height Drawable bounding box height
1194- * @property {Array<number> } scratchOffset [x, y] offset in Scratch coordinates
1195- * from the drawable position to the client x, y coordinate
1196- * @property {int } x The x coordinate relative to drawable bounding box
1197- * @property {int } y The y coordinate relative to drawable bounding box
1198- */
1199-
1200- /**
1201- * Return drawable pixel data and picking coordinates relative to the drawable bounds
1202- * @param {int } drawableID The ID of the drawable to get pixel data for
1203- * @param {int } x The client x coordinate of the picking location.
1204- * @param {int } y The client y coordinate of the picking location.
1205- * @return {?DrawableExtractionOld } Data about the picked drawable
1206- * @deprecated Use {@link extractDrawableScreenSpace} instead.
1207- */
1208- extractDrawable ( drawableID , x , y ) {
1209- this . _doExitDrawRegion ( ) ;
1210-
1211- const drawable = this . _allDrawables [ drawableID ] ;
1212- if ( ! drawable ) return null ;
1213-
1214- // Convert client coordinates into absolute scratch units
1215- const scratchX = this . _nativeSize [ 0 ] * ( ( x / this . _gl . canvas . clientWidth ) - 0.5 ) ;
1216- const scratchY = this . _nativeSize [ 1 ] * ( ( y / this . _gl . canvas . clientHeight ) - 0.5 ) ;
1217-
1218- const gl = this . _gl ;
1219-
1220- const bounds = drawable . getFastBounds ( ) ;
1221- bounds . snapToInt ( ) ;
1222-
1223- // Set a reasonable max limit width and height for the bufferInfo bounds
1224- const maxTextureSize = gl . getParameter ( gl . MAX_TEXTURE_SIZE ) ;
1225- const clampedWidth = Math . min ( 2048 , bounds . width , maxTextureSize ) ;
1226- const clampedHeight = Math . min ( 2048 , bounds . height , maxTextureSize ) ;
1227-
1228- // Make a new bufferInfo since this._queryBufferInfo is limited to 480x360
1229- const attachments = [
1230- { format : gl . RGBA } ,
1231- { format : gl . DEPTH_STENCIL }
1232- ] ;
1233- const bufferInfo = twgl . createFramebufferInfo ( gl , attachments , clampedWidth , clampedHeight ) ;
1234-
1235- try {
1236- // If the new bufferInfo is invalid, fall back to using the smaller _queryBufferInfo
1237- twgl . bindFramebufferInfo ( gl , bufferInfo ) ;
1238- if ( gl . checkFramebufferStatus ( gl . FRAMEBUFFER ) !== gl . FRAMEBUFFER_COMPLETE ) {
1239- twgl . bindFramebufferInfo ( gl , this . _queryBufferInfo ) ;
1240- }
1241-
1242- // Translate to scratch units relative to the drawable
1243- const pickX = scratchX - bounds . left ;
1244- const pickY = scratchY + bounds . top ;
1245-
1246- // Limit size of viewport to the bounds around the target Drawable,
1247- // and create the projection matrix for the draw.
1248- gl . viewport ( 0 , 0 , bounds . width , bounds . height ) ;
1249- const projection = twgl . m4 . ortho ( bounds . left , bounds . right , bounds . top , bounds . bottom , - 1 , 1 ) ;
1250-
1251- gl . clearColor ( 0 , 0 , 0 , 0 ) ;
1252- gl . clear ( gl . COLOR_BUFFER_BIT ) ;
1253- try {
1254- gl . disable ( gl . BLEND ) ;
1255- // ImageData objects store alpha un-premultiplied, so draw with the `straightAlpha` draw mode.
1256- this . _drawThese ( [ drawableID ] , ShaderManager . DRAW_MODE . straightAlpha , projection ,
1257- { effectMask : ~ ShaderManager . EFFECT_INFO . ghost . mask } ) ;
1258- } finally {
1259- gl . enable ( gl . BLEND ) ;
1260- }
1261-
1262- const data = new Uint8Array ( Math . floor ( bounds . width * bounds . height * 4 ) ) ;
1263- gl . readPixels ( 0 , 0 , bounds . width , bounds . height , gl . RGBA , gl . UNSIGNED_BYTE , data ) ;
1264-
1265- if ( this . _debugCanvas ) {
1266- this . _debugCanvas . width = bounds . width ;
1267- this . _debugCanvas . height = bounds . height ;
1268- const ctx = this . _debugCanvas . getContext ( '2d' ) ;
1269- const imageData = ctx . createImageData ( bounds . width , bounds . height ) ;
1270- imageData . data . set ( data ) ;
1271- ctx . putImageData ( imageData , 0 , 0 ) ;
1272- ctx . beginPath ( ) ;
1273- ctx . arc ( pickX , pickY , 3 , 0 , 2 * Math . PI , false ) ;
1274- ctx . fillStyle = 'white' ;
1275- ctx . fill ( ) ;
1276- ctx . lineWidth = 1 ;
1277- ctx . strokeStyle = 'black' ;
1278- ctx . stroke ( ) ;
1279- }
1280-
1281- return {
1282- data : data ,
1283- width : bounds . width ,
1284- height : bounds . height ,
1285- scratchOffset : [
1286- - scratchX + drawable . _position [ 0 ] ,
1287- - scratchY - drawable . _position [ 1 ]
1288- ] ,
1289- x : pickX ,
1290- y : pickY
1291- } ;
1292- } finally {
1293- gl . deleteFramebuffer ( bufferInfo . framebuffer ) ;
1294- }
1295- }
1296-
12971192 /**
12981193 * @typedef DrawableExtraction
12991194 * @property {ImageData } data Raw pixel data for the drawable
@@ -1371,9 +1266,15 @@ class RenderWebGL extends EventEmitter {
13711266
13721267 gl . clearColor ( 0 , 0 , 0 , 0 ) ;
13731268 gl . clear ( gl . COLOR_BUFFER_BIT ) ;
1374- // Don't apply the ghost effect. TODO: is this an intentional design decision?
13751269 this . _drawThese ( [ drawableID ] , ShaderManager . DRAW_MODE . straightAlpha , projection ,
1376- { effectMask : ~ ShaderManager . EFFECT_INFO . ghost . mask } ) ;
1270+ {
1271+ // Don't apply the ghost effect. TODO: is this an intentional design decision?
1272+ effectMask : ~ ShaderManager . EFFECT_INFO . ghost . mask ,
1273+ // We're doing this in screen-space, so the framebuffer dimensions should be those of the canvas in
1274+ // screen-space. This is used to ensure SVG skins are rendered at the proper resolution.
1275+ framebufferWidth : canvas . width ,
1276+ framebufferHeight : canvas . height
1277+ } ) ;
13771278
13781279 const data = new Uint8Array ( Math . floor ( clampedWidth * clampedHeight * 4 ) ) ;
13791280 gl . readPixels ( 0 , 0 , clampedWidth , clampedHeight , gl . RGBA , gl . UNSIGNED_BYTE , data ) ;
@@ -1902,18 +1803,6 @@ class RenderWebGL extends EventEmitter {
19021803 this . _regionId = null ;
19031804 }
19041805
1905- /**
1906- * Get the screen-space scale of a drawable, as percentages of the drawable's "normal" size.
1907- * @param {Drawable } drawable The drawable whose screen-space scale we're fetching.
1908- * @returns {Array<number> } The screen-space X and Y dimensions of the drawable's scale, as percentages.
1909- */
1910- _getDrawableScreenSpaceScale ( drawable ) {
1911- return [
1912- drawable . scale [ 0 ] * this . _gl . canvas . width / this . _nativeSize [ 0 ] ,
1913- drawable . scale [ 1 ] * this . _gl . canvas . height / this . _nativeSize [ 1 ]
1914- ] ;
1915- }
1916-
19171806 /**
19181807 * Draw a set of Drawables, by drawable ID
19191808 * @param {Array<int> } drawables The Drawable IDs to draw, possibly this._drawList.
@@ -1924,13 +1813,20 @@ class RenderWebGL extends EventEmitter {
19241813 * @param {object.<string,*> } opts.extraUniforms Extra uniforms for the shaders.
19251814 * @param {int } opts.effectMask Bitmask for effects to allow
19261815 * @param {boolean } opts.ignoreVisibility Draw all, despite visibility (e.g. stamping, touching color)
1816+ * @param {int } opts.framebufferWidth The width of the framebuffer being drawn onto. Defaults to "native" width
1817+ * @param {int } opts.framebufferHeight The height of the framebuffer being drawn onto. Defaults to "native" height
19271818 * @private
19281819 */
19291820 _drawThese ( drawables , drawMode , projection , opts = { } ) {
19301821
19311822 const gl = this . _gl ;
19321823 let currentShader = null ;
19331824
1825+ const framebufferSpaceScaleDiffers = (
1826+ 'framebufferWidth' in opts && 'framebufferHeight' in opts &&
1827+ opts . framebufferWidth !== this . _nativeSize [ 0 ] && opts . framebufferHeight !== this . _nativeSize [ 1 ]
1828+ ) ;
1829+
19341830 const numDrawables = drawables . length ;
19351831 for ( let drawableIndex = 0 ; drawableIndex < numDrawables ; ++ drawableIndex ) {
19361832 const drawableID = drawables [ drawableIndex ] ;
@@ -1945,8 +1841,13 @@ class RenderWebGL extends EventEmitter {
19451841 // the ignoreVisibility flag is used (e.g. for stamping or touchingColor).
19461842 if ( ! drawable . getVisible ( ) && ! opts . ignoreVisibility ) continue ;
19471843
1948- // Combine drawable scale with the native vs. backing pixel ratio
1949- const drawableScale = this . _getDrawableScreenSpaceScale ( drawable ) ;
1844+ // drawableScale is the "framebuffer-pixel-space" scale of the drawable, as percentages of the drawable's
1845+ // "native size" (so 100 = same as skin's "native size", 200 = twice "native size").
1846+ // If the framebuffer dimensions are the same as the stage's "native" size, there's no need to calculate it.
1847+ const drawableScale = framebufferSpaceScaleDiffers ? [
1848+ drawable . scale [ 0 ] * opts . framebufferWidth / this . _nativeSize [ 0 ] ,
1849+ drawable . scale [ 1 ] * opts . framebufferHeight / this . _nativeSize [ 1 ]
1850+ ] : drawable . scale ;
19501851
19511852 // If the skin or texture isn't ready yet, skip it.
19521853 if ( ! drawable . skin || ! drawable . skin . getTexture ( drawableScale ) ) continue ;
@@ -2179,7 +2080,7 @@ class RenderWebGL extends EventEmitter {
21792080}
21802081
21812082// :3
2182- RenderWebGL . prototype . canHazPixels = RenderWebGL . prototype . extractDrawable ;
2083+ RenderWebGL . prototype . canHazPixels = RenderWebGL . prototype . extractDrawableScreenSpace ;
21832084
21842085/**
21852086 * Values for setUseGPU()
0 commit comments