14.隐藏面消除

1.隐藏面消除:虽然透视投影已经将场景的深度效果表现了出来,但是要想得到真实的立体效果还需要将物体的前后遮挡关系正确的显示出来。遗憾的是WebGL并没有那么智能
    WebGL在默认情况下会按照缓冲区中的顺序绘制图形,而且后绘制的图形覆盖先绘制的图形。但是WebGL提供了隐藏面消除功能:
    (1)开启隐藏面消除功能:
gl.enable(gl.DEPTH_TEST);
    (2)在绘制之前清除深度缓冲区
gl.clear(gl.DEPTH_BUFFER_BIT);
2.gl.DEPTH_TEST深度检测与gl.DEPTH_BUFFER_BIT深度缓冲区
    深度检测:检测物体每个像素的深度来决定是否将其画出
    深度缓冲区:用来存储深度信息。在绘制任意一帧图片时都必须清除深度缓冲区,以消除绘制上一帧时在其中留下的痕迹

  同时清理颜色缓冲区和深度缓冲区(注意隐藏面消除成功的前提是正确设置可视空间)

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

3.深度冲突:

    当几何图形或物体的两个表面极为接近时,由于深度缓冲区精度有限,无法区分哪个在前哪个在后

4.多边形偏移:用于解决深度冲突,该机制自动在Z值上增加一个偏移量,偏移量的值由物体表面相对于观察者视线的角度来确定。

    (1)启用多边形偏移

gl.enable(gl.POLYGON_OFFSET_FILL);

    (2)指定用来计算偏移量的参数

gl.polygonOffset(1.0,1.0);

API:gl.polygonOffset(factor,units)

        偏移量=m*factor+r*units,其中m表示顶点所在面相对于观察者的视线的角度,r表示硬件能区分两个z值之差的最小值。

var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'varying vec4 v_Color;\n' +
'uniform mat4 u_viewMatrix;\n' +
'uniform mat4 u_projMatrix;\n' +
'void main(){\n' +
'gl_Position = u_projMatrix * u_viewMatrix * a_Position;\n' +
'gl_PointSize = 10.0;\n'+
'v_Color = a_Color;\n' +
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n' +
'varying vec4 v_Color;\n'+
'void main(){\n' +
'gl_FragColor = v_Color;\n' +
'}\n';

function main()
{
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
if(!gl)
{
console.log("获取上下文失败");
}

if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE))
{
console.log("着色器初始化异常");
}
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
gl.enable(gl.POLYGON_OFFSET_FILL);
var n = initVertexBuffers(gl);
var viewMatrix = new Matrix4();
var u_viewMatrix = gl.getUniformLocation(gl.program,'u_viewMatrix');
viewMatrix.setLookAt(0,0,10,0,0,-1.0,0,1,0);
gl.uniformMatrix4fv(u_viewMatrix,false,viewMatrix.elements);

var projMatrix = new Matrix4();
projMatrix.setPerspective(30,canvas.width/canvas.height,1,100);
var u_projMatrix = gl.getUniformLocation(gl.program,'u_projMatrix');
gl.uniformMatrix4fv(u_projMatrix,false,projMatrix.elements);
gl.drawArrays(gl.TRIANGLES,0,n/2);


gl.polygonOffset(1.0,1.0);
gl.drawArrays(gl.TRIANGLES,n/2,n/2);
}

function initVertexBuffers(gl)
{
var verticescColor = new Float32Array([
0.0,2.5,-5.0,0.0,1.0,0.0,
-2.5,-2.5,-5.0,0.0,1.0,0.0,
2.5,-2.5,-5.0,0.0,1.0,0.0,

0.0,3.0,-5.0,1.0,0.0,0.0,
-3.0,-3.0,-5.0,1.0,0.0,0.0,
3.0,-3.0,-5.0,1.0,0.0,0.0
]);
var n = 6;
var FSIZE = verticescColor.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
if(a_Position<0)
{
console.log("a_Position变量地址获取失败");
}
var a_Color = gl.getAttribLocation(gl.program,'a_Color');
if(!a_Color)
{

console.log("a_Color变量地址获取失败");
}

var vertexBuffer = gl.createBuffer();
if(!vertexBuffer)
{
console.log("缓冲区创建失败");
}
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticescColor,gl.STATIC_DRAW);
gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*6,0);
gl.enableVertexAttribArray(a_Position);
gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE*6,FSIZE*3);
gl.enableVertexAttribArray(a_Color);

return n;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值