diff --git a/src/webgl/p5.RendererGL.Immediate.js b/src/webgl/p5.RendererGL.Immediate.js index 9da349f494..726023d651 100644 --- a/src/webgl/p5.RendererGL.Immediate.js +++ b/src/webgl/p5.RendererGL.Immediate.js @@ -368,6 +368,7 @@ p5.RendererGL.prototype._tesselateShape = function() { */ p5.RendererGL.prototype._drawImmediateFill = function() { const gl = this.GL; + this._useVertexColor = (this.immediateMode.geometry.vertexColors.length > 0); const shader = this._getImmediateFillShader(); this._setFillUniforms(shader); diff --git a/src/webgl/p5.RendererGL.Retained.js b/src/webgl/p5.RendererGL.Retained.js index 05b9673f45..1cea90431c 100644 --- a/src/webgl/p5.RendererGL.Retained.js +++ b/src/webgl/p5.RendererGL.Retained.js @@ -130,6 +130,7 @@ p5.RendererGL.prototype.drawBuffers = function(gId) { } if (this._doFill) { + this._useVertexColor = (geometry.model.vertexColors.length > 0); const fillShader = this._getRetainedFillShader(); this._setFillUniforms(fillShader); for (const buff of this.retainedMode.buffers.fill) { diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index 4cfb73cec3..ccfac0df9c 100755 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -111,6 +111,7 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) { this._useShininess = 1; this._useLineColor = false; + this._useVertexColor = false; this._tint = [255, 255, 255, 255]; @@ -1270,6 +1271,7 @@ p5.RendererGL.prototype._setFillUniforms = function(fillShader) { fillShader.bindShader(); // TODO: optimize + fillShader.setUniform('uUseVertexColor', this._useVertexColor); fillShader.setUniform('uMaterialColor', this.curFillColor); fillShader.setUniform('isTexture', !!this._tex); if (this._tex) { diff --git a/src/webgl/shaders/basic.frag b/src/webgl/shaders/basic.frag index fa6646fa2a..be191e1c34 100644 --- a/src/webgl/shaders/basic.frag +++ b/src/webgl/shaders/basic.frag @@ -1,5 +1,5 @@ precision mediump float; -uniform vec4 uMaterialColor; +varying vec4 vColor; void main(void) { - gl_FragColor = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a; + gl_FragColor = vec4(vColor.rgb, 1.) * vColor.a; } diff --git a/src/webgl/shaders/light.vert b/src/webgl/shaders/light.vert index 5a756684c7..b79713cd26 100644 --- a/src/webgl/shaders/light.vert +++ b/src/webgl/shaders/light.vert @@ -3,14 +3,19 @@ attribute vec3 aPosition; attribute vec3 aNormal; attribute vec2 aTexCoord; +attribute vec4 aVertexColor; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; uniform mat3 uNormalMatrix; +uniform bool uUseVertexColor; +uniform vec4 uMaterialColor; + varying highp vec2 vVertTexCoord; varying vec3 vDiffuseColor; varying vec3 vSpecularColor; +varying vec4 vColor; void main(void) { @@ -27,4 +32,6 @@ void main(void) { vDiffuseColor += uAmbientColor[i]; } } + + vColor = (uUseVertexColor ? aVertexColor : uMaterialColor); } diff --git a/src/webgl/shaders/light_texture.frag b/src/webgl/shaders/light_texture.frag index 11e5db5520..be31c6d732 100644 --- a/src/webgl/shaders/light_texture.frag +++ b/src/webgl/shaders/light_texture.frag @@ -1,6 +1,5 @@ precision highp float; -uniform vec4 uMaterialColor; uniform vec4 uTint; uniform sampler2D uSampler; uniform bool isTexture; @@ -9,13 +8,14 @@ uniform bool uEmissive; varying highp vec2 vVertTexCoord; varying vec3 vDiffuseColor; varying vec3 vSpecularColor; +varying vec4 vColor; void main(void) { if(uEmissive && !isTexture) { - gl_FragColor = uMaterialColor; + gl_FragColor = vColor; } else { - vec4 baseColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor; + vec4 baseColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : vColor; gl_FragColor = vec4(gl_FragColor.rgb * vDiffuseColor + vSpecularColor, 1.) * baseColor.a; } } diff --git a/src/webgl/shaders/normal.vert b/src/webgl/shaders/normal.vert index 9727a77eaf..8a94e83ed1 100644 --- a/src/webgl/shaders/normal.vert +++ b/src/webgl/shaders/normal.vert @@ -1,17 +1,23 @@ attribute vec3 aPosition; attribute vec3 aNormal; attribute vec2 aTexCoord; +attribute vec4 aVertexColor; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; uniform mat3 uNormalMatrix; +uniform vec4 uMaterialColor; +uniform bool uUseVertexColor; + varying vec3 vVertexNormal; varying highp vec2 vVertTexCoord; +varying vec4 vColor; void main(void) { vec4 positionVec4 = vec4(aPosition, 1.0); gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; vVertexNormal = normalize(vec3( uNormalMatrix * aNormal )); vVertTexCoord = aTexCoord; + vColor = (uUseVertexColor ? aVertexColor : uMaterialColor); } diff --git a/src/webgl/shaders/phong.frag b/src/webgl/shaders/phong.frag index 6f848f861c..497669965e 100644 --- a/src/webgl/shaders/phong.frag +++ b/src/webgl/shaders/phong.frag @@ -6,7 +6,6 @@ uniform vec4 uSpecularMatColor; uniform vec4 uAmbientMatColor; uniform vec4 uEmissiveMatColor; -uniform vec4 uMaterialColor; uniform vec4 uTint; uniform sampler2D uSampler; uniform bool isTexture; @@ -15,6 +14,7 @@ varying vec3 vNormal; varying vec2 vTexCoord; varying vec3 vViewPosition; varying vec3 vAmbientColor; +varying vec4 vColor; void main(void) { @@ -24,7 +24,7 @@ void main(void) { // Calculating final color as result of all lights (plus emissive term). - vec4 baseColor = isTexture ? texture2D(uSampler, vTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor; + vec4 baseColor = isTexture ? texture2D(uSampler, vTexCoord) * (uTint / vec4(255, 255, 255, 255)) : vColor; gl_FragColor = vec4(diffuse * baseColor.rgb + vAmbientColor * uAmbientMatColor.rgb + specular * uSpecularMatColor.rgb + diff --git a/src/webgl/shaders/phong.vert b/src/webgl/shaders/phong.vert index af6ab4fd2f..4a6a7f1400 100644 --- a/src/webgl/shaders/phong.vert +++ b/src/webgl/shaders/phong.vert @@ -4,6 +4,7 @@ precision highp int; attribute vec3 aPosition; attribute vec3 aNormal; attribute vec2 aTexCoord; +attribute vec4 aVertexColor; uniform vec3 uAmbientColor[5]; @@ -12,10 +13,14 @@ uniform mat4 uProjectionMatrix; uniform mat3 uNormalMatrix; uniform int uAmbientLightCount; +uniform bool uUseVertexColor; +uniform vec4 uMaterialColor; + varying vec3 vNormal; varying vec2 vTexCoord; varying vec3 vViewPosition; varying vec3 vAmbientColor; +varying vec4 vColor; void main(void) { @@ -35,4 +40,6 @@ void main(void) { vAmbientColor += uAmbientColor[i]; } } + + vColor = (uUseVertexColor ? aVertexColor : uMaterialColor); } diff --git a/test/unit/webgl/p5.RendererGL.js b/test/unit/webgl/p5.RendererGL.js index 2fe395c1fd..a46d0b2103 100644 --- a/test/unit/webgl/p5.RendererGL.js +++ b/test/unit/webgl/p5.RendererGL.js @@ -1109,6 +1109,147 @@ suite('p5.RendererGL', function() { }); }); + suite('interpolation of vertex colors', function(){ + test('immediate mode uses vertex colors (noLight)', function(done) { + const renderer = myp5.createCanvas(256, 256, myp5.WEBGL); + + // upper color: (200, 0, 0, 255); + // lower color: (0, 0, 200, 255); + // expected center color: (100, 0, 100, 255); + + myp5.beginShape(); + myp5.fill(200, 0, 0); + myp5.vertex(-128, -128); + myp5.fill(200, 0, 0); + myp5.vertex(128, -128); + myp5.fill(0, 0, 200); + myp5.vertex(128, 128); + myp5.fill(0, 0, 200); + myp5.vertex(-128, 128); + myp5.endShape(myp5.CLOSE); + + assert.equal(renderer._useVertexColor, true); + assert.deepEqual(myp5.get(128, 128), [100, 0, 100, 255]); + done(); + }); + + test('immediate mode uses vertex colors (light)', function(done) { + const renderer = myp5.createCanvas(256, 256, myp5.WEBGL); + + myp5.directionalLight(255, 255, 255, 0, 0, -1); + // diffuseFactor:0.73 + // so, expected color is (73, 0, 73, 255). + + myp5.beginShape(); + myp5.fill(200, 0, 0); + myp5.vertex(-128, -128); + myp5.fill(200, 0, 0); + myp5.vertex(128, -128); + myp5.fill(0, 0, 200); + myp5.vertex(128, 128); + myp5.fill(0, 0, 200); + myp5.vertex(-128, 128); + myp5.endShape(myp5.CLOSE); + + assert.equal(renderer._useVertexColor, true); + assert.deepEqual(myp5.get(128, 128), [73, 0, 73, 255]); + done(); + }); + + test('geom without vertex colors use curFillCol (noLight)', function(done) { + const renderer = myp5.createCanvas(256, 256, myp5.WEBGL); + + // expected center color is curFillColor. + + myp5.fill(200, 0, 200); + myp5.rectMode(myp5.CENTER); + myp5.rect(0, 0, myp5.width, myp5.height); + + assert.equal(renderer._useVertexColor, false); + assert.deepEqual(myp5.get(128, 128), [200, 0, 200, 255]); + done(); + }); + + test('geom without vertex colors use curFillCol (light)', function(done) { + const renderer = myp5.createCanvas(256, 256, myp5.WEBGL); + + myp5.directionalLight(255, 255, 255, 0, 0, -1); + // diffuseFactor:0.73 + // so, expected color is (146, 0, 146, 255). + + myp5.fill(200, 0, 200); + myp5.rectMode(myp5.CENTER); + myp5.rect(0, 0, myp5.width, myp5.height); + + assert.equal(renderer._useVertexColor, false); + assert.deepEqual(myp5.get(128, 128), [146, 0, 146, 255]); + done(); + }); + + test('geom with vertex colors use their color (noLight)', function(done) { + const renderer = myp5.createCanvas(256, 256, myp5.WEBGL); + + // upper color: (200, 0, 0, 255); + // lower color: (0, 0, 200, 255); + // expected center color: (100, 0, 100, 255); + + const myGeom = new p5.Geometry(1, 1, function() { + this.gid = 'vertexColorTestWithNoLights'; + this.vertices.push(myp5.createVector(-128, -128)); + this.vertices.push(myp5.createVector(128, -128)); + this.vertices.push(myp5.createVector(128, 128)); + this.vertices.push(myp5.createVector(-128, 128)); + this.faces.push([0, 1, 2]); + this.faces.push([0, 2, 3]); + this.vertexColors.push( + 200/255, 0, 0, 1, + 200/255, 0, 0, 1, + 0, 0, 200/255, 1, + 0, 0, 200/255, 1 + ); + this.computeNormals(); + }); + + myp5.noStroke(); + myp5.model(myGeom); + + assert.equal(renderer._useVertexColor, true); + assert.deepEqual(myp5.get(128, 128), [100, 0, 100, 255]); + done(); + }); + + test('geom with vertex colors use their color (light)', function(done) { + const renderer = myp5.createCanvas(256, 256, myp5.WEBGL); + + const myGeom = new p5.Geometry(1, 1, function() { + this.gid = 'vertexColorTestWithLighs'; + this.vertices.push(myp5.createVector(-128, -128)); + this.vertices.push(myp5.createVector(128, -128)); + this.vertices.push(myp5.createVector(128, 128)); + this.vertices.push(myp5.createVector(-128, 128)); + this.faces.push([0, 1, 2]); + this.faces.push([0, 2, 3]); + this.vertexColors.push( + 200/255, 0, 0, 1, + 200/255, 0, 0, 1, + 0, 0, 200/255, 1, + 0, 0, 200/255, 1 + ); + this.computeNormals(); + }); + + myp5.directionalLight(255, 255, 255, 0, 0, -1); + // diffuseFactor:0.73 + // so, expected color is (73, 0, 73, 255). + myp5.noStroke(); + myp5.model(myGeom); + + assert.equal(renderer._useVertexColor, true); + assert.deepEqual(myp5.get(128, 128), [73, 0, 73, 255]); + done(); + }); + }); + suite('setAttributes', function() { test('It leaves a reference to the correct canvas', function(done) { const renderer = myp5.createCanvas(10, 10, myp5.WEBGL);