From c24cfaaf4c9bae289921748b3d31311d3059c9ab Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Thu, 26 May 2016 09:53:22 -0700 Subject: [PATCH] Fix pixelate "pixel" size Pixelate still needs a bit more work: at certain scales the edges of the "pixels" are ragged. This happens in Scratch 2.0 as well, but for me it seems slightly worse in this implementation. --- src/Drawable.js | 29 ++++++++++++----------------- src/shaders/sprite.frag | 9 +++------ 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/Drawable.js b/src/Drawable.js index e79452d..70c9928 100644 --- a/src/Drawable.js +++ b/src/Drawable.js @@ -29,15 +29,9 @@ function Drawable(renderer, gl) { */ u_mvp: twgl.m4.identity(), - /** - * The scaling factor to use when drawing. - * This is updated at the same time as u_mvp. - * @type {number} - */ - u_scale: 1, - /** * The nominal (not necessarily current) size of the current skin. + * This is scaled by _costumeResolution. * @type {number[]} */ u_skinSize: [0, 0], @@ -62,7 +56,6 @@ function Drawable(renderer, gl) { this._direction = 90; this._transformDirty = true; this._shaderIndex = 0; - this._costumeResolution = 2; // TODO: only for bitmaps this.setSkin(Drawable._DEFAULT_SKIN); } @@ -297,23 +290,23 @@ Drawable.prototype._setSkinSVG = function (skin_md5ext) { /** * Common code for setting all skin types. * @param {string|Image} source The source of image data for the skin. - * @param costumeResolution {int} The resolution to use for this skin. + * @param {int} costumeResolution The resolution to use for this skin. * @private */ Drawable.prototype._setSkinCore = function (source, costumeResolution) { var instance = this; var callback = function (err, texture, source) { if (!err) { - instance._costumeResolution = costumeResolution || 1; instance._uniforms.u_texture = texture; - instance._setSkinSize(source.width, source.height); + instance._setSkinSize( + source.width, source.height, costumeResolution); } }; var options = { auto: true, mag: this._gl.NEAREST, - min: this._gl.LINEAR, // TODO: mipmaps + min: this._gl.NEAREST, // TODO: mipmaps, linear (except pixelate) src: source }; var willCallCallback = typeof source == 'string'; @@ -390,9 +383,13 @@ Drawable.prototype.updateProperties = function (properties) { * Set the dimensions of this Drawable's skin. * @param {int} width The width of the new skin. * @param {int} height The height of the new skin. + * @param {int} costumeResolution The resolution to use for this skin. * @private */ -Drawable.prototype._setSkinSize = function (width, height) { +Drawable.prototype._setSkinSize = function (width, height, costumeResolution) { + costumeResolution = costumeResolution || 1; + width /= costumeResolution; + height /= costumeResolution; if (this._uniforms.u_skinSize[0] != width || this._uniforms.u_skinSize[1] != height) { this._uniforms.u_skinSize[0] = width; @@ -414,10 +411,8 @@ Drawable.prototype._calculateTransform = function () { var rotation = (270 - this._direction) * Math.PI / 180; twgl.m4.rotateZ(mvp, rotation, mvp); - var scale = this._scale / 100; - scale /= this._costumeResolution; - this._uniforms.u_scale = scale; - var scaledSize = twgl.v3.mulScalar(this._uniforms.u_skinSize, scale); + var scaledSize = twgl.v3.mulScalar( + this._uniforms.u_skinSize, this._scale / 100); scaledSize[2] = 0; // was NaN because u_skinSize has only 2 components twgl.m4.scale(mvp, scaledSize, mvp); diff --git a/src/shaders/sprite.frag b/src/shaders/sprite.frag index a762a16..d5db7c5 100644 --- a/src/shaders/sprite.frag +++ b/src/shaders/sprite.frag @@ -13,7 +13,6 @@ uniform float u_whirl; #endif #ifdef ENABLE_pixelate uniform float u_pixelate; -uniform float u_scale; uniform vec2 u_skinSize; #endif #ifdef ENABLE_mosaic @@ -27,7 +26,6 @@ uniform float u_ghost; #endif uniform sampler2D u_skin; -#define u_pixelate_half vec2(0.5,0.5) // TODO varying vec2 v_texCoord; @@ -83,10 +81,9 @@ void main() #ifdef ENABLE_pixelate { - // TODO: understand why this padding helps clean up "pixel" edges - const vec2 pixelPadding = vec2(0.125, 0.125); - vec2 pixelTexelSize = u_skinSize * u_scale / u_pixelate; - texcoord0 = (floor(texcoord0 * pixelTexelSize + pixelPadding)) / pixelTexelSize; + // TODO: clean up "pixel" edges + vec2 pixelTexelSize = u_skinSize / u_pixelate; + texcoord0 = (floor(texcoord0 * pixelTexelSize) + kCenter) / pixelTexelSize; } #endif // ENABLE_pixelate