Project

General

Profile

Drawing Text on a WGLWidget canvas

Added by Mina Mina almost 4 years ago

Hi everyone I am trying to convert the JS examples published on this site [[[https://webglfundamentals.org/webgl/lessons/webgl-text-canvas2d.html]]] to Wt because I need to write text at specific points on an already drawn obj model. I can draw obj models ALL is WELL!! The issue is with writing text in the same canvas with the model such that rotations, translations and scalings on the model are also acted upon by the text. Here is an example of the JS code and output for wat I need :

@

"use strict";

function main() {

// Get A WebGL context

/ @type {HTMLCanvasElement} */

var canvas = document.querySelector("#canvas");

var gl = canvas.getContext("webgl");

if (!gl) {

return;

}

// look up the text canvas.

var textCanvas = document.querySelector("#text");

// make a 2D context for it

var ctx = textCanvas.getContext("2d");

// setup GLSL program

var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);

// look up where the vertex data needs to go.

var positionLocation = gl.getAttribLocation(program, "a_position");

var colorLocation = gl.getAttribLocation(program, "a_color");

// lookup uniforms

var matrixLocation = gl.getUniformLocation(program, "u_matrix");

// Create a buffer to put positions in

var positionBuffer = gl.createBuffer();

// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

// Put geometry data into buffer

setGeometry(gl);

// Create a buffer to put colors in

var colorBuffer = gl.createBuffer();

// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = colorBuffer)

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

// Put geometry data into buffer

setColors(gl);

function radToDeg® {

return r * 180 / Math.PI;

}

function degToRad(d) {

return d * Math.PI / 180;

}

var translation = [0, 30, --360];

var rotation = [degToRad(190), degToRad(0), degToRad(0)];

var scale = [1, 1, 1];

var fieldOfViewRadians = degToRad(60);

var rotationSpeed = 1.2;

var then = 0;

requestAnimationFrame(drawScene);

// Draw the scene.

function drawScene(clock) {

// Convert to seconds

clock *= 0.001;

// Subtract the previous time from the current time

var deltaTime = clock - then;

// Remember the current time for the next frame.

then = clock;

// Every frame increase the rotation a little.

rotation[1] += rotationSpeed * deltaTime;

rotation[2] += deltaTime;

webglUtils.resizeCanvasToDisplaySize(gl.canvas);

webglUtils.resizeCanvasToDisplaySize(ctx.canvas);

// Tell WebGL how to convert from clip space to pixels

gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

// Clear the canvas AND the depth buffer.

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// Clear the 2D canvas

ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

// Turn on culling. By default backfacing triangles

// will be culled.

gl.enable(gl.CULL_FACE);

// Enable the depth buffer

gl.enable(gl.DEPTH_TEST);

// Tell it to use our program (pair of shaders)

gl.useProgram(program);

// Turn on the position attribute

gl.enableVertexAttribArray(positionLocation);

// Bind the position buffer.

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

// Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)

var size = 3; // 3 components per iteration

var type = gl.FLOAT; // the data is 32bit floats

var normalize = false; // don't normalize the data

var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position

var offset = 0; // start at the beginning of the buffer

gl.vertexAttribPointer(

positionLocation, size, type, normalize, stride, offset);

// Turn on the color attribute

gl.enableVertexAttribArray(colorLocation);

// Bind the color buffer.

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

// Tell the attribute how to get data out of colorBuffer (ARRAY_BUFFER)

var size = 3; // 3 components per iteration

var type = gl.UNSIGNED_BYTE; // the data is 8bit unsigned values

var normalize = true; // normalize the data (convert from 0-255 to 0-1)

var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position

var offset = 0; // start at the beginning of the buffer

gl.vertexAttribPointer(

colorLocation, size, type, normalize, stride, offset);

// Compute the matrices

var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;

var projectionMatrix =

m4.perspective(fieldOfViewRadians, aspect, 1, 2000);

var spread = 170;

for (var yy = --1; yy <= 1; ++yy) {

for (var xx = --2; xx <= 2; ++xx) {

var matrix = m4.translate(projectionMatrix,

translation[0] + xx * spread, translation[1] + yy * spread, translation[2]);

matrix = m4.xRotate(matrix, rotation[0]);

matrix = m4.yRotate(matrix, rotation[1] + yy * xx * 0.2);

matrix = m4.zRotate(matrix, rotation[2] + (yy * 3 + xx) * 0.1);

matrix = m4.translate(matrix, --50, --75, 0);

// Set the matrix.

gl.uniformMatrix4fv(matrixLocation, false, matrix);

// Draw the geometry.

gl.drawArrays(gl.TRIANGLES, 0, 16 * 6);

// compute a clipspace position

// using the matrix we computed for the F

var clipspace = m4.transformVector(matrix, [100, 0, 0, 1]);

// divide X and Y by W just like the GPU does.

clipspace[0] /= clipspace[3];

clipspace[1] /= clipspace[3];

// convert from clipspace to pixels

var pixelX = (clipspace[0] * 0.5 + 0.5) * gl.canvas.width;

var pixelY = (clipspace[1] * --0.5 + 0.5) * gl.canvas.height;

// draw an arrow and text.

// save all the canvas settings

ctx.save();

// translate the canvas origin so 0, 0 is at

// the top front right corner of our F

ctx.translate(pixelX, pixelY);

// draw an arrow

ctx.beginPath();

ctx.moveTo(10, 5);

ctx.lineTo(0, 0);

ctx.lineTo(5, 10);

ctx.moveTo(0, 0);

ctx.lineTo(15, 15);

ctx.stroke();

// draw the text.

ctx.fillText("" + xx + "," + yy, 20, 20);

// restore the canvas to its old settings.

ctx.restore();

}

}

requestAnimationFrame(drawScene);

}

}

// Fill the buffer with the values that define a letter 'F'.

function setGeometry(gl) {

gl.bufferData(

gl.ARRAY_BUFFER,

new Float32Array([

// left column front

0, 0, 0,

0, 150, 0,

30, 0, 0,

0, 150, 0,

30, 150, 0,

30, 0, 0,

// top rung front

30, 0, 0,

30, 30, 0,

100, 0, 0,

30, 30, 0,

100, 30, 0,

100, 0, 0,

// middle rung front

30, 60, 0,

30, 90, 0,

67, 60, 0,

30, 90, 0,

67, 90, 0,

67, 60, 0,

// left column back

0, 0, 30,

30, 0, 30,

0, 150, 30,

0, 150, 30,

30, 0, 30,

30, 150, 30,

// top rung back

30, 0, 30,

100, 0, 30,

30, 30, 30,

30, 30, 30,

100, 0, 30,

100, 30, 30,

// middle rung back

30, 60, 30,

67, 60, 30,

30, 90, 30,

30, 90, 30,

67, 60, 30,

67, 90, 30,

// top

0, 0, 0,

100, 0, 0,

100, 0, 30,

0, 0, 0,

100, 0, 30,

0, 0, 30,

// top rung right

100, 0, 0,

100, 30, 0,

100, 30, 30,

100, 0, 0,

100, 30, 30,

100, 0, 30,

// under top rung

30, 30, 0,

30, 30, 30,

100, 30, 30,

30, 30, 0,

100, 30, 30,

100, 30, 0,

// between top rung and middle

30, 30, 0,

30, 60, 30,

30, 30, 30,

30, 30, 0,

30, 60, 0,

30, 60, 30,

// top of middle rung

30, 60, 0,

67, 60, 30,

30, 60, 30,

30, 60, 0,

67, 60, 0,

67, 60, 30,

// right of middle rung

67, 60, 0,

67, 90, 30,

67, 60, 30,

67, 60, 0,

67, 90, 0,

67, 90, 30,

// bottom of middle rung.

30, 90, 0,

30, 90, 30,

67, 90, 30,

30, 90, 0,

67, 90, 30,

67, 90, 0,

// right of bottom

30, 90, 0,

30, 150, 30,

30, 90, 30,

30, 90, 0,

30, 150, 0,

30, 150, 30,

// bottom

0, 150, 0,

0, 150, 30,

30, 150, 30,

0, 150, 0,

30, 150, 30,

30, 150, 0,

// left side

0, 0, 0,

0, 0, 30,

0, 150, 30,

0, 0, 0,

0, 150, 30,

0, 150, 0]),

gl.STATIC_DRAW);

}

// Fill the buffer with colors for the 'F'.

function setColors(gl) {

gl.bufferData(

gl.ARRAY_BUFFER,

new Uint8Array([

// left column front

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

// top rung front

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

// middle rung front

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

200, 70, 120,

// left column back

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

// top rung back

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

// middle rung back

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

80, 70, 200,

// top

70, 200, 210,

70, 200, 210,

70, 200, 210,

70, 200, 210,

70, 200, 210,

70, 200, 210,

// top rung right

200, 200, 70,

200, 200, 70,

200, 200, 70,

200, 200, 70,

200, 200, 70,

200, 200, 70,

// under top rung

210, 100, 70,

210, 100, 70,

210, 100, 70,

210, 100, 70,

210, 100, 70,

210, 100, 70,

// between top rung and middle

210, 160, 70,

210, 160, 70,

210, 160, 70,

210, 160, 70,

210, 160, 70,

210, 160, 70,

// top of middle rung

70, 180, 210,

70, 180, 210,

70, 180, 210,

70, 180, 210,

70, 180, 210,

70, 180, 210,

// right of middle rung

100, 70, 210,

100, 70, 210,

100, 70, 210,

100, 70, 210,

100, 70, 210,

100, 70, 210,

// bottom of middle rung.

76, 210, 100,

76, 210, 100,

76, 210, 100,

76, 210, 100,

76, 210, 100,

76, 210, 100,

// right of bottom

140, 210, 80,

140, 210, 80,

140, 210, 80,

140, 210, 80,

140, 210, 80,

140, 210, 80,

// bottom

90, 130, 110,

90, 130, 110,

90, 130, 110,

90, 130, 110,

90, 130, 110,

90, 130, 110,

// left side

160, 160, 220,

160, 160, 220,

160, 160, 220,

160, 160, 220,

160, 160, 220,

160, 160, 220]),

gl.STATIC_DRAW);

}

main();

@

See attached image for the desired image of the text.


Replies (1)

RE: Drawing Text on a WGLWidget canvas - Added by Wim Dumon almost 4 years ago

Hello Mina,

The page you refers to puts a 2D canvas and a 3D canvas on top of each other. You can do that in Wt too, by using a WGLWidget (for 3D) and a WPaintedWidget (for 2D).

The coupling of the transformation matrix of the 3D canvas to the one of the 2D canvas requires some creativity, but I think it is possible with the use of a small amount of client-side javascript code, since both classes support client-side transformation matrices.

BR,

Wim.

    (1-1/1)