2017-09-14 40 views
1

我从包含文本的画布生成纹理,问题在于渲染纹理时文本的透明部分完全被忽略。在webgl中生成文本纹理:Alpha不透明

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); 

有没有想法?

+1

请在回答中添加您的解决方案,然后接受它,将其从问题中删除。请参阅[游览] –

回答

1

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

gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); 

参见WebGL Fundamentals - textures

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

见Khronos的规格Premultiplied Alpha, Canvas APIs and texImage2D

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


此外,设置了纹理放慢参数TEXTURE_MAG_FILTERNEAREST

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); 


参见:

+0

我找到了一个解决方案:gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,true); 这告诉WebGL将预乘alpha值提供给gl.texImage2D和gl.texSubImage2D。如果传递给gl.texImage2D的数据与Canvas 2D数据一样已经预乘,那么WebGL就可以传递它。 – Elias

2

首先,在WebGL的使用阿尔法透明度,你必须启用与正确混合等式的混合。典型的一个是:

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

我什么也看不到相关的代码中的融合,你将它设置在其他地方,什么混合式,你用?

+0

答案的第二部分 - “我看不出有关在代码中混合的东西,你是否在其他地方设置过它,你使用了什么混合方程?” - 应该是对问题的评论,而不是**你的答案的一部分。 – Rabbid76

+1

完全符合你,但是......我没有足够的声望来发表评论,所以,我该怎么办? :) – 2017-09-14 20:14:51