Move useNearest to skin classes
This commit is contained in:
parent
a7df2b2e8e
commit
97605f9e55
@ -33,13 +33,6 @@ class BitmapSkin extends Skin {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean} true for a raster-style skin (like a BitmapSkin), false for vector-style (like SVGSkin).
|
||||
*/
|
||||
get isRaster () {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<number>} the "native" size, in texels, of this skin.
|
||||
*/
|
||||
|
||||
@ -489,40 +489,6 @@ class Drawable {
|
||||
return this.skin.isTouchingLinear(getLocalPosition(this, vec));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the drawable use NEAREST NEIGHBOR or LINEAR INTERPOLATION mode
|
||||
* @param {?Array<Number>} scale Optionally, the screen-space scale of the drawable.
|
||||
* @return {boolean} True if the drawable should use nearest-neighbor interpolation.
|
||||
*/
|
||||
useNearest (scale = this.scale) {
|
||||
// Raster skins (bitmaps) should always prefer nearest neighbor
|
||||
if (this.skin.isRaster) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the effect bits for mosaic, pixelate, whirl, or fisheye are set, use linear
|
||||
if ((this.enabledEffects & (
|
||||
ShaderManager.EFFECT_INFO.fisheye.mask |
|
||||
ShaderManager.EFFECT_INFO.whirl.mask |
|
||||
ShaderManager.EFFECT_INFO.pixelate.mask |
|
||||
ShaderManager.EFFECT_INFO.mosaic.mask
|
||||
)) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can't use nearest neighbor unless we are a multiple of 90 rotation
|
||||
if (this._direction % 90 !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the scale of the skin is very close to 100 (0.99999 variance is okay I guess)
|
||||
if (Math.abs(scale[0]) > 99 && Math.abs(scale[0]) < 101 &&
|
||||
Math.abs(scale[1]) > 99 && Math.abs(scale[1]) < 101) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the precise bounds for a Drawable.
|
||||
* This function applies the transform matrix to the known convex hull,
|
||||
@ -660,7 +626,7 @@ class Drawable {
|
||||
if (this.skin) {
|
||||
this.skin.updateSilhouette(this._scale);
|
||||
|
||||
if (this.useNearest()) {
|
||||
if (this.skin.useNearest(this._scale)) {
|
||||
this.isTouching = this._isTouchingNearest;
|
||||
} else {
|
||||
this.isTouching = this._isTouchingLinear;
|
||||
@ -734,10 +700,10 @@ class Drawable {
|
||||
dst[3] = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
const textColor =
|
||||
// commenting out to only use nearest for now
|
||||
// drawable.useNearest() ?
|
||||
// drawable.skin.useNearest(drawable._scale) ?
|
||||
drawable.skin._silhouette.colorAtNearest(localPosition, dst);
|
||||
// : drawable.skin._silhouette.colorAtLinear(localPosition, dst);
|
||||
|
||||
|
||||
@ -151,13 +151,6 @@ class PenSkin extends Skin {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean} true for a raster-style skin (like a BitmapSkin), false for vector-style (like SVGSkin).
|
||||
*/
|
||||
get isRaster () {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<number>} the "native" size, in texels, of this skin. [width, height]
|
||||
*/
|
||||
@ -165,6 +158,12 @@ class PenSkin extends Skin {
|
||||
return [this._canvas.width, this._canvas.height];
|
||||
}
|
||||
|
||||
useNearest (scale) {
|
||||
// Use nearest-neighbor interpolation when scaling up the pen skin-- this matches Scratch 2.0.
|
||||
// When scaling it down, use linear interpolation to avoid giving pen lines a "dashed" appearance.
|
||||
return Math.max(scale[0], scale[1]) >= 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {WebGLTexture} The GL texture representation of this skin when drawing at the given size.
|
||||
* @param {int} pixelsWide - The width that the skin will be rendered at, in GPU pixels.
|
||||
|
||||
@ -1899,7 +1899,7 @@ class RenderWebGL extends EventEmitter {
|
||||
|
||||
if (uniforms.u_skin) {
|
||||
twgl.setTextureParameters(
|
||||
gl, uniforms.u_skin, {minMag: drawable.useNearest(drawableScale) ? gl.NEAREST : gl.LINEAR}
|
||||
gl, uniforms.u_skin, {minMag: drawable.skin.useNearest(drawableScale) ? gl.NEAREST : gl.LINEAR}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ const twgl = require('twgl.js');
|
||||
|
||||
const Skin = require('./Skin');
|
||||
const SvgRenderer = require('scratch-svg-renderer').SVGRenderer;
|
||||
const ShaderManager = require('./ShaderManager');
|
||||
|
||||
const MAX_TEXTURE_DIMENSION = 2048;
|
||||
|
||||
@ -58,6 +59,33 @@ class SVGSkin extends Skin {
|
||||
return this._svgRenderer.size;
|
||||
}
|
||||
|
||||
// Because SVG skins' bounding boxes are currently not pixel-aligned, the idea here is to hide blurriness
|
||||
// by using nearest-neighbor scaling if one screen-space pixel is "close enough" to one texture pixel.
|
||||
useNearest (scale) {
|
||||
// If the effect bits for mosaic, pixelate, whirl, or fisheye are set, use linear
|
||||
if ((this.enabledEffects & (
|
||||
ShaderManager.EFFECT_INFO.fisheye.mask |
|
||||
ShaderManager.EFFECT_INFO.whirl.mask |
|
||||
ShaderManager.EFFECT_INFO.pixelate.mask |
|
||||
ShaderManager.EFFECT_INFO.mosaic.mask
|
||||
)) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can't use nearest neighbor unless we are a multiple of 90 rotation
|
||||
if (this._direction % 90 !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the scale of the skin is very close to 100 (0.99999 variance is okay I guess)
|
||||
// TODO: Make this check more precise. Mipmaps complicate this somewhat.
|
||||
if (Math.abs(scale[0]) > 99 && Math.abs(scale[0]) < 101 &&
|
||||
Math.abs(scale[1]) > 99 && Math.abs(scale[1]) < 101) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MIP for a given scale.
|
||||
* @param {number} scale - The relative size of the MIP
|
||||
|
||||
19
src/Skin.js
19
src/Skin.js
@ -59,13 +59,6 @@ class Skin extends EventEmitter {
|
||||
this._id = RenderConstants.ID_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean} true for a raster-style skin (like a BitmapSkin), false for vector-style (like SVGSkin).
|
||||
*/
|
||||
get isRaster () {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {int} the unique ID for this Skin.
|
||||
*/
|
||||
@ -88,6 +81,18 @@ class Skin extends EventEmitter {
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this skin's texture be filtered with nearest-neighbor or linear interpolation at the given scale?
|
||||
* @param {?Array<Number>} scale The screen-space X and Y scaling factors at which this skin's texture will be
|
||||
* displayed, as percentages (100 means 1 "native size" unit is 1 screen pixel; 200 means 2 screen pixels, etc).
|
||||
* @return {boolean} True if this skin's texture, as returned by {@link getTexture}, should be filtered with
|
||||
* nearest-neighbor interpolation.
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
useNearest (scale) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the center of the current bounding box
|
||||
* @return {Array<number>} the center of the current bounding box
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user