diff --git a/src/BitmapSkin.js b/src/BitmapSkin.js index 63cf8fc..ecd2dc9 100644 --- a/src/BitmapSkin.js +++ b/src/BitmapSkin.js @@ -39,6 +39,13 @@ 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} the "native" size, in texels, of this skin. */ @@ -71,11 +78,9 @@ class BitmapSkin extends Skin { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmapData); this._silhouette.update(bitmapData); } else { + // TODO: mipmaps? const textureOptions = { auto: true, - mag: gl.NEAREST, - /** @todo mipmaps, linear (except pixelate) */ - min: gl.NEAREST, wrap: gl.CLAMP_TO_EDGE, src: bitmapData }; diff --git a/src/PenSkin.js b/src/PenSkin.js index 2c2a5d8..e67fc00 100644 --- a/src/PenSkin.js +++ b/src/PenSkin.js @@ -72,6 +72,13 @@ 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} the "native" size, in texels, of this skin. [width, height] */ diff --git a/src/RenderWebGL.js b/src/RenderWebGL.js index a3d177c..7372425 100644 --- a/src/RenderWebGL.js +++ b/src/RenderWebGL.js @@ -1096,6 +1096,14 @@ class RenderWebGL extends EventEmitter { * @private */ _drawThese (drawables, drawMode, projection, opts = {}) { + + const near = function (a, b, relativeTolerance = 0.01) { + const absA = Math.abs(a); + const absB = Math.abs(b); + const error = Math.abs(a - b) / Math.max(absA, absB); + return error < relativeTolerance; + }; + const gl = this._gl; let currentShader = null; @@ -1117,6 +1125,8 @@ class RenderWebGL extends EventEmitter { // If the skin or texture isn't ready yet, skip it. if (!drawable.skin || !drawable.skin.getTexture(drawableScale)) continue; + const uniforms = {}; + let effectBits = drawable.getEnabledEffects(); effectBits &= opts.hasOwnProperty('effectMask') ? opts.effectMask : effectBits; const newShader = this._shaderManager.getShader(drawMode, effectBits); @@ -1124,18 +1134,29 @@ class RenderWebGL extends EventEmitter { currentShader = newShader; gl.useProgram(currentShader.program); twgl.setBuffersAndAttributes(gl, currentShader, this._bufferInfo); - twgl.setUniforms(currentShader, {u_projectionMatrix: projection}); - twgl.setUniforms(currentShader, {u_fudge: window.fudge || 0}); + Object.assign(uniforms, { + u_projectionMatrix: projection, + u_fudge: window.fudge || 0 + }); } - twgl.setUniforms(currentShader, drawable.skin.getUniforms(drawableScale)); - twgl.setUniforms(currentShader, drawable.getUniforms()); + Object.assign(uniforms, + drawable.skin.getUniforms(drawableScale), + drawable.getUniforms()); // Apply extra uniforms after the Drawable's, to allow overwriting. if (opts.extraUniforms) { - twgl.setUniforms(currentShader, opts.extraUniforms); + Object.assign(uniforms, opts.extraUniforms); } + if (uniforms.u_skin) { + const useNearest = + (drawable._direction % 90 === 0) && (near(drawableScale, 100) || drawable.skin.isRaster); + twgl.setTextureParameters(gl, uniforms.u_skin, {minMag: useNearest ? gl.NEAREST : gl.LINEAR}); + } + + twgl.setUniforms(currentShader, uniforms); + twgl.drawBufferInfo(gl, this._bufferInfo, gl.TRIANGLES); } } diff --git a/src/SVGSkin.js b/src/SVGSkin.js index 235dde3..186eb16 100644 --- a/src/SVGSkin.js +++ b/src/SVGSkin.js @@ -81,10 +81,9 @@ class SVGSkin extends Skin { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._svgRenderer.canvas); this._silhouette.update(this._svgRenderer.canvas); } else { + // TODO: mipmaps? const textureOptions = { auto: true, - mag: gl.NEAREST, - min: gl.NEAREST, /** @todo mipmaps, linear (except pixelate) */ wrap: gl.CLAMP_TO_EDGE, src: this._svgRenderer.canvas }; diff --git a/src/Skin.js b/src/Skin.js index d0bc940..861828a 100644 --- a/src/Skin.js +++ b/src/Skin.js @@ -62,6 +62,13 @@ 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. */