From b0acea9f35b55122e9ee11bc7a945634b0ccbba2 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 13 Aug 2020 14:53:13 -0400 Subject: [PATCH] Pull in parts of pull 479 which move clamping to texture space into silhouette --- src/Drawable.js | 14 +------------- src/Silhouette.js | 30 ++++++++++++++++++++---------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/Drawable.js b/src/Drawable.js index 9e58ffb..74fb81d 100644 --- a/src/Drawable.js +++ b/src/Drawable.js @@ -712,8 +712,7 @@ class Drawable { * Sample a color from a drawable's texture. * The caller is responsible for ensuring this drawable's inverse matrix & its skin's silhouette are up-to-date. * @see updateCPURenderAttributes - * @param {twgl.v3} vec The scratch space [x,y] vector. This will be clamped to the texture space, to match the - * GL code (See https://github.com/LLK/scratch-render/blob/develop/src/BitmapSkin.js#L88) + * @param {twgl.v3} vec The scratch space [x,y] vector * @param {Drawable} drawable The drawable to sample the texture from * @param {Uint8ClampedArray} dst The "color4b" representation of the texture at point. * @param {number} [effectMask] A bitmask for which effects to use. Optional. @@ -721,17 +720,6 @@ class Drawable { */ static sampleColor4b (vec, drawable, dst, effectMask) { const localPosition = getLocalPosition(drawable, vec); - if (localPosition[0] < 0) { - localPosition[0] = 0; - } else if (localPosition[0] > 1) { - localPosition[0] = 1; - } - - if (localPosition[1] < 0) { - localPosition[1] = 0; - } else if (localPosition[1] > 1) { - localPosition[1] = 1; - } const textColor = // commenting out to only use nearest for now // drawable.useNearest() ? diff --git a/src/Silhouette.js b/src/Silhouette.js index 08e7120..b96348a 100644 --- a/src/Silhouette.js +++ b/src/Silhouette.js @@ -10,6 +10,11 @@ */ let __SilhouetteUpdateCanvas; +// Optimized Math.min and Math.max for integers; +// taken from https://web.archive.org/web/20190716181049/http://guihaire.com/code/?p=549 +const intMin = (i, j) => j ^ ((i ^ j) & ((i - j) >> 31)); +const intMax = (i, j) => i ^ ((i ^ j) & ((i - j) >> 31)); + /** * Internal helper function (in hopes that compiler can inline). Get a pixel * from silhouette data, or 0 if outside it's bounds. @@ -40,13 +45,18 @@ const __cornerWork = [ /** * Get the color from a given silhouette at an x/y local texture position. * Multiply color values by alpha for proper blending. - * @param {Silhouette} The silhouette to sample. - * @param {number} x X position of texture (0-1). - * @param {number} y Y position of texture (0-1). + * @param {Silhouette} $0 The silhouette to sample. + * @param {number} x X position of texture [0, width). + * @param {number} y Y position of texture [0, height). * @param {Uint8ClampedArray} dst A color 4b space. * @return {Uint8ClampedArray} The dst vector. */ const getColor4b = ({_width: width, _height: height, _colorData: data}, x, y, dst) => { + // Clamp coords to edge, matching GL_CLAMP_TO_EDGE. + // (See github.com/LLK/scratch-render/blob/954cfff02b08069a082cbedd415c1fecd9b1e4fb/src/BitmapSkin.js#L88) + x = intMax(0, intMin(x, width - 1)); + y = intMax(0, intMin(y, height - 1)); + // 0 if outside bounds, otherwise read from data. if (x >= width || y >= height || x < 0 || y < 0) { return dst.fill(0); @@ -64,17 +74,17 @@ const getColor4b = ({_width: width, _height: height, _colorData: data}, x, y, ds /** * Get the color from a given silhouette at an x/y local texture position. * Do not multiply color values by alpha, as it has already been done. - * @param {Silhouette} The silhouette to sample. - * @param {number} x X position of texture (0-1). - * @param {number} y Y position of texture (0-1). + * @param {Silhouette} $0 The silhouette to sample. + * @param {number} x X position of texture [0, width). + * @param {number} y Y position of texture [0, height). * @param {Uint8ClampedArray} dst A color 4b space. * @return {Uint8ClampedArray} The dst vector. */ const getPremultipliedColor4b = ({_width: width, _height: height, _colorData: data}, x, y, dst) => { - // 0 if outside bounds, otherwise read from data. - if (x >= width || y >= height || x < 0 || y < 0) { - return dst.fill(0); - } + // Clamp coords to edge, matching GL_CLAMP_TO_EDGE. + x = intMax(0, intMin(x, width - 1)); + y = intMax(0, intMin(y, height - 1)); + const offset = ((y * width) + x) * 4; dst[0] = data[offset]; dst[1] = data[offset + 1];