在webgl中生成文本纹理:Alpha是不透明的

时间:2017-09-14 09:16:33

标签: canvas text textures webgl dynamically-generated

我正在从包含文本的画布生成纹理,问题是当我渲染纹理时,文本的透明部分被完全忽略。

comparision

当我渲染纹理时,它看起来像顶部文本,它应该看起来像底部文本。

这就是我生成纹理的方法:

canvas.width = textRendBuffC.measureText(text).width*2;
canvas.height = parseInt(fontStyle, 10)*1.5;
c.clearRect(0, 0, canvas.width, canvas.height);
c.font = fontStyle;
c.fillStyle = colorStyle;
c.fillText(text, 0, parseInt(fontStyle, 10));


var canvasTexture = gl.createTexture();

gl.bindTexture(gl.TEXTURE_2D, canvasTexture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,true);

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D,null);

这就是我绘制纹理的方式:

gl.bindBuffer(gl.ARRAY_BUFFER, spritePlan.vertBuffer);
gl.vertexAttribPointer(currentShader.sh.vertexAttribLocation, spritePlan.vertBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, spritePlan.texCoordBuffer);
gl.vertexAttribPointer(currentShader.sh.textureCoordAttribute, spritePlan.texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, spritePlan.colorBuffer);
gl.vertexAttribPointer(currentShader.sh.colorAttribLocation, spritePlan.colorBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.uniform1i(currentShader.sh.sampler2DUniform, 0);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, spritePlan.indexBuffer);
setMatrixUniforms();

gl.drawElements(gl.TRIANGLES, spritePlan.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

这是片段着色器经过的代码:

vec4 tex = texture2D(sampler2DUniform, vTextureCoord);
gl_FragColor = vec4(tex.rgb, tex.a);

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

首先,要在WebGL中使用alpha作为透明度,您必须使用正确的混合方程进行混合。典型的是:

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

我没有看到与您的代码中的混合相关的内容,您是否将其设置在其他位置,您使用了什么混合方程式?

答案 1 :(得分:1)

您必须将UNPACK_PREMULTIPLY_ALPHA_WEBGL参数设置为truepixelStorei)。这将导致颜色通道乘以Alpha通道,初始值为false

gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

请参阅WebGL Fundamentals - textures

  

这告诉WebGL向gl.texImage2Dgl.texSubImage2D提供预乘的alpha值。如果传递给gl.texImage2D的数据已经预先乘以Canvas 2D数据,那么WebGL就可以通过它。

参见Khronos规范Premultiplied Alpha, Canvas APIs and texImage2D

  

将WebGL渲染的Canvas传递给texImage2D API时,根据传递的画布的premultipliedAlpha上下文创建参数的设置和目标WebGL上下文的UNPACK_PREMULTIPLY_ALPHA_WEBGL像素存储参数,像素数据可能会需要更改为或从预乘形式。


此外,您使用TEXTURE_MAG_FILTER

设置纹理参数NEAREST
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,gl.NEAREST);

请参阅Sampler Object的Khronos OpenGL参考:

  

放大滤镜由GL_TEXTURE_MAG_FILTER纹理参数控制。该值可以是GL_LINEARGL_NEAREST。如果使用GL_NEAREST,则实现将选择最接近纹理坐标的纹素;这通常被称为"点采样"。如果使用GL_LINEAR,则实现将在最近的相邻样本之间执行加权线性混合。

这意味着,如果您使用NEAREST,则根据纹理坐标从纹理中读取最近的纹理元素。这会产生坚硬而有棱角的外观 如果将纹理参数TEXTURE_MAG_FILTER设置为LINEAR,则会对纹素进行插值,并计算给定坐标周围4个像素的加权平均值。结果是更平滑的外观:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,gl.LINEAR);


另见: