Skip to content

Commit be19324

Browse files
committed
Check for per vertex transparency when blending
1 parent 17304ce commit be19324

File tree

5 files changed

+77
-6
lines changed

5 files changed

+77
-6
lines changed

src/webgl/material.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,14 +1177,17 @@ p5.prototype.shininess = function(shine) {
11771177
* @private blends colors according to color components.
11781178
* If alpha value is less than 1, or non-standard blendMode
11791179
* we need to enable blending on our gl context.
1180-
* @param {Number[]} color [description]
1180+
* @param {Number[]} color The currently set color, with values in 0-1 range
1181+
* @param {Boolean} [hasTransparency] Whether the shape being drawn has other
1182+
* transparency internally, e.g. via vertex colors
11811183
* @return {Number[]]} Normalized numbers array
11821184
*/
1183-
p5.RendererGL.prototype._applyColorBlend = function(colors) {
1185+
p5.RendererGL.prototype._applyColorBlend = function(colors, hasTransparency) {
11841186
const gl = this.GL;
11851187

11861188
const isTexture = this.drawMode === constants.TEXTURE;
11871189
const doBlend =
1190+
hasTransparency ||
11881191
this.userFillShader ||
11891192
this.userStrokeShader ||
11901193
this.userPointShader ||

src/webgl/p5.Geometry.js

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

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

7477
reset() {
78+
this._hasFillTransparency = undefined;
79+
this._hasStrokeTransparency = undefined;
80+
7581
this.lineVertices.clear();
7682
this.lineTangentsIn.clear();
7783
this.lineTangentsOut.clear();
@@ -87,6 +93,32 @@ p5.Geometry = class Geometry {
8793

8894
this.dirtyFlags = {};
8995
}
96+
97+
hasFillTransparency() {
98+
if (this._hasFillTransparency === undefined) {
99+
this._hasFillTransparency = false;
100+
for (let i = 0; i < this.vertexColors.length; i += 4) {
101+
if (this.vertexColors[i + 3] < 1) {
102+
this._hasFillTransparency = true;
103+
break;
104+
}
105+
}
106+
}
107+
return this._hasFillTransparency;
108+
}
109+
hasStrokeTransparency() {
110+
if (this._hasStrokeTransparency === undefined) {
111+
this._hasStrokeTransparency = false;
112+
for (let i = 0; i < this.lineVertexColors.length; i += 4) {
113+
if (this.lineVertexColors[i + 3] < 1) {
114+
this._hasStrokeTransparency = true;
115+
break;
116+
}
117+
}
118+
}
119+
return this._hasStrokeTransparency;
120+
}
121+
90122
/**
91123
* Removes the internal colors of p5.Geometry.
92124
* 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
@@ -518,7 +518,10 @@ p5.RendererGL.prototype._drawImmediateFill = function(count = 1) {
518518
}
519519
shader.disableRemainingAttributes();
520520

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

523526
if (count === 1) {
524527
gl.drawArrays(
@@ -560,7 +563,10 @@ p5.RendererGL.prototype._drawImmediateStroke = function() {
560563
buff._prepareBuffer(this.immediateMode.geometry, shader);
561564
}
562565
shader.disableRemainingAttributes();
563-
this._applyColorBlend(this.curStrokeColor);
566+
this._applyColorBlend(
567+
this.curStrokeColor,
568+
this.immediateMode.geometry.hasFillTransparency()
569+
);
564570

565571
gl.drawArrays(
566572
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
@@ -1137,6 +1137,30 @@ suite('p5.RendererGL', function() {
11371137
assert.deepEqual(myp5.get(16, 16), [255, 0, 255, 255]);
11381138
done();
11391139
});
1140+
1141+
test('transparency works the same with per-vertex colors', function() {
1142+
myp5.createCanvas(20, 20, myp5.WEBGL);
1143+
myp5.noStroke();
1144+
1145+
function drawShapes() {
1146+
myp5.fill(255, 0, 0, 100);
1147+
myp5.rect(-10, -10, 15, 15);
1148+
myp5.fill(0, 0, 255, 100);
1149+
myp5.rect(-5, -5, 15, 15);
1150+
}
1151+
1152+
drawShapes();
1153+
myp5.loadPixels();
1154+
const eachShapeResult = [...myp5.pixels];
1155+
1156+
myp5.clear();
1157+
const shapes = myp5.buildGeometry(drawShapes);
1158+
myp5.model(shapes);
1159+
myp5.loadPixels();
1160+
const singleShapeResult = [...myp5.pixels];
1161+
1162+
assert.deepEqual(eachShapeResult, singleShapeResult);
1163+
});
11401164
});
11411165

11421166
suite('BufferDef', function() {

0 commit comments

Comments
 (0)