更新于 

HUD

HUD平视显示器

什么是HUD?

答: head up display ,即 平视显示器
之所以是 平视 , 是因为最初是用于称呼方便飞行员能够平视前方的驾驶舱玻璃就能够看到仪表图形投影的显示器。

本例要实现的HUD即在三维场景前方绘制二维三角形和文本。

简单实现思路
  1. 三维图形二维图形 各自准备一个 canvas
  2. 将两个canvas 重叠放置 (HUD在上)。
  3. 在三维canvas上使用 WebGL API 绘制三维场景。
  4. 在二维canvas上使用 canvas 2D API绘制HUD信息。
HUD Code
HUD运行效果
HUD运行效果
1
2
3
4
<body onload="main()">
<canvas id="webgl" width="400" height="400" style="position:absolute; z-index:0;"></canvas>
<canvas id="hud" width="400" height="400" style="position:absolute; z-index:1;"></canvas>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function main() {
let canvas = document.getElementById('webgl');
let hud = document.getElementById('hud');

let gl = getWebGLContext(canvas);
let ctx = hud.getContext('2d');

...

let tick = function () {
currentAngle = animate(currentAngle);
draw(gl, n, vpMatrix, currentAngle, u_MvpMatrix);
draw2D(ctx, currentAngle);
requestAnimationFrame(tick);
}
tick();

hud.onmousedown = function (ev) {
...
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function draw2D(ctx, currentAngle) {
// Draw triangle
ctx.clearRect(0, 0, 400, 400);
ctx.beginPath();
ctx.moveTo(120, 10);
ctx.lineTo(200, 150);
ctx.lineTo(40, 150);
ctx.closePath();
ctx.strokeStyle = 'rgba(0,255,0,1)';
ctx.stroke();

// Draw letters
ctx.font = '18px "Times New Roman"';
ctx.fillStyle = 'rgba(0,255,0,1)';
ctx.fillText('HUD: Head Up Display', 40, 180);
ctx.fillText('Triangle is drawn by Canvas 2D API,', 40, 200);
ctx.fillText('Cube is drawn by WebGL API.', 40, 220);
ctx.fillText('Current Angle: ' + Math.floor(currentAngle), 40, 240);
}
有关程序的一些问题。
HUD.js大部分是基于PickFace.js的,二者的区别在哪里?
  • 获取的上下文不同
    • PickFace 只获取三维画布
      1
      2
      let canavs = document.getElementById('webgl');
      let gl = getWebGLContext(canvas);
    • HUD 获取二维和三维画布
      1
      2
      3
      4
      let canavs = document.getElementById('webgl');
      let hud = document.getElementById('hud');
      let gl = getWebGLContext(canvas);
      let ctx = getWebGLContext(hud);
  • 鼠标点击事件注册的画布不同(主要是因为画布层级不同)
    • PickFace 的鼠标事件注册到 三维画布
      1
      canvas.onmousedown = function(ev){...}
    • HUD 的鼠标事件注册到 二维画布
      1
      hud.onmousedown = function(ev){...}
draw2D中绘制使用的函数都具有什么特征?

clearRect

1
ctx.clearRect(0,0,400,400)

用于清除给定矩形内的像素。

beginPath

1
ctx.beginPath()

用于起始一条路径,或重置当前路径。

moveTo

1
ctx.moveTo(120, 10);

用于把路径移动到画布中的指定点,不创建线条。

lineTo

1
2
ctx.lineTo(200,150);
ctx.lineTo(40,150);

用于添加一个新点,然后在画布中创建从该点到最后指定点的线条。

closePath

1
ctx.closePath();

用于创建从当前点回到起始点的路径。

stroke

1
ctx.strokeStyle = 'rgba(0,255,0,1)';

用于设置或返回用于笔触的颜色、渐变或模式。

1
ctx.stroke();

用于绘制已定义的路径。

text

1
ctx.font = '18px "Times New Roman"';

用于设置或返回文本内容的当前字体属性

1
ctx.fillStye = 'rgba(0,255,0,1)';

用于设置或返回用于填充绘画的颜色、渐变或模式。

1
2
3
4
ctx.fillText('HUD: Head Up Display', 40, 180);
ctx.fillText('Triangle is drawn by Canvas 2D API,', 40, 200);
ctx.fillText('Cube is drawn by WebGL API.', 40, 220);
ctx.fillText('Current Angle: ' + Math.floor(currentAngle), 40, 240);

用于在画布上绘制被填充的文本。

在网页上方显示三维物体

该程序是基于PickFace。

3DoverWeb Code
3DoverWeb运行效果
3DoverWeb运行效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body onload="main()">
<canvas id="webgl" width="400" height="400" style="position:absolute;"></canvas>
<div>
<h1>19<h1>

<h2>Great Designs Come from Great Designers --- Not from Great Design Processes</h2>

<p>The basic premise underlying the SEI's [Software
Engineering Institute] work on software process maturity
is that the quality of a software product is largely
determined by the quality of the software development
and maintenance processes used to build it.</p>

Mark Paulk [1995], "The evolution of clothe SEI's capability maturity model for software"

<p>...[W]hile some may see them as the crazy ones, we see
genius, because the ones who are crazy enough to think
that they can change the world, are the ones who do.</p>

Steve Jobs, Apple commercial (1997)

</div>
</body>

与PickFace唯一的不同就是canvas背景色的设置。

1
2
3
4
5
6
...
function main(){
...
gl.clearColor(0,0,0,0);
...
}