我需要在 webgl 中创建平滑的 alpha 过渡

i need to create a smooth alpha transition in webgl

需要从三个颜色顶点创建平滑的 alpha 过渡而不中断。我做错了什么。

https://jsfiddle.net/Lm208gjq/

var vertexShaderText = 
[
'precision mediump float;',
'',
'attribute vec2 vertPosition;',
'attribute vec4 vertColor;',
'varying vec4 fragColor;',
'',
'void main()',
'{',
'  fragColor = vertColor;',
'  gl_Position = vec4(vertPosition, 0.0, 1.0);',
'}'
].join('\n');

var fragmentShaderText =
[
'precision mediump float;',
'',
'varying vec4 fragColor;',
'void main()',
'{',
'  gl_FragColor = fragColor;',
'}'
].join('\n');

var InitDemo = function () {
 console.log('This is working');

 var canvas = document.getElementById('opengl_output');
 var gl = canvas.getContext('webgl');

 if (!gl) {
  console.log('WebGL not supported, falling back on experimental-webgl');
  gl = canvas.getContext('experimental-webgl');
 }

 if (!gl) {
  alert('Your browser does not support WebGL');
 }

 gl.clearColor(0.0, 0.0, 0.0, 1.0);
 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

 //
 // Create shaders
 // 
 var vertexShader = gl.createShader(gl.VERTEX_SHADER);
 var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

 gl.shaderSource(vertexShader, vertexShaderText);
 gl.shaderSource(fragmentShader, fragmentShaderText);

 gl.compileShader(vertexShader);
 if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
  console.error('ERROR compiling vertex shader!', gl.getShaderInfoLog(vertexShader));
  return;
 }

 gl.compileShader(fragmentShader);
 if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
  console.error('ERROR compiling fragment shader!', gl.getShaderInfoLog(fragmentShader));
  return;
 }

 var program = gl.createProgram();
 gl.attachShader(program, vertexShader);
 gl.attachShader(program, fragmentShader);
 gl.linkProgram(program);
 if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  console.error('ERROR linking program!', gl.getProgramInfoLog(program));
  return;
 }
 gl.validateProgram(program);
 if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
  console.error('ERROR validating program!', gl.getProgramInfoLog(program));
  return;
 }

 //
 // Create buffer
 //
 var triangleVertices = 
 [ // X, Y,       R, G, B, A
  0.0, 0.5,    1.0, 0.0, 0.0, 1.0,
  -0.5, -0.5,  0.0, 1.0, 0.0, 0.0001,
  0.5, -0.5,   0.0, 0.0, 1.0, 1.0
 ];

 var triangleVertexBufferObject = gl.createBuffer();
 gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);
 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);

 var positionAttribLocation = gl.getAttribLocation(program, 'vertPosition');
 var colorAttribLocation = gl.getAttribLocation(program, 'vertColor');
 gl.vertexAttribPointer(
  positionAttribLocation, // Attribute location
  2, // Number of elements per attribute
  gl.FLOAT, // Type of elements
  gl.FALSE,
  6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
  0 // Offset from the beginning of a single vertex to this attribute
 );
 gl.vertexAttribPointer(
  colorAttribLocation, // Attribute location
  4, // Number of elements per attribute
  gl.FLOAT, // Type of elements
  gl.FALSE,
  6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
  2 * Float32Array.BYTES_PER_ELEMENT // Offset from the beginning of a single vertex to this attribute
 );
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.ONE, gl.ZERO);

 gl.enableVertexAttribArray(positionAttribLocation);
 gl.enableVertexAttribArray(colorAttribLocation);

 //
 // Main render loop
 //
 gl.useProgram(program);
 gl.drawArrays(gl.TRIANGLES, 0, 3);
};

InitDemo();
<canvas id="opengl_output" width="640" height="480"></canvas>

为什么这段代码会生成另一个三角形?

我是这个 webgl 编程的新手,我尝试更改属性缓冲区但没有成功,这可能很简单。

默认的 alpha 合成是 premultiplied alpha

要么您必须禁用 premultipliedAlpha,

var gl = canvas.getContext('webgl', { premultipliedAlpha: false });

或者您必须在片段着色器中将 RGB 颜色通道乘以 ALPHA 通道:

gl_FragColor = vec4(fragColor.rgb * fragColor.a, fragColor.a);

WebGLFundamentals - WebGL and Alpha

var vertexShaderText = 
[
'precision mediump float;',
'',
'attribute vec2 vertPosition;',
'attribute vec4 vertColor;',
'varying vec4 fragColor;',
'',
'void main()',
'{',
'  fragColor = vertColor;',
'  gl_Position = vec4(vertPosition, 0.0, 1.0);',
'}'
].join('\n');

var fragmentShaderText =
[
'precision mediump float;',
'',
'varying vec4 fragColor;',
'void main()',
'{',
'  gl_FragColor = vec4(fragColor.rgb * fragColor.a, fragColor.a);',
'}'
].join('\n');

var InitDemo = function () {
 console.log('This is working');

 var canvas = document.getElementById('opengl_output');
 var gl = canvas.getContext('webgl' /*, { premultipliedAlpha: false }*/);

 if (!gl) {
  console.log('WebGL not supported, falling back on experimental-webgl');
  gl = canvas.getContext('experimental-webgl' /*, { premultipliedAlpha: false }*/);
 }

 if (!gl) {
  alert('Your browser does not support WebGL');
 }

 gl.clearColor(0.0, 0.0, 0.0, 1.0);
 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

 //
 // Create shaders
 // 
 var vertexShader = gl.createShader(gl.VERTEX_SHADER);
 var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

 gl.shaderSource(vertexShader, vertexShaderText);
 gl.shaderSource(fragmentShader, fragmentShaderText);

 gl.compileShader(vertexShader);
 if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
  console.error('ERROR compiling vertex shader!', gl.getShaderInfoLog(vertexShader));
  return;
 }

 gl.compileShader(fragmentShader);
 if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
  console.error('ERROR compiling fragment shader!', gl.getShaderInfoLog(fragmentShader));
  return;
 }

 var program = gl.createProgram();
 gl.attachShader(program, vertexShader);
 gl.attachShader(program, fragmentShader);
 gl.linkProgram(program);
 if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  console.error('ERROR linking program!', gl.getProgramInfoLog(program));
  return;
 }
 gl.validateProgram(program);
 if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
  console.error('ERROR validating program!', gl.getProgramInfoLog(program));
  return;
 }

 //
 // Create buffer
 //
 var triangleVertices = 
 [ // X, Y,       R, G, B, A
  0.0, 0.5,    1.0, 0.0, 0.0, 1.0,
  -0.5, -0.5,  0.0, 1.0, 0.0, 0.0001,
  0.5, -0.5,   0.0, 0.0, 1.0, 1.0
 ];

 var triangleVertexBufferObject = gl.createBuffer();
 gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);
 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);

 var positionAttribLocation = gl.getAttribLocation(program, 'vertPosition');
 var colorAttribLocation = gl.getAttribLocation(program, 'vertColor');
 gl.vertexAttribPointer(
  positionAttribLocation, // Attribute location
  2, // Number of elements per attribute
  gl.FLOAT, // Type of elements
  gl.FALSE,
  6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
  0 // Offset from the beginning of a single vertex to this attribute
 );
 gl.vertexAttribPointer(
  colorAttribLocation, // Attribute location
  4, // Number of elements per attribute
  gl.FLOAT, // Type of elements
  gl.FALSE,
  6 * Float32Array.BYTES_PER_ELEMENT, // Size of an individual vertex
  2 * Float32Array.BYTES_PER_ELEMENT // Offset from the beginning of a single vertex to this attribute
 );
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.ONE, gl.ZERO);

 gl.enableVertexAttribArray(positionAttribLocation);
 gl.enableVertexAttribArray(colorAttribLocation);

 //
 // Main render loop
 //
 gl.useProgram(program);
 gl.drawArrays(gl.TRIANGLES, 0, 3);
};

InitDemo();
<canvas id="opengl_output" width="640" height="480"></canvas>