diff --git a/src/webgl/material.js b/src/webgl/material.js index 4435fc741e..8048c7d315 100644 --- a/src/webgl/material.js +++ b/src/webgl/material.js @@ -782,14 +782,19 @@ p5.RendererGL.prototype._applyColorBlend = function(colors) { const gl = this.GL; const isTexture = this.drawMode === constants.TEXTURE; - if (isTexture || colors[colors.length - 1] < 1.0 || this._isErasing) { - gl.depthMask(isTexture); - gl.enable(gl.BLEND); - this._applyBlendMode(); - } else { - gl.depthMask(true); - gl.disable(gl.BLEND); + const doBlend = + isTexture || colors[colors.length - 1] < 1.0 || this._isErasing; + if (doBlend !== this._isBlending) { + if (doBlend) { + gl.depthMask(isTexture); + gl.enable(gl.BLEND); + } else { + gl.depthMask(true); + gl.disable(gl.BLEND); + } + this._isBlending = doBlend; } + this._applyBlendMode(); return colors; }; @@ -799,6 +804,9 @@ p5.RendererGL.prototype._applyColorBlend = function(colors) { * @return {Number[]]} Normalized numbers array */ p5.RendererGL.prototype._applyBlendMode = function() { + if (this._cachedBlendMode === this.curBlendMode) { + return; + } const gl = this.GL; switch (this.curBlendMode) { case constants.BLEND: @@ -861,6 +869,7 @@ p5.RendererGL.prototype._applyBlendMode = function() { ); break; } + this._cachedBlendMode = this.curBlendMode; }; export default p5; diff --git a/src/webgl/p5.RendererGL.Retained.js b/src/webgl/p5.RendererGL.Retained.js index cb499821c6..4daa99c307 100644 --- a/src/webgl/p5.RendererGL.Retained.js +++ b/src/webgl/p5.RendererGL.Retained.js @@ -130,8 +130,8 @@ p5.RendererGL.prototype._prepareBuffers = function(buffers, shader, defs) { gl.deleteBuffer(buffer); buffers[def.dst] = null; } - // disable the vertex - gl.disableVertexAttribArray(attr.index); + // no need to disable + // gl.disableVertexAttribArray(attr.index); } } }; diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index dd8b73b63f..c49deb6eed 100755 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -63,6 +63,9 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) { this._setAttributeDefaults(pInst); this._initContext(); this.isP3D = true; //lets us know we're in 3d mode + + // This redundant property is useful in reminding you that you are + // interacting with WebGLRenderingContext, still worth considering future removal this.GL = this.drawingContext; // erasing @@ -94,8 +97,10 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) { this.curFillColor = this._cachedFillStyle = [1, 1, 1, 1]; this.curStrokeColor = this._cachedStrokeStyle = [0, 0, 0, 1]; - this.curBlendMode = this._cachedBlendMode = constants.BLEND; + this.curBlendMode = constants.BLEND; + this._cachedBlendMode = undefined; this.blendExt = this.GL.getExtension('EXT_blend_minmax'); + this._isBlending = false; this._useSpecularMaterial = false; this._useEmissiveMaterial = false; @@ -169,6 +174,9 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) { this.fontInfos = {}; + this._cachedBackground = undefined; + this._curShader = undefined; + return this; }; @@ -533,13 +541,19 @@ p5.RendererGL.prototype._update = function() { */ p5.RendererGL.prototype.background = function(...args) { const _col = this._pInst.color(...args); - const _r = _col.levels[0] / 255; - const _g = _col.levels[1] / 255; - const _b = _col.levels[2] / 255; - const _a = _col.levels[3] / 255; - this.GL.clearColor(_r, _g, _b, _a); - this.GL.depthMask(true); - this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT); + const needsUpdate = + this._cachedBackground === undefined || + !this._arraysEqual(_col._array, this._cachedBackground); + if (needsUpdate) { + const _r = _col.levels[0] / 255; + const _g = _col.levels[1] / 255; + const _b = _col.levels[2] / 255; + const _a = _col.levels[3] / 255; + this.GL.clearColor(_r, _g, _b, _a); + this.GL.depthMask(true); + this._cachedBackground = _col._array.slice(0); + } + this.GL.clear(this.GL.COLOR_BUFFER_BIT); }; ////////////////////////////////////////////// @@ -1293,6 +1307,24 @@ p5.RendererGL.prototype._bindBuffer = function( /////////////////////////////// //// UTILITY FUNCTIONS ////////////////////////////// +p5.RendererGL.prototype._arraysEqual = function(a, b) { + const aLength = a.length; + if (aLength !== b.length) return false; + for (let i = 0; i < aLength; i++) { + if (a[i] !== b[i]) return false; + } + return true; +}; + +p5.RendererGL.prototype._isTypedArray = function(arr) { + let res = false; + res = arr instanceof Float32Array; + res = arr instanceof Float64Array; + res = arr instanceof Int16Array; + res = arr instanceof Uint16Array; + res = arr instanceof Uint32Array; + return res; +}; /** * turn a two dimensional array into one dimensional array * @private diff --git a/src/webgl/p5.Shader.js b/src/webgl/p5.Shader.js index e4ea4a4b49..53f79e5f42 100644 --- a/src/webgl/p5.Shader.js +++ b/src/webgl/p5.Shader.js @@ -171,11 +171,19 @@ p5.Shader.prototype._loadUniforms = function() { } uniform.name = uniformName; uniform.type = uniformInfo.type; + uniform._cachedData = undefined; if (uniform.type === gl.SAMPLER_2D) { uniform.samplerIndex = samplerIndex; samplerIndex++; this.samplers.push(uniform); } + uniform.isArray = + uniform.type === gl.FLOAT_MAT3 || + uniform.type === gl.FLOAT_MAT4 || + uniform.type === gl.INT_VEC2 || + uniform.type === gl.INT_VEC3 || + uniform.type === gl.INT_VEC4; + this.uniforms[uniformName] = uniform; } this._loadedUniforms = true; @@ -274,7 +282,10 @@ p5.Shader.prototype._setMatrixUniforms = function() { */ p5.Shader.prototype.useProgram = function() { const gl = this._renderer.GL; - gl.useProgram(this._glProgram); + if (this._renderer._curShader !== this) { + gl.useProgram(this._glProgram); + this._renderer._curShader = this; + } return this; }; @@ -341,16 +352,29 @@ p5.Shader.prototype.useProgram = function() { * canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed. */ p5.Shader.prototype.setUniform = function(uniformName, data) { - //@todo update all current gl.uniformXX calls - const uniform = this.uniforms[uniformName]; if (!uniform) { return; } + const gl = this._renderer.GL; + + if (uniform.isArray) { + if ( + uniform._cachedData && + this._renderer._arraysEqual(uniform._cachedData, data) + ) { + return; + } else { + uniform._cachedData = data.slice(0); + } + } else if (uniform._cachedData && uniform._cachedData === data) { + return; + } else { + uniform._cachedData = data; + } const location = uniform.location; - const gl = this._renderer.GL; this.useProgram(); switch (uniform.type) { @@ -507,8 +531,11 @@ p5.Shader.prototype.enableAttrib = function( const loc = attr.location; if (loc !== -1) { const gl = this._renderer.GL; - gl.enableVertexAttribArray(loc); - gl.vertexAttribPointer( + if (!attr.enabled) { + gl.enableVertexAttribArray(loc); + attr.enabled = true; + } + this._renderer.GL.vertexAttribPointer( loc, size, type || gl.FLOAT, diff --git a/test/manual-test-examples/webgl/interaction/orbitControl/sketch.js b/test/manual-test-examples/webgl/interaction/orbitControl/sketch.js deleted file mode 100644 index e24677cfab..0000000000 --- a/test/manual-test-examples/webgl/interaction/orbitControl/sketch.js +++ /dev/null @@ -1,33 +0,0 @@ -function setup() { - createCanvas(windowWidth, windowHeight, WEBGL); - - // controls should work whether or not camera center is set to (0,0,0) - // camera(0, 0, 500, 300, 0, 0, 0, 1, 0); -} - -function draw() { - background(250); - var radius = width; - - orbitControl(1, 1, 0.1); - - normalMaterial(); - - let scale = 200; - for (let px = -5; px < 5; px++) { - for (let pz = -5; pz < 5; pz++) { - push(); - rotateX(PI); - translate(px * scale, 0, pz * scale); - if (px > 0) { - fill(255, 0, 0); - } - if (px === 0 && pz === 0) { - cone(50, 100); - } else { - cone(20, 50); - } - pop(); - } - } -} diff --git a/test/manual-test-examples/webgl/lights/noLights/index.html b/test/manual-test-examples/webgl/lights/noLights/index.html deleted file mode 100644 index ef2cf9f556..0000000000 --- a/test/manual-test-examples/webgl/lights/noLights/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - -
- - -