Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn on premultiplied alpha (and alpha) by default #5917

Merged
merged 3 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions src/webgl/material.js
Original file line number Diff line number Diff line change
Expand Up @@ -1086,28 +1086,23 @@ p5.RendererGL.prototype._applyBlendMode = function() {
switch (this.curBlendMode) {
case constants.BLEND:
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
break;
case constants.ADD:
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.blendFunc(gl.ONE, gl.ONE);
break;
case constants.REMOVE:
gl.blendEquation(gl.FUNC_REVERSE_SUBTRACT);
gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_ALPHA);
break;
case constants.MULTIPLY:
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
gl.blendFuncSeparate(
gl.DST_COLOR,
gl.ONE_MINUS_SRC_ALPHA,
gl.ONE,
gl.ONE_MINUS_SRC_ALPHA
);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA);
break;
case constants.SCREEN:
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE_MINUS_DST_COLOR, gl.ONE, gl.ONE, gl.ONE);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR);
break;
case constants.EXCLUSION:
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
Expand All @@ -1124,7 +1119,7 @@ p5.RendererGL.prototype._applyBlendMode = function() {
break;
case constants.SUBTRACT:
gl.blendEquationSeparate(gl.FUNC_REVERSE_SUBTRACT, gl.FUNC_ADD);
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE);
gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
break;
case constants.DARKEST:
if (this.blendExt) {
Expand Down
10 changes: 5 additions & 5 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,11 @@ p5.RendererGL.prototype._setAttributeDefaults = function(pInst) {
// See issue #3850, safer to enable AA in Safari
const applyAA = navigator.userAgent.toLowerCase().includes('safari');
const defaults = {
alpha: false,
alpha: true,
depth: true,
stencil: true,
antialias: applyAA,
premultipliedAlpha: false,
premultipliedAlpha: true,
preserveDrawingBuffer: true,
perPixelLighting: true
};
Expand Down Expand Up @@ -342,7 +342,7 @@ p5.RendererGL.prototype._resetContext = function(options, callback) {
* The available attributes are:
* <br>
* alpha - indicates if the canvas contains an alpha buffer
* default is false
* default is true
*
* depth - indicates whether the drawing buffer has a depth buffer
* of at least 16 bits - default is true
Expand All @@ -355,7 +355,7 @@ p5.RendererGL.prototype._resetContext = function(options, callback) {
*
* premultipliedAlpha - indicates that the page compositor will assume
* the drawing buffer contains colors with pre-multiplied alpha
* default is false
* default is true
*
* preserveDrawingBuffer - if true the buffers will not be cleared and
* and will preserve their values until cleared or overwritten by author
Expand Down Expand Up @@ -895,7 +895,7 @@ p5.RendererGL.prototype.clear = function(...args) {
const _b = args[2] || 0;
const _a = args[3] || 0;

this.GL.clearColor(_r, _g, _b, _a);
this.GL.clearColor(_r * _a, _g * _a, _b * _a, _a);
this.GL.clearDepth(1);
this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
};
Expand Down
4 changes: 2 additions & 2 deletions src/webgl/shaders/basic.frag
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
precision mediump float;
uniform vec4 uMaterialColor;
void main(void) {
gl_FragColor = uMaterialColor;
}
gl_FragColor = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;
}
6 changes: 3 additions & 3 deletions src/webgl/shaders/font.frag
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,6 @@ void main() {
float distance = max(weight.x + weight.y, minDistance); // manhattan approx.
float antialias = abs(dot(coverage, weight) / distance);
float cover = min(abs(coverage.x), abs(coverage.y));
gl_FragColor = uMaterialColor;
gl_FragColor.a *= saturate(max(antialias, cover));
}
gl_FragColor = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;
gl_FragColor *= saturate(max(antialias, cover));
}
6 changes: 3 additions & 3 deletions src/webgl/shaders/light_texture.frag
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ void main(void) {
gl_FragColor = uMaterialColor;
}
else {
gl_FragColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;
gl_FragColor.rgb = gl_FragColor.rgb * vDiffuseColor + vSpecularColor;
vec4 baseColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;
gl_FragColor = vec4(gl_FragColor.rgb * vDiffuseColor + vSpecularColor, 1.) * baseColor.a;
}
}
}
4 changes: 2 additions & 2 deletions src/webgl/shaders/line.frag
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ precision mediump int;
uniform vec4 uMaterialColor;

void main() {
gl_FragColor = uMaterialColor;
}
gl_FragColor = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;
}
8 changes: 4 additions & 4 deletions src/webgl/shaders/phong.frag
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ void main(void) {

// Calculating final color as result of all lights (plus emissive term).

gl_FragColor = isTexture ? texture2D(uSampler, vTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;
gl_FragColor.rgb = diffuse * gl_FragColor.rgb +
vec4 baseColor = isTexture ? texture2D(uSampler, vTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;
gl_FragColor = vec4(diffuse * baseColor.rgb +
vAmbientColor * uAmbientMatColor.rgb +
specular * uSpecularMatColor.rgb +
uEmissiveMatColor.rgb;
}
uEmissiveMatColor.rgb, 1.) * baseColor.a;
}
30 changes: 15 additions & 15 deletions src/webgl/shaders/point.frag
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ uniform vec4 uMaterialColor;
varying float vStrokeWeight;

void main(){
float mask = 0.0;
float mask = 0.0;

// make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)
// might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant
// make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)
// might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant

mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));
mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));

// if strokeWeight is 1 or less lets just draw a square
// this prevents weird artifacting from carving circles when our points are really small
// if strokeWeight is larger than 1, we just use it as is
// if strokeWeight is 1 or less lets just draw a square
// this prevents weird artifacting from carving circles when our points are really small
// if strokeWeight is larger than 1, we just use it as is

mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));
mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));

// throw away the borders of the mask
// otherwise we get weird alpha blending issues
// throw away the borders of the mask
// otherwise we get weird alpha blending issues

if(mask > 0.98){
discard;
}
if(mask > 0.98){
discard;
}

gl_FragColor = vec4(uMaterialColor.rgb * (1.0 - mask), uMaterialColor.a) ;
}
gl_FragColor = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;
}
4 changes: 2 additions & 2 deletions src/webgl/shaders/vertexColor.frag
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
gl_FragColor = vec4(vColor.rgb, 1.) * vColor.a;
}
32 changes: 14 additions & 18 deletions test/unit/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ suite('p5.RendererGL', function() {
pg.clear();
myp5.image(pg, -myp5.width / 2, -myp5.height / 2);
pixel = myp5.get(0, 0);
assert.deepEqual(pixel, [0, 0, 0, 255]);
assert.deepEqual(pixel, [0, 255, 255, 255]);
done();
});

Expand All @@ -361,7 +361,7 @@ suite('p5.RendererGL', function() {
pg.background(100, 100, 100, 100);
myp5.image(pg, -myp5.width / 2, -myp5.height / 2);
pixel = myp5.get(0, 0);
assert.deepEqual(pixel, [100, 100, 100, 255]);
assert.deepEqual(pixel, [39, 194, 194, 255]);
done();
});

Expand All @@ -383,7 +383,7 @@ suite('p5.RendererGL', function() {
pg.clear();
myp5.image(pg, 0, 0);
pixel = myp5.get(0, 0);
assert.deepEqual(pixel, [0, 0, 0, 255]);
assert.deepEqual(pixel, [0, 255, 255, 255]);
done();
});

Expand All @@ -394,7 +394,7 @@ suite('p5.RendererGL', function() {
pg.background(100, 100, 100, 100);
myp5.image(pg, 0, 0);
pixel = myp5.get(0, 0);
assert.deepEqual(pixel, [100, 100, 100, 255]);
assert.deepEqual(pixel, [39, 194, 194, 255]);
done();
});
});
Expand Down Expand Up @@ -483,14 +483,14 @@ suite('p5.RendererGL', function() {
myp5.createCanvas(10, 10, myp5.WEBGL);
myp5.noStroke();
assert.deepEqual([122, 0, 122, 255], mixAndReturn(myp5.ADD, 0));
assert.deepEqual([0, 0, 255, 255], mixAndReturn(myp5.REPLACE, 255));
assert.deepEqual([0, 0, 122, 122], mixAndReturn(myp5.REPLACE, 255));
assert.deepEqual([133, 255, 133, 255], mixAndReturn(myp5.SUBTRACT, 255));
assert.deepEqual([255, 0, 255, 255], mixAndReturn(myp5.SCREEN, 0));
assert.deepEqual([0, 255, 0, 255], mixAndReturn(myp5.EXCLUSION, 255));
assert.deepEqual([122, 0, 122, 255], mixAndReturn(myp5.SCREEN, 0));
assert.deepEqual([133, 255, 133, 255], mixAndReturn(myp5.EXCLUSION, 255));
// Note that in 2D mode, this would just return black, because 2D mode
// ignores alpha in this case.
assert.deepEqual([133, 69, 202, 255], mixAndReturn(myp5.MULTIPLY, 255));
assert.deepEqual([255, 0, 255, 255], mixAndReturn(myp5.LIGHTEST, 0));
assert.deepEqual([133, 69, 133, 255], mixAndReturn(myp5.MULTIPLY, 255));
assert.deepEqual([122, 0, 122, 255], mixAndReturn(myp5.LIGHTEST, 0));
assert.deepEqual([0, 0, 0, 255], mixAndReturn(myp5.DARKEST, 255));
done();
});
Expand All @@ -517,15 +517,11 @@ suite('p5.RendererGL', function() {
const assertSameIn2D = function(colorA, colorB, mode) {
const refColor = testBlend(myp5, colorA, colorB, mode);
const webglColor = testBlend(ref, colorA, colorB, mode);
if (refColor[3] === 0) {
assert.equal(webglColor[3], 0);
} else {
assert.deepEqual(
refColor,
webglColor,
`Blending ${colorA} with ${colorB} using ${mode}`
);
}
assert.deepEqual(
refColor,
webglColor,
`Blending ${colorA} with ${colorB} using ${mode}`
);
};

for (const alpha of [255, 200]) {
Expand Down