webgl——混合与模板测试

        今天研究了一个混合与模板测试相结合的案例,这里做以总结。
        案例中一个篮球在地板上不断弹起并且落下,这里主要涉及到了两项技术:混合与模板测试。首先篮球在地板上反射出来的镜像篮球就是通过混合技术实现的,为了让镜像体在运动脱离地板时消失,实现真实的效果,还需要加入模板测试。
        首先介绍他们的绘制顺序    
1.开启模板测试,关闭深度检测 
2.绘制实体地板  
3.设置模板测试参数    
4.绘制镜像球 ,禁用模板测试   
5.开启混合    
6.设置混合参数,绘制半透明地板
7.关闭混合,开启深度检测
        看到这里是不是有些头晕了,不过没关系,我们来一起理一理其中的思路。
        首先关于深度检测:深度检测在此案例中不需要使用,我们完全可以根据绘制的顺序来确定他们的显示顺序,当不开启深度检测时,会根据我们绘制的顺序来决定谁会覆盖谁。

        其次是模板测试,先清除上一次绘制产生的模板缓冲,使得缓冲中所有值为0,然后给地板设置模板缓冲的参数,其中设置  glStencilFunc(GL_ALWAYS, 1, 1); 这样一来,地板的像素的“模板值”为1,而其它地方像素的“模板值”为0。glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);这个函数第一个参数是未通过模板测试时的操作,第二个参数是通过模板测试,未通过深度测试的操作,第三个是深度测试和模板测试都通过时的操作。我对这个函数的理解是:当其它物体通过模板测试与深度测试时用其它物体的像素,取代该物体的像素。

//设置模板测试参数
gl.stencilFunc(gl.ALWAYS, 1, 1);
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);

        然后设置模板参数为equal,当进行比较时,通过比较ref也就是stencilFunc的第二个参数来确定是否通过模板测试,比较的方式是第一个参数也就是equal相等。所以当镜像体篮球在地板范围内时通过模板测试与深度测试,显示镜像。当球体超出地板范围之后模板测试失败,不显示该球体。

//设置模板测试参数
gl.stencilFunc(gl.EQUAL,1, 1); 
//设置模板测试后的操作
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);   
        最后是混合当理解了模板测试之后,混合也就更为简单了,我们在绘制地板时,实际是绘制了两次,第一次绘制了不透明度为1的地板,第二次绘制了不透明度为0.5的地板(也就是一个半透明的地板),半透明地板的作用就是参与混合,使得镜像篮球看起来更加真实,不会和实体篮球一样。所以这里使用了混合,目标因子是篮球的颜色,源因子是半透明地板,(用半透明地板去混合篮球,所以篮球是目标因子,地板是源因子)所以该参数的意思是根据(源因子的不透明度:目标因子减原因子的不透明度)这个比例来混合他们的颜色,最终达到镜像效果。

//开启混合
gl.enable(gl.BLEND);
//设置混合因子
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

下面是绘制部分的代码:

function drawFrame()
{
    if(!rectdb||!ball)
   {
      alert("加载未完成!");//提示信息
      return;
   }

      //清除着色缓冲与深度缓冲
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
             //清除模板缓存
         gl.clear(gl.STENCIL_BUFFER_BIT);
//关闭深度检测
gl.disable(gl.DEPTH_TEST);
//允许模板测试
         gl.enable(gl.STENCIL_TEST);

         //设置模板测试参数
         gl.stencilFunc(gl.ALWAYS, 1, 1);
         //设置模板测试后的操作
         gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);

ms.pushMatrix();
ms.scale(0.3,0.3,0.3);
     //绘制反射面地板
         rectdb.drawSelf(ms,texMap["db"]);
ms.popMatrix();

//设置模板测试参数
         gl.stencilFunc(gl.EQUAL,1, 1); 
         //设置模板测试后的操作
         gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);            
     //绘制镜像体
         drawmirror();
         //禁用模板测试
         gl.disable(gl.STENCIL_TEST);
         //开启混合
         gl.enable(gl.BLEND);
         //设置混合因子
         gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
ms.pushMatrix();
ms.scale(0.3,0.3,0.3);
     //绘制半透明反射面地板
         rectdb.drawSelf(ms,texMap["tm"]);
ms.popMatrix(); 
//开启深度检测
gl.enable(gl.DEPTH_TEST);
         //关闭混合
         gl.disable(gl.BLEND);  

     //绘制实际物体 
         drawball();
}

最后是图片和github地址:https://github.com/StringKun/WebGL-mirror-image



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值