WebGL-15.HUB效果

本系列教程主要讲解利用WebGL开发网页版的三维图形程序。这里主要用到的OpenGL和FlyMath内容。本系列内容较难。要求学生对几何和编程有一定的了解。建议初三以上同学学习。

平视显示器(head up display)简称HUD。最早用于飞机驾驶,平视显示器将一些重要信息投射到飞机驾驶舱前方的一块玻璃上。飞行员不用低头观察仪表盘。在WebGL用这个功能可以在用来显示提示、菜单等信息。会让你的WebGL程序变得更酷。

WebGL中应用HUD是很方便的,其实这也不能算WebGL技术。是只是在绘制WebGL的Canvas上方,再绘制一个透明的,有HUD信息的Canvas。或者两者反过来。

程序设计上要注意两个Canvas的大小位置一定要重叠。否则就会影响视觉。

我们来看下程序吧。程序是关键点就是让Canvas或WebGL渲染的背景设为透明。


Html代码

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html>
<title>HUD应用</title>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<script type="text/javascript" src='http://www.cmnsoft/jquery-1.11.1.min.js' charset="utf-8"></script>
<script type="text/javascript" src='https://www.cmnsoft.com/flymath/flymath_min.js' charset="utf-8"></script>
<script>
//定义全局GL上下文
var gl_context;
     
//循环控制参数
var curTime;
var isStop=0;
    
//偏移步长
var cur_x = 0;
var x_step = 0.01;
     
//定义Camera位置
var camera = [0,0,1];
var camera_to = [0,0,0];
var camera_up = [0,1,0];
     
//定义颜色数组
var color = [1,0,0];
    
//定义camera矩阵和工程矩阵
var matView = new Array;
var matProject = new Array;
var matOffset = new Array;
     
//定义纹理图片
var curImg;
var imgSrc = "http://www.cmnsoft.com/cai/webgl/img/WebGL-Logo.png";
    
//时间函数
function onTime()
{
    cur_x += x_step;
        
    if(cur_x>0.5 || cur_x<-0.5)
        x_step *=-1;
        
    draw_quad();  
    curTime = setTimeout("onTime()",100);
}
      
//加载纹理图片
function pre_loadImg()
{ 
    curImg = new Image();
    curImg.src = imgSrc;
         
    curImg.onload = function()
    {
        onTime();
        return;
    }
         
    curImg.onerror = function()
    {
        alert("加载纹理图片失败!");
        return;
    }   
}
     
//初始化WebGL
function init_webgl()
{
  var canvas0 = document.getElementById("webGL0");
  var canvas1 = document.getElementById("webGL1");
  var canvas2 = document.getElementById("webGL2");
       
  if(!canvas0 || !canvas1 || !canvas2){
    alert("获取<Canvas>标签失败!");
    return;
  }
     
  //获取webGL统计图上下文
  gl_context = canvas1.getContext('webgl',
                { antialias:true,
                  depth:true,
                  stencil:true});
     
  if(!gl_context){
    alert("获取WebGL上下文失败!");
    return;
  }
     
  canvas0.width = $("#area").width();
  canvas0.height = $("#area").width()*3/5;
      
  canvas1.width = canvas0.width;
  canvas1.height = canvas0.height;
      
  canvas2.width = canvas0.width;
  canvas2.height = canvas0.height;
      
  var y=$("#area").offset().top;
  var x=$("#area").offset().left;
    
  $("#webGL1").css("top",y);
  $("#webGL1").css("left",x);
      
  $("#webGL2").css("top",y);
  $("#webGL2").css("left",x);
      
    
  var ctx0=canvas0.getContext("2d");
  ctx0.font="60px 黑体";
  ctx0.fillStyle = '#ffff00';
  ctx0.fillText("最底层的HUD",canvas0.width/2-130,canvas0.height/2-30);
      
  var ctx2=canvas2.getContext("2d");
  ctx2.font="60px 黑体";
  ctx2.fillStyle = '#ff0000';
  ctx2.fillText("最前面的HUD",canvas0.width/2-130,canvas0.height/2+30);
     
  //设置视口大小
  gl_context.viewport(0,0,canvas1.width,canvas1.height);
     
  //设置matView和matProject矩阵
  FlyMath.Matrix.LookAtRH(matView,camera,camera_to,camera_up);
  FlyMath.Matrix.PerspectiveRH(matProject,FlyMath_PI/3,1,1,100);
     
  pre_loadImg();
}
     
//绘制正方形
function draw_quad()
{
//清空canvas的背景颜色
  gl_context.clearColor(0,0,0.5,0);
     
  //清空webgl颜色缓冲区和深度缓冲区里的内容
  gl_context.clear(gl_context.COLOR_BUFFER_BIT | gl_context.DEPTH_BUFFER_BIT);
  //开启深度缓冲检测
  gl_context.enable(gl_context.DEPTH_TEST);
     
//定义顶点shader和片断shader
    var vs_src = "attribute vec4 a_Position;\n" +
                "attribute vec2 a_UV;\n" +
                "uniform mat4 projectionMatrix;\n" +
                "uniform mat4 modelViewMatrix;\n" +
                "uniform mat4 offsetMatrix;\n" +
                "varying vec2 A_UV;\n" +             
                "void main() {\n" +
                    "gl_Position = projectionMatrix * modelViewMatrix * offsetMatrix * a_Position;\n"+
                    "A_UV = a_UV;\n" +
                    "}\n";
     
    var fs_src = "precision highp float;\n" +
                "varying vec2 A_UV;\n" +
                "uniform sampler2D A_Texture;\n" +
                "void main() {\n" +
                " vec4 imgColor = texture2D(A_Texture,A_UV);\n" +
                " gl_FragColor = imgColor;\n" +
                "}\n";
                    
    var vs = gl_context.createShader(gl_context.VERTEX_SHADER);
    gl_context.shaderSource(vs,vs_src);
    gl_context.compileShader(vs);
       
    if(!gl_context.getShaderParameter(vs,gl_context.COMPILE_STATUS)){
        alert(gl_context.getShaderInfoLog(vs));
        return;
    }
     
    var fs = gl_context.createShader(gl_context.FRAGMENT_SHADER);
    gl_context.shaderSource(fs,fs_src);
    gl_context.compileShader(fs);
       
    if(!gl_context.getShaderParameter(vs,gl_context.COMPILE_STATUS)){
        alert(gl_context.getShaderInfoLog(fs));
        return;
    }
     
//加载选择的顶点和片断
    var shaderProgram = gl_context.createProgram();
    gl_context.attachShader(shaderProgram, vs);
    gl_context.attachShader(shaderProgram, fs);
    gl_context.linkProgram(shaderProgram);
     
    if (!gl_context.getProgramParameter(shaderProgram, gl_context.LINK_STATUS)) {
        alert("Could not initialise shaders");
        return;
    }
     
//绑定shader中的参数变量
    var shader_pos = gl_context.getAttribLocation(shaderProgram, "a_Position");
    var shader_uv = gl_context.getAttribLocation(shaderProgram, "a_UV");
    
    var shaderModelViewMatrixUniform = gl_context.getUniformLocation(shaderProgram,"modelViewMatrix");
    var shaderProjectionMatrixUniform = gl_context.getUniformLocation(shaderProgram,"projectionMatrix");
    var shaderOffsetMatrixUniform = gl_context.getUniformLocation(shaderProgram,"offsetMatrix");
    var SamplerUniform = gl_context.getUniformLocation(shaderProgram,"A_Texture");
     
/* 正方形顶点位置
    0 , 1
    2 , 3 
*/
    var vertices = new Float32Array([-0.3,0.3,-1,0.3,0.3,-1,-0.3,-0.3,-1,0.3,-0.3,-1]);
    var indices =  [0,1,2,1,2,3];
    var uvs = [0,0,1,0,0,1,1,1];
        
    FlyMath.Matrix.Translation(matOffset,cur_x,0,0);
     
    var quad_buf = gl_context.createBuffer();
    var indexBuffer = gl_context.createBuffer();
    var uvBuffer = gl_context.createBuffer();
                
//使用选择的程序,激活缓冲区,渲染
    gl_context.useProgram(shaderProgram);
    gl_context.enableVertexAttribArray(shader_pos);
    gl_context.enableVertexAttribArray(shader_uv);
     
    gl_context.bindBuffer(gl_context.ARRAY_BUFFER, quad_buf);
    gl_context.bufferData(gl_context.ARRAY_BUFFER, new Float32Array(vertices), gl_context.STATIC_DRAW);
    gl_context.vertexAttribPointer(shader_pos, 3, gl_context.FLOAT, false, 0, 0);
     
    gl_context.bindBuffer(gl_context.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl_context.bufferData(gl_context.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl_context.STATIC_DRAW);
         
    gl_context.bindBuffer(gl_context.ARRAY_BUFFER,uvBuffer);
    gl_context.bufferData(gl_context.ARRAY_BUFFER,new Float32Array(uvs),gl_context.STATIC_DRAW);
    gl_context.vertexAttribPointer(shader_uv, 2, gl_context.FLOAT, false, 0, 0);
     
//绑定矩阵
    gl_context.uniformMatrix4fv(shaderModelViewMatrixUniform,false,matView);
    gl_context.uniformMatrix4fv(shaderProjectionMatrixUniform,false,matProject);
    gl_context.uniformMatrix4fv(shaderOffsetMatrixUniform,false,matOffset);
         
//绑定纹理图片,设置纹理坐标方式
    var img_texture = gl_context.createTexture();
    gl_context.bindTexture(gl_context.TEXTURE_2D, img_texture);
    gl_context.texImage2D(gl_context.TEXTURE_2D, 0, gl_context.RGBA, gl_context.RGBA, gl_context.UNSIGNED_BYTE, curImg);
     
    gl_context.texParameteri(gl_context.TEXTURE_2D, gl_context.TEXTURE_MIN_FILTER, gl_context.NEAREST);
    gl_context.texParameteri(gl_context.TEXTURE_2D, gl_context.TEXTURE_MAG_FILTER, gl_context.NEAREST);
    gl_context.texParameteri(gl_context.TEXTURE_2D, gl_context.TEXTURE_WRAP_S, gl_context.CLAMP_TO_EDGE);
    gl_context.texParameteri(gl_context.TEXTURE_2D, gl_context.TEXTURE_WRAP_T, gl_context.CLAMP_TO_EDGE);
         
    gl_context.activeTexture(gl_context.TEXTURE0);
    gl_context.bindTexture(gl_context.TEXTURE_2D, img_texture);
         
    gl_context.uniform1i(SamplerUniform, 0);
         
    gl_context.drawElements(gl_context.TRIANGLES,indices.length,gl_context.UNSIGNED_BYTE, 0); 
}
    
</script>
    
</head>
<body>
<center>
<div id='area' style='width:80%;'>
<canvas id='webGL0' width='600' height='400' style='border:1px solid #000000;'>
<b>浏览器不支持Webgl_context.</b>
</canvas>
<canvas id='webGL1' width='600' height='400' style='position:absolute;z-index:100;border:1px solid #000000;'>
<b>浏览器不支持Webgl_context.</b>
</canvas>
<canvas id='webGL2' width='600' height='400' style='position:absolute;z-index:101;border:1px solid #000000;'>
<b>浏览器不支持Webgl_context.</b>
</canvas>
</div>
</center>
</body>
<script>init_webgl();</script>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值