文本渲染WebGL

时间:2015-02-20 02:30:41

标签: javascript html textures webgl

我正在尝试为2D图像中的不同元素添加文本标签。通过从3d投影获得2D元素。我有一些我希望包含为文本标签的元素ID。我已经尝试了2天而没有运气。我不知道出了什么问题。以下是执行渲染的函数:

function drawOverlayTriangles()
{
    if (overlay.numElements <= 0)
    return;

    gl.enableVertexAttribArray(shaderProgram.aVertexPosition);
    gl.enableVertexAttribArray(shaderProgram.aVertexColor);

    // Turn off textures
    //gl.vertexAttrib1f(shaderProgram.aHasTexture, 0.0);

    // Upload Projection, ModelView matrices
    gl.uniformMatrix4fv(shaderProgram.uMVMatrix, false, pMVMatrix);
    gl.uniformMatrix4fv(shaderProgram.uPMatrix, false, perspM);

    for (var i = 0; i < overlay.numElements; i++) {
        // Upload overlay vertices                      
        gl.bindBuffer(gl.ARRAY_BUFFER, overlayVertices[i]);
        gl.vertexAttribPointer(shaderProgram.aVertexPosition, 3, gl.FLOAT, false, 0, 0);

        // Upload overlay colors
        gl.bindBuffer(gl.ARRAY_BUFFER, overlayTriangleColors[i]);    
        gl.vertexAttribPointer(shaderProgram.aVertexColor, 4, gl.FLOAT, false, 0, 0);

        var canvas = document.createElement("canvas");
        canvas.setAttribute("id","canvas");
        canvas.width="512";
        canvas.height="512";
        document.body.appendChild(canvas);

        var ctx = canvas.getContext('2d');
        var text = "element";//overlay.elementIDs[i];

        ctx.beginPath();
        ctx.clearRect(0,0,300,300);
        ctx.fillStyle = 'white';
        ctx.fillRect(0,0,300,300);

        ctx.fillStyle = 'rgba(255,0,0,255)';
        ctx.lineWidth = 2.5;
        ctx.strokeStyle = 'black';
        ctx.save();
        ctx.font = 'bold 80px Verdana';

        var leftOffset = ctx.canvas.width/2;
        var rightOffset = ctx.canvas.height/2;
        ctx.strokeText(text,leftOffset,rightOffset);
        ctx.fillText(text,leftOffset,rightOffset);
        ctx.restore();

        var texttexture=gl.createTexture();

        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.bindTexture(gl.TEXTURE_2D,texttexture);
        gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,canvas);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        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);



    // Draw overlay
       gl.drawArrays(gl.TRIANGLES, 0, overlay.elementNumVertices[i]);
       }

  gl.disableVertexAttribArray(shaderProgram.aVertexPosition);
  gl.disableVertexAttribArray(shaderProgram.aVertexColor);
  }

我是Webgl的初学者,因为我只需要2d投影元素的2d文本标签,请告诉我是否有更简单的方法来做到这一点。

这是调用渲染函数的函数:

function saveModelImage(separateElementImages)
{
var glCanvas = document.getElementById("glCanvas");
glCanvas.width = 2144;
glCanvas.height = 1424;

var fov = deg2rad(60);
if(cameraIndex > -1)
{
    var f = model.cameras[cameraIndex].f;
    glCanvas.width = camImageWidths[cameraIndex];
    glCanvas.height = camImageHeights[cameraIndex];
    console.info("w: " + glCanvas.width + "  h: " + glCanvas.height);
    fov = 2 * Math.atan(0.5 * glCanvas.height / f);
}

gl.viewportWidth = glCanvas.width;
gl.viewportHeight = glCanvas.height;
gl.aspectRatio = gl.viewportWidth / gl.viewportHeight;
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.viewportCenter = vec3.fromValues(gl.viewportWidth / 2.0, gl.viewportHeight / 2.0);
updateBoundingRect();

mat4.ortho(orthoM, -gl.aspectRatio, gl.aspectRatio, -1.0, 1.0, 1.0, 100.0);
mat4.perspective(perspM, fov, gl.aspectRatio, 0.5, 10000);
// we need to pass in the cameraID to this function
// using camera.ID, we will find the accurate width and height to use for glCanvas.
// then the gl.aspectRatio could be set as above
// and FOV (in rad) = 2 atan(0.5 glCanvas.height / camera.f)


if(separateElementImages == true)
{
    //something
}
else
{
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    drawOverlayTriangles();

    var imageUrl = glCanvas.toDataURL('image/jpeg', 1.0);

    var pom = document.createElement('a');
    pom.setAttribute('href', imageUrl);
    pom.setAttribute('download', 'image_C' + cameraIndex + '.jpg');

    document.body.appendChild(pom);

    pom.click();

    document.body.removeChild(pom);
}
}

非常感谢任何帮助

1 个答案:

答案 0 :(得分:6)

最简单的方法是在webgl画布上绘制2d画布,或者在webgl画布上移动HTML元素。

在WebGL Canvas上绘制2d画布

var underCanvas = document.getElementById("under");
var overCanvas = document.getElementById("over");

// get a webgl context for the under canvas.
var gl = underCanvas.getContext("webgl");

// get a webgl context for the over canvas.
var ctx = overCanvas.getContext("2d");

var radius = 70;
var clock;
var x;
var y;

function render() {
  
  clock = Date.now() * 0.001;
 
  
  x = Math.floor(Math.cos(clock) * radius + gl.canvas.width  * 0.5);
  y = Math.floor(Math.sin(clock) * radius + gl.canvas.height * 0.5);
  
  
  drawWebGLStuff(gl);
  drawCanvas2DStuff(ctx);
  
  requestAnimationFrame(render);
}
render();


function drawWebGLStuff(gl) {
  // I'm using the SCISSOR because it's the simplest thing
  gl.disable(gl.SCISSOR_TEST);
  gl.clearColor(0, 0, 0, 0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  
  gl.scissor(
     Math.max(0, x - 10),
     Math.max(0, y - 10),
     20,
     20);
  gl.enable(gl.SCISSOR_TEST);
  gl.clearColor(0, 1, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
}

function drawCanvas2DStuff() {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.textAlign = "center";
  ctx.fillText("Hello World", x, ctx.canvas.height - y);
}
canvas {
  border: 1px solid black;
}
#under {
  position: absolute;
  left: 0px;
  top: 0px;
}
/* put "over" on top of "under" */
#over {
  position: absolute;
  left: 0px;
  top: 0px;
  z-index: 2;
}
<canvas id="under"></canvas>
<canvas id="over"></canvas>

通过在画布上移动HTML元素来绘图

var underCanvas = document.getElementById("under");
var overCanvas = document.getElementById("over");

// get a webgl context for the under canvas.
var gl = underCanvas.getContext("webgl");

// make a div for text
var textDiv = document.createElement("div");
textNode = document.createTextNode("");
textDiv.className = "over";
textDiv.appendChild(textNode);
document.body.appendChild(textDiv);


var radius = 70;
var clock;
var x;
var y;

function render() {
  
  clock = Date.now() * 0.001;
 
  
  x = Math.floor(Math.cos(clock) * radius + gl.canvas.width  * 0.5);
  y = Math.floor(Math.sin(clock) * radius + gl.canvas.height * 0.5);
  
  
  drawWebGLStuff(gl);
  moveTextDiv();
  
  requestAnimationFrame(render);
}
render();


function drawWebGLStuff(gl) {
  // I'm using the SCISSOR because it's the simplest thing
  gl.disable(gl.SCISSOR_TEST);
  gl.clearColor(0, 0, 0, 0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  
  gl.scissor(
     Math.max(0, x - 10),
     Math.max(0, y - 10),
     20,
     20);
  gl.enable(gl.SCISSOR_TEST);
  gl.clearColor(0, 1, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
}

function moveTextDiv() {
  textDiv.style.left = x + "px";
  textDiv.style.top  = (gl.canvas.height - y) + "px";
  textNode.nodeValue = clock.toFixed(2);
}
html, body {
  overflow: none;
  position: absolute;
}
canvas {
  border: 1px solid black;
}
#under {
  position: absolute;
  left: 0px;
  top: 0px;
}
.over {
  position: absolute;
  left: 0px;
  top: 0px;
  z-index: 2;
}
<body>
<canvas id="under"></canvas>
</body>