diff --git a/src/webgl/shaders/phong.frag b/src/webgl/shaders/phong.frag index e141f62f1f..74c5206d95 100644 --- a/src/webgl/shaders/phong.frag +++ b/src/webgl/shaders/phong.frag @@ -47,13 +47,13 @@ void main(void) { inputs.texCoord = vTexCoord; inputs.ambientLight = vAmbientColor; inputs.color = isTexture - // Textures come in with premultiplied alpha. To apply tint and still have - // premultiplied alpha output, we need to multiply the RGB channels by the - // tint RGB, and all channels by the tint alpha. - ? TEXTURE(uSampler, vTexCoord) * vec4(uTint.rgb/255., 1.) * (uTint.a/255.) - // Colors come in with unmultiplied alpha, so we need to multiply the RGB - // channels by alpha to convert it to premultiplied alpha. - : vec4(vColor.rgb * vColor.a, vColor.a); + ? TEXTURE(uSampler, vTexCoord) * uTint/255. + : vColor; + if (isTexture) { + // Textures come in with premultiplied alpha. Temporarily unpremultiply it + // so hooks users don't have to think about premultiplied alpha. + inputs.color.rgb /= inputs.color.a; + } inputs.shininess = uShininess; inputs.metalness = uMetallic; inputs.ambientMaterial = uHasSetAmbient ? uAmbientMatColor.rgb : inputs.color.rgb; @@ -79,5 +79,6 @@ void main(void) { c.specular = specular; c.emissive = inputs.emissiveMaterial; OUT_COLOR = HOOK_getFinalColor(HOOK_combineColors(c)); + OUT_COLOR.rgb *= OUT_COLOR.a; // Premultiply alpha before rendering HOOK_afterFragment(); } diff --git a/test/unit/visual/cases/webgl.js b/test/unit/visual/cases/webgl.js index fe676a0e8c..de0c234a2c 100644 --- a/test/unit/visual/cases/webgl.js +++ b/test/unit/visual/cases/webgl.js @@ -345,4 +345,58 @@ visualSuite('WebGL', function() { screenshot(); }) }) + + visualSuite('Opacity', function() { + visualTest('Basic colors have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + p5.background(255); + p5.fill(255, 0, 0, 100); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors have opacity applied correctly when lights are used', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + p5.background(255); + p5.ambientLight(255); + p5.fill(255, 0, 0, 100); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors in shader hooks have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const myShader = p5.baseMaterialShader().modify({ + 'Inputs getPixelInputs': `(Inputs inputs) { + inputs.color = vec4(1., 0., 0., 100./255.); + return inputs; + }` + }) + p5.background(255); + p5.shader(myShader); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors in textures have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const tex = p5.createFramebuffer(); + tex.draw(() => p5.background(255, 0, 0, 100)); + p5.background(255); + p5.texture(tex); + p5.circle(0, 0, 50); + screenshot(); + }); + + visualTest('Colors in tinted textures have opacity applied correctly', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const tex = p5.createFramebuffer(); + tex.draw(() => p5.background(255, 0, 0, 255)); + p5.background(255); + p5.texture(tex); + p5.tint(255, 100); + p5.circle(0, 0, 50); + screenshot(); + }); + }); }); diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Basic colors have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors have opacity applied correctly when lights are used/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors in shader hooks have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors in textures have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/000.png b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/000.png new file mode 100644 index 0000000000..b885704e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/metadata.json b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Opacity/Colors in tinted textures have opacity applied correctly/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file