【问题标题】:Text to texture in webglwebgl中的文本到纹理
【发布时间】:2013-03-12 17:21:58
【问题描述】:

我有一个绘制球体的 webGL 代码,我在旁边添加了文本标签。 我正在做的是创建 2D 矩形,然后使用我的文本应用纹理。

function createCubeTexture(text) {

var canvas = document.createElement('canvas');
canvas.id     = "hiddenCanvas";
canvas.width  = 512;
canvas.height = 128;
canvas.style.display   = "none";
var body = document.getElementsByTagName("body")[0];
body.appendChild(canvas);        

var cubeImage = document.getElementById('hiddenCanvas');
var ctx = cubeImage.getContext('2d');
ctx.beginPath();
ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);            
ctx.fillStyle = 'rgba(255,255,255,0)';
ctx.fill();
ctx.fillStyle = 'black';
ctx.font = "65px Arial";
ctx.textAlign = 'center';            
ctx.fillText(text, ctx.canvas.width / 2, ctx.canvas.height / 2);
ctx.restore();        

var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
handleTextureLoaded(cubeImage, texture) 

return texture;
}

但我正在寻找的是完全透明的纹理。我想要没有bgcolor的文本。 我可以使用 alpha 并获得“类似透明”的颜色,但我的矩形从不透明(如果 alpha=0,则它是白色的),我从未设法通过矩形看到球体。

任何想法

谢谢

【问题讨论】:

    标签: html5-canvas transparency webgl textures


    【解决方案1】:

    为了使用 alpha = 0 进行绘制,您需要在画布 2d 中使用不同的 globalCompositeOperation。在rgba(255,255,255,0) 上面的代码中,source-over 的默认 globalCompositingOperation 基本上是这样做的

    dest = dest * (1 - alpha) + source * alpha
    

    由于 alpha 为 0,这意味着它不绘制任何内容,因此您的第一个 fill 调用不绘制任何内容。

    改为将 alpha 设置为 1,但对文本使用 'ctx.globalCompositeOperation = "destination-out"for the fill, then set back tosource-over`。

    看到这个问题 How do you draw with alpha = 0 in an html5 canvas to 'erase'.

    尽管实际上,在您的情况下,只需删除填充即可。画布元素开始完全透明。要将画布清除回透明调用ctx.clearRect

    这是从另一个示例复制的 sn-p:

    var gl;
    
    function initGL(canvas) {
        try {
            gl = canvas.getContext("webgl");
            gl.viewportWidth = canvas.width;
            gl.viewportHeight = canvas.height;
        } catch (e) {
        }
        if (!gl) {
            alert("Could not initialise WebGL, sorry :-(");
        }
    }
    
    
    function getShader(gl, id) {
        var shaderScript = document.getElementById(id);
        if (!shaderScript) {
            return null;
        }
    
        str = shaderScript.text;
    
        var shader;
        if (shaderScript.type == "x-shader/x-fragment") {
            shader = gl.createShader(gl.FRAGMENT_SHADER);
        } else if (shaderScript.type == "x-shader/x-vertex") {
            shader = gl.createShader(gl.VERTEX_SHADER);
        } else {
            return null;
        }
    
        gl.shaderSource(shader, str);
        gl.compileShader(shader);
    
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert(gl.getShaderInfoLog(shader));
            return null;
        }
    
        return shader;
    }
    
    
    var shaderProgram;
    
    function initShaders() {
        var fragmentShader = getShader(gl, "shader-fs");
        var vertexShader = getShader(gl, "shader-vs");
    
        shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);
    
        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert("Could not initialise shaders");
        }
    
        gl.useProgram(shaderProgram);
    
        // This is a bad code.
        // If the context is lsot shaderProgram will be null
        // and trying to assign a vertexPositionAttribute to null
        // will throw an exception.
        // better would be 
        // shaderProgram = {};
        // shaderProgram.program = gl.createProgram();
        // shaderProgram.vertexPositionAtrribute = ...
        shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
        gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
    
        shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
        gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
    
        shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
        shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
        shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    }
    
    
    var texturen = new Array();
    function initTexture(text,texturen)  
    {
      var anz = texturen.length;
      texturen[anz] = gl.createTexture();
      // this is a bad code. on context lost gl.createTexture() will return null and
      // an exception will be thrown when you try to attach .image to null
      // Better would be
      // texturen[anz] = {};
      // texturen[anz].texture = gl.createTexture();
      // texturen[anz].image = new Image();
      var c = document.createElement("canvas");
      c.width = 256;
      c.height = 256;
      var ctx = c.getContext("2d"); 
      //ctx.fillStyle = "rgba(0, 0, 0, 1)";
      //ctx.globalCompositeOperation = "destination-out";
      //ctx.fillRect(0, 0, 64, 64);
      //ctx.globalCompositeOperation = "source-over";
      ctx.fillStyle = "rgb(255, 128, 64)";
      ctx.font = "40px Arial";
      ctx.fillText(text, 128 - 64, 128);
      gl.bindTexture(gl.TEXTURE_2D, texturen[anz]);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
    } 
    
    var mvMatrix = mat4.create();
    var mvMatrixStack = [];
    var pMatrix = mat4.create();
    
    function mvPushMatrix() {
        var copy = mat4.create();
        mat4.set(mvMatrix, copy);
        mvMatrixStack.push(copy);
    }
    
    function mvPopMatrix() {
        if (mvMatrixStack.length == 0) {
            throw "Invalid popMatrix!";
        }
        mvMatrix = mvMatrixStack.pop();
    }
    
    
    function setMatrixUniforms() {
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    }
    
    function degToRad(degrees) {
        return degrees * Math.PI / 180;
    }
    
    function initBuffers() {
        vertBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
        var vertices = [
            // Front face
            -1.0, -1.0,  1.0,
             1.0, -1.0,  1.0,
             1.0,  1.0,  1.0,
            -1.0,  1.0,  1.0,
    
            // Back face
            -1.0, -1.0, -1.0,
            -1.0,  1.0, -1.0,
             1.0,  1.0, -1.0,
             1.0, -1.0, -1.0,
    
            // Top face
            -1.0,  1.0, -1.0,
            -1.0,  1.0,  1.0,
             1.0,  1.0,  1.0,
             1.0,  1.0, -1.0,
    
           // Bottom face
            -1.0, -1.0, -1.0,
             1.0, -1.0, -1.0,
             1.0, -1.0,  1.0,
            -1.0, -1.0,  1.0,
    
            // Right face
             1.0, -1.0, -1.0,
             1.0,  1.0, -1.0,
             1.0,  1.0,  1.0,
             1.0, -1.0,  1.0,
    
            // Left face
            -1.0, -1.0, -1.0,
            -1.0, -1.0,  1.0,
            -1.0,  1.0,  1.0,
            -1.0,  1.0, -1.0,
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        
        // This is bad code. See the above examples of bad code.
        // vertBuffer will be null on context lost and this code
        // will throw an exception.
        vertBuffer.itemSize = 3;
        vertBuffer.numItems = 24;
    
        CoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,CoordBuffer);
        var textureCoords = [
          // Front face
          1.0, 0.0,
          0.0, 0.0,
          0.0, 1.0,
          1.0, 1.0,
    
          // Back face
          0.0, 0.0,
          0.0, 1.0,
          1.0, 1.0,
          1.0, 0.0,
    
          // Top face
          1.0, 1.0,
          1.0, 0.0,
          0.0, 0.0,
          0.0, 1.0,
    
       // Bottom face
          0.0, 1.0,
          1.0, 1.0,
          1.0, 0.0,
          0.0, 0.0,
    
          // Right face
          0.0, 0.0,
          0.0, 1.0,
          1.0, 1.0,
          1.0, 0.0,
    
          // Left face
          1.0, 0.0,
          0.0, 0.0,
          0.0, 1.0,
          1.0, 1.0,
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
        CoordBuffer.itemSize = 2;
        CoordBuffer.numItems = 24;
    
        IndexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
        var Indices = [
            0, 1, 2,      0, 2, 3,    // Front face
            4, 5, 6,      4, 6, 7,    // Back face
            8, 9, 10,     8, 10, 11,  // Top face
            12, 13, 14,   12, 14, 15, // Bottom face
            16, 17, 18,   16, 18, 19, // Right face
            20, 21, 22,   20, 22, 23  // Left face
        ];
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(Indices), gl.STATIC_DRAW);
        IndexBuffer.itemSize = 1;
        IndexBuffer.numItems = 36;
    }
    
    
    var xRot = 0;
    var yRot = 0;
    var zRot = 0;
    
    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
        mat4.perspective(pMatrix, 45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
    
        mat4.identity(mvMatrix);
    
        mat4.translate(mvMatrix, mvMatrix, [0.0, 0.0, -5.0]);
    
        mat4.rotate(mvMatrix, mvMatrix, degToRad(xRot), [1, 0, 0]);
        mat4.rotate(mvMatrix, mvMatrix, degToRad(yRot), [0, 1, 0]);
        mat4.rotate(mvMatrix, mvMatrix, degToRad(zRot), [0, 0, 0]);
        setMatrixUniforms();
    
    
        gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,vertBuffer.itemSize, 
           gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, CoordBuffer);
        gl.vertexAttribPointer(shaderProgram.textureCoordAttribute,CoordBuffer.itemSize, 
           gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
    
    // Draw face 0
    gl.bindTexture(gl.TEXTURE_2D, texturen[0]);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
    
    // Draw face 1
    gl.bindTexture(gl.TEXTURE_2D, texturen[1]);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 12);
    
    // Draw face 2
    gl.bindTexture(gl.TEXTURE_2D, texturen[2]);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 24);
    
    // Draw face 3
    gl.bindTexture(gl.TEXTURE_2D, texturen[3]);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 36);
    
    // Draw face 4
    gl.bindTexture(gl.TEXTURE_2D, texturen[4]);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 48);
    
    // Draw face 5
    gl.bindTexture(gl.TEXTURE_2D, texturen[5]);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 60);
    }
    
    
    var lastTime = 0;
    
    function animate() {
        var timeNow = new Date().getTime();
        if (lastTime != 0) {
            var elapsed = timeNow - lastTime;
    
            xRot += (90 * elapsed) / 1000.0;
            yRot += (90 * elapsed) / 1000.0;
            zRot += (90 * elapsed) / 1000.0;
        }
        lastTime = timeNow;
    }
    
    
    function tick() {
        requestAnimationFrame(tick);
        drawScene();
        animate();
    }
    
    
    function webGLStart() {
        var canvas = document.getElementById("lesson05-canvas");
        initGL(canvas);
        initShaders();
        initBuffers();
        initTexture("face 0",texturen);
        initTexture("face 1",texturen);
        initTexture("face 2",texturen);
        initTexture("face 3",texturen);
        initTexture("face 4",texturen);
        initTexture("face 5",texturen);
    
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
        tick();
    }
    
    
    webGLStart();
        
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
    <script id="shader-fs" type="x-shader/x-fragment">
    precision mediump float;
    
    varying vec2 vTextureCoord;
    
    uniform sampler2D uSampler;
    
    void main(void) {
        gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
    }
    </script>
    
    <script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    attribute vec2 aTextureCoord;
    
    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;
    
    varying vec2 vTextureCoord;
    
    
    void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        vTextureCoord = aTextureCoord;
    }
    </script>
    
    <canvas id="lesson05-canvas" style="border: none;" width="500" height="500">    </canvas>    

    【讨论】:

      猜你喜欢
      • 2016-08-28
      • 1970-01-01
      • 1970-01-01
      • 2013-01-05
      • 1970-01-01
      • 2013-01-20
      • 1970-01-01
      • 1970-01-01
      • 2021-04-08
      相关资源
      最近更新 更多