Skip to content

Commit 304ee90

Browse files
authored
Merge pull request #6541 from davepagurek/fix/vertex-color-transparency
Check for per vertex transparency when blending
2 parents 4b255e2 + e9fb178 commit 304ee90

File tree

5 files changed

+78
-7
lines changed

5 files changed

+78
-7
lines changed

src/webgl/material.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,14 +1279,17 @@ p5.prototype.metalness = function (metallic) {
12791279
* @private blends colors according to color components.
12801280
* If alpha value is less than 1, or non-standard blendMode
12811281
* we need to enable blending on our gl context.
1282-
* @param {Number[]} color [description]
1283-
* @return {Number[]} Normalized numbers array
1282+
* @param {Number[]} color The currently set color, with values in 0-1 range
1283+
* @param {Boolean} [hasTransparency] Whether the shape being drawn has other
1284+
* transparency internally, e.g. via vertex colors
1285+
* @return {Number[]]} Normalized numbers array
12841286
*/
1285-
p5.RendererGL.prototype._applyColorBlend = function (colors) {
1287+
p5.RendererGL.prototype._applyColorBlend = function(colors, hasTransparency) {
12861288
const gl = this.GL;
12871289

12881290
const isTexture = this.drawMode === constants.TEXTURE;
12891291
const doBlend =
1292+
hasTransparency ||
12901293
this.userFillShader ||
12911294
this.userStrokeShader ||
12921295
this.userPointShader ||

src/webgl/p5.Geometry.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,19 @@ p5.Geometry = class Geometry {
6666
this.detailY = detailY !== undefined ? detailY : 1;
6767
this.dirtyFlags = {};
6868

69+
this._hasFillTransparency = undefined;
70+
this._hasStrokeTransparency = undefined;
71+
6972
if (callback instanceof Function) {
7073
callback.call(this);
7174
}
7275
return this; // TODO: is this a constructor?
7376
}
7477

7578
reset() {
79+
this._hasFillTransparency = undefined;
80+
this._hasStrokeTransparency = undefined;
81+
7682
this.lineVertices.clear();
7783
this.lineTangentsIn.clear();
7884
this.lineTangentsOut.clear();
@@ -88,6 +94,32 @@ p5.Geometry = class Geometry {
8894

8995
this.dirtyFlags = {};
9096
}
97+
98+
hasFillTransparency() {
99+
if (this._hasFillTransparency === undefined) {
100+
this._hasFillTransparency = false;
101+
for (let i = 0; i < this.vertexColors.length; i += 4) {
102+
if (this.vertexColors[i + 3] < 1) {
103+
this._hasFillTransparency = true;
104+
break;
105+
}
106+
}
107+
}
108+
return this._hasFillTransparency;
109+
}
110+
hasStrokeTransparency() {
111+
if (this._hasStrokeTransparency === undefined) {
112+
this._hasStrokeTransparency = false;
113+
for (let i = 0; i < this.lineVertexColors.length; i += 4) {
114+
if (this.lineVertexColors[i + 3] < 1) {
115+
this._hasStrokeTransparency = true;
116+
break;
117+
}
118+
}
119+
}
120+
return this._hasStrokeTransparency;
121+
}
122+
91123
/**
92124
* Removes the internal colors of p5.Geometry.
93125
* Using `clearColors()`, you can use `fill()` to supply new colors before drawing each shape.

src/webgl/p5.RendererGL.Immediate.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,10 @@ p5.RendererGL.prototype._drawImmediateFill = function(count = 1) {
519519
}
520520
shader.disableRemainingAttributes();
521521

522-
this._applyColorBlend(this.curFillColor);
522+
this._applyColorBlend(
523+
this.curFillColor,
524+
this.immediateMode.geometry.hasFillTransparency()
525+
);
523526

524527
if (count === 1) {
525528
gl.drawArrays(
@@ -561,7 +564,10 @@ p5.RendererGL.prototype._drawImmediateStroke = function() {
561564
buff._prepareBuffer(this.immediateMode.geometry, shader);
562565
}
563566
shader.disableRemainingAttributes();
564-
this._applyColorBlend(this.curStrokeColor);
567+
this._applyColorBlend(
568+
this.curStrokeColor,
569+
this.immediateMode.geometry.hasFillTransparency()
570+
);
565571

566572
gl.drawArrays(
567573
gl.TRIANGLES,

src/webgl/p5.RendererGL.Retained.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ p5.RendererGL.prototype.drawBuffers = function(gId) {
143143
//vertex index buffer
144144
this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER);
145145
}
146-
this._applyColorBlend(this.curFillColor);
146+
this._applyColorBlend(
147+
this.curFillColor,
148+
geometry.model.hasFillTransparency()
149+
);
147150
this._drawElements(gl.TRIANGLES, gId);
148151
fillShader.unbindShader();
149152
}
@@ -156,7 +159,10 @@ p5.RendererGL.prototype.drawBuffers = function(gId) {
156159
buff._prepareBuffer(geometry, strokeShader);
157160
}
158161
strokeShader.disableRemainingAttributes();
159-
this._applyColorBlend(this.curStrokeColor);
162+
this._applyColorBlend(
163+
this.curStrokeColor,
164+
geometry.model.hasStrokeTransparency()
165+
);
160166
this._drawArrays(gl.TRIANGLES, gId);
161167
strokeShader.unbindShader();
162168
}

test/unit/webgl/p5.RendererGL.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,30 @@ suite('p5.RendererGL', function() {
12581258
assert.deepEqual(myp5.get(16, 16), [255, 0, 255, 255]);
12591259
done();
12601260
});
1261+
1262+
test('transparency works the same with per-vertex colors', function() {
1263+
myp5.createCanvas(20, 20, myp5.WEBGL);
1264+
myp5.noStroke();
1265+
1266+
function drawShapes() {
1267+
myp5.fill(255, 0, 0, 100);
1268+
myp5.rect(-10, -10, 15, 15);
1269+
myp5.fill(0, 0, 255, 100);
1270+
myp5.rect(-5, -5, 15, 15);
1271+
}
1272+
1273+
drawShapes();
1274+
myp5.loadPixels();
1275+
const eachShapeResult = [...myp5.pixels];
1276+
1277+
myp5.clear();
1278+
const shapes = myp5.buildGeometry(drawShapes);
1279+
myp5.model(shapes);
1280+
myp5.loadPixels();
1281+
const singleShapeResult = [...myp5.pixels];
1282+
1283+
assert.deepEqual(eachShapeResult, singleShapeResult);
1284+
});
12611285
});
12621286

12631287
suite('BufferDef', function() {

0 commit comments

Comments
 (0)