【问题标题】:Possible to draw a string ("Hello World") as a texture at run-time?可以在运行时将字符串(“Hello World”)绘制为纹理吗?
【发布时间】:2014-07-02 07:35:00
【问题描述】:

我了解如何将纹理映射应用于多边形。

但是是否可以在运行时创建字符串的纹理(例如每秒显示的当前帧数)并将其映射到多边形?

更新

这可能会奏效。我必须自己测试一下。 Drawing text as textures on squares does not show anything

【问题讨论】:

    标签: textures webgl


    【解决方案1】:

    使用 2D 画布 API 在运行时创建纹理很容易

    var gl = someCavnasInThePage.getContext("webgl");
    
    // create an offscreen canvas with a 2D canvas context
    var ctx = document.createElement("canvas").getContext("2d");
    
    // make it a desired size 
    ctx.canvas.width = 128;
    ctx.canvas.height = 64;
    
    // fill it a certain color
    ctx.fillStyle = "rgb(255,0,0)";  // red
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    
    // draw some text into it.
    ctx.fillStyle = "rgb(255,255,0)";  // yellow
    ctx.font = "20px sans-serif";
    ctx.fillText("Hello World", 5, 40);
    
    // Now make a texture from it
    var tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, tex);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
    
    // generate mipmaps or set filtering 
    gl.generateMipmap(gl.TEXTURE_2D);
    

    这是一个工作示例

    var m4 = twgl.m4;
    var gl = twgl.getWebGLContext(document.getElementById("c"));
    var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
    
    var arrays = {
      position: [1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1],
      normal:   [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1],
      texcoord: [1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1],
      indices:  [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23],
    };
    var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
    
    
    var tex = createTextTexture(gl, "Hello World", 256, 128);
    gl.bindTexture(gl.TEXTURE_2D, tex);
    
    function render(time) {
      time *= 0.001;
      
      twgl.resizeCanvasToDisplaySize(gl.canvas);
      gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
      gl.enable(gl.DEPTH_TEST);
    
      var fieldOfView = Math.PI * 0.25;
      var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
      var projection = m4.perspective(fieldOfView, aspect, 0.0001, 500);
      var radius = 5;
      var eye = [
        Math.sin(time) * radius,
        2,
        Math.cos(time) * radius];
      var target = [0, 0, 0];
      var up = [0, 1, 0];
      var camera = m4.lookAt(eye, target, up);
      var view = m4.inverse(camera);
    
      var worldViewProjection = m4.multiply(view, projection);
      var uniforms = {
        u_worldViewProjection: worldViewProjection,
      };
      
      gl.useProgram(programInfo.program);
      twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
      twgl.setUniforms(programInfo, uniforms);
      gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);
      
      requestAnimationFrame(render);
    }
    requestAnimationFrame(render);
    
    var ctxForMakingTextures;
    function createTextTexture(gl, str, width, height) {
        // create an offscreen canvas with a 2D canvas context
        if (!ctxForMakingTextures) {
           ctxForMakingTextures = document.createElement("canvas").getContext("2d");
        }
        var ctx = ctxForMakingTextures;
        
        // make it a desired size 
        ctx.canvas.width = width;
        ctx.canvas.height = height;
        
        // fill it a certain color
        ctx.fillStyle = "rgb(255,0,0)";  // red
        ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        
        // draw some text into it.
        ctx.fillStyle = "rgb(255,255,0)";  // yellow
        ctx.font = "40px sans-serif";
        ctx.fillText("Hello World", 5, 40);
        
        // Now make a texture from it
        var tex = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
        
        // generate mipmaps or set filtering 
        gl.generateMipmap(gl.TEXTURE_2D);
        
        return tex;
    };
    html, body, canvas {
      width: 100%;
      height: 100%;
      margin: 0;
    }
    <script src="https://twgljs.org/dist/twgl-full.min.js"></script>
    <script id="vs" type="not-js">
    attribute vec4 position;
    attribute vec2 texcoord;
    
    varying vec2 v_texcoord;
        
    uniform mat4 u_worldViewProjection;
    
    void main() {
       gl_Position = u_worldViewProjection * position;
       v_texcoord = texcoord;
    }
    </script>
    <!-- fragment shader -->
    <script id="fs" type="not-js">
    precision mediump float;
        
    varying vec2 v_texcoord;
    
    uniform sampler2D u_texture;
    void main() {
       gl_FragColor = texture2D(u_texture, v_texcoord);
    }
    </script>
    <canvas id="c"></canvas>

    【讨论】:

      【解决方案2】:

      如果我理解正确,您正在尝试使用 OpenGL 以 3D 显示文本。以下是您应该考虑的几个选项:

      1. 使用您希望显示的文本创建一个常规矩形纹理,并将其渲染在一个简单的 4 顶点矩形上。这是最简单的实现,但它需要您为要显示的每个字符串生成不同的纹理。

      2. 如上所述,创建一个矩形纹理,但这次,为您希望能够支持的每个字母/字符制作一个。然后,构建一个工厂,为特定字符串中的每个字母生成 4 顶点矩形,为每个形状选择合适的字母。你需要在良好的定位上做一些工作,但这会给你一个相当灵活的解决方案。

      3. 与 #2 类似,但这次使用一些无缝纹理,但会为您希望支持的每个字母/字符生成形状。每个形状将包含多个顶点,除非您使用外部图形资源,否则可能需要一些时间才能完成。但是,此实现将为您提供最令人印象深刻的文本显示方法,因为每个字母将在空间中显示为 3 维对象。

      【讨论】:

      • 我不确定这是我想要的。我不想创建一个使用广告牌/四边形创建字体/字母的“工厂”。我想要的是:1)给定一个在运行时确定的字符串,2)创建纹理,3)应用于任何多边形表面。
      • 你所描述的听起来不像是“不可能”的事情,但它绝对很难。您要求找到一种从字符串自动生成纹理(位图)的方法,这不是很困难,但是您想找到一种方法将其以一种好的方式映射到任何多边形,这很困难。很抱歉,我想我不能帮你解决这个问题。
      猜你喜欢
      • 2012-10-26
      • 2011-12-14
      • 2020-05-02
      • 2016-04-05
      • 2020-12-07
      • 2011-10-07
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多