简体   繁体   中英

how WebGL return pixel color when blending is disabled?

when there is no blending, what is the function that give color pixel from fragment color and clearColor ?

 const canvas = document.querySelector("#normal"); const gl = canvas.getContext('webgl', {premultipliedAlpha: false}); gl.clearColor(0 , 0.5 , 0.7 , 0.65); gl.clear(gl.COLOR_BUFFER_BIT);
 html, body { height: 100%; background: repeating-linear-gradient( 45deg, lime, /* lime=( 0.0 , 1.0 , 0.0 , 1.0 ) */ lime 10px, orange 10px, /* orange=( 1.0 , 0.64705.. , 0.0 , 1.0) */ orange 20px ); } canvas { border: 1px solid black; }
 <canvas width="128" height="128" id="normal"></canvas>

从 Gimp 获取快照和颜色

body 1.0 , 0.647 , 0.0 , 1.0
canvas 0.0 , 0.5 , 0.7 , 0.65
(1)canvas x alpha 0.0 , 0.325 , 0.455 , 0.4225
(2)body x (1-alpha) 0.35 , 0.2264 , 0.0 , 0.35
(1)+(2)= 0.35 , 0.5514 , 0.455 , 0.7725

So, the result is like :

gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

but i did not write that code...

16/07/2021 : Merci peabrainiac !

the result is the same as with : gl.blendFuncSeparate(gl.SRC_AlPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE_MINUS_SRC_ALPHA)

color(RGB) = sourceColor * As + destinationColor * (1-As)

color(A) = sourceAlpha + destinationAlpha * ( 1-As)

color(RGB) = (0.0, 0.5 , 0.7) * 0.65 + (1.0 , 0.647.. , 0.0) * 0.35

color(A) = 0.65 + 1.0 * 0.35

color(RGB) = (0.35 , 0.55147.. , 0.455)

color(A) = 1.0

test :

 test('#normal'); test3('#blendfunc'); function test(selector) { const canvas = document.querySelector(selector); const gl = canvas.getContext('webgl'); var r = 0; var g = 0.5; var b = 0.7; var a = 0.65; gl.clearColor(r * a, g * a, b * a, a); gl.clear(gl.COLOR_BUFFER_BIT); } function test3(selector) { const canvas = document.querySelector(selector); const gl = canvas.getContext('webgl'); const vs=` void main() { gl_Position=vec4(0,0,0,1); gl_PointSize = 128.; } `; const fs=` precision highp float; void main() { float r=0.0; float g=0.5; float b=0.7; float a=0.65; gl_FragColor=vec4(r*a,g*a,b*a,a); // it works with gl_FragColor = vec4 (r, g, b, a) //However I am not in {premultipliedAlpha: false} //gl_FragColor=vec4(r,g,b,a); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vs); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fs); gl.compileShader(fragmentShader); const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.enable(gl.BLEND); //gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE_MINUS_SRC_ALPHA); gl.viewport(0,0,canvas.width,canvas.height); gl.drawArrays(gl.POINTS,0,1); }
 html, body { height: 100%; background: repeating-linear-gradient( 45deg, lime, lime 10px, orange 10px, /* 1,0.647,1,0 */ orange 20px ); } canvas { border: 1px solid black; }
 <canvas width="128" height="128" id="normal"></canvas> <canvas width="128" height="128" id="blendfunc"></canvas>

...oups it does not work !

 test('#normal'); test3('#blendfunc'); function test(selector) { const canvas = document.querySelector(selector); const gl = canvas.getContext('webgl'); var r = 0; var g = 0.5; var b = 0.7; var a = 0.65; gl.clearColor(r * a, g * a, b * a, a); gl.clear(gl.COLOR_BUFFER_BIT); } function test3(selector) { const canvas = document.querySelector(selector); const gl = canvas.getContext('webgl'); const vs=` void main() { gl_Position=vec4(0,0,0,1); gl_PointSize = 128.; } `; const fs=` precision highp float; void main() { float r=0.0; float g=0.5; float b=0.7; float a=0.65; gl_FragColor=vec4(r,g,b,a); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vs); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fs); gl.compileShader(fragmentShader); const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.enable(gl.BLEND); gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE_MINUS_SRC_ALPHA); gl.viewport(0,0,canvas.width,canvas.height); gl.drawArrays(gl.POINTS,0,1); }
 html, body { height: 100%; background: repeating-linear-gradient( 45deg, lime, lime 10px, orange 10px, /* 1,0.647,1,0 */ orange 20px ); } canvas { border: 1px solid black; }
 <canvas width="128" height="128" id="normal"></canvas> <canvas width="128" height="128" id="blendfunc"></canvas>

In this case blending is not happening inside of WebGL but inside the browser, just like with any other image with a color of 0 , 0.5 , 0.7 , 0.65 .

Blending in WebGL simply changes how the values emitted from a fragment shader get blended with the values already in that buffer. When blending is disabled, as it is by default, they simply overwrite the old values without any sort of blending. Similarly, glClear always just overwrites the old values even if blending is enabled .

So, in your case the main buffer / canvas is indeed completely filled with the rgba values 0, 0.5, 0.7, 0.65 , not blended with anything else in any way; however, as with any partially transparent element, this is then blended linearly with the background by the browser.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM