代码之家  ›  专栏  ›  技术社区  ›  Elias

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

  •  1
  • Elias  · 技术社区  · 7 年前

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

    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 回复  |  直到 7 年前
        1
  •  2
  •   user1501157 user1501157    7 年前

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

    我在你的代码中没有看到任何与混合相关的内容,你在别处设置了吗,你使用了什么混合方程?

        2
  •  1
  •   Rabbid76    7 年前

    你必须设置 UNPACK_PREMULTIPLY_ALPHA_WEBGL true ( pixelStorei ). 这将导致颜色通道乘以alpha通道,初始值为 false :

    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    

    看见 WebGL Fundamentals - textures

    gl.texImage2D gl.texSubImage2D . 如果数据传递给 德国劳埃德船级社。texImage2D 与画布2D数据一样,已预乘,然后WebGL可以将其传递。

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

    将WebGL渲染的画布传递给texImage2D API时,则取决于传递的画布的预乘Alpha上下文创建参数的设置和 UNPACK\u PREMULTIPLY\u ALPHA\u WEBGL 目标WebGL上下文的像素存储参数,可能需要将像素数据更改为预乘形式或从预乘形式更改为预乘形式。


    TEXTURE_MAG_FILTER 具有 NEAREST :

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

    Sampler Object :

    GL_TEXTURE_MAG_FILTER 纹理参数。该值可以为 GL_LINEAR GL_NEAREST . 如果 GL_最近 GL_线性

    最近的 ,然后根据纹理坐标从纹理中读取最近的texel。这会导致坚硬和棱角分明的外观。
    纹理MAG\u过滤器 LINEAR ,将对纹理进行插值,并计算给定坐标周围4个像素的加权平均值。结果是外观更平滑:

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