webgl实现物体描边效果的方法介绍

 更新时间:2019年11月27日 10:30:04   作者:String_Kun  
这篇文章主要给大家介绍了关于webgl实现物体描边效果的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用webgl具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

终于把手头的事结束了,可以有时间来研究研究技术~作为一名3D开发人员,仅仅使用现有的引擎来开发项目不免有些浮于表面,多研究研究底层的实现更利于对3D开发整体的把控~于是我决定最近开始研究webgl一些特效的实现,希望能在秋招前对底层有更深入的理解。

在webgl中实现描边的效果有很多种方式,比如我写卡通风格着色器那篇文章讲到的(将视线投影到每个点的法线上,这个值越小越说明这个点靠近边缘),所以接下来介绍实现的另一种方式:法线延展法。

这种方法不用进行法线与视线之间的计算,而是将物体每个点的x、y、z坐标沿着该点的法线扩大一定的距离并且添加描边的颜色,然后在绘制原来的物体覆盖到上面,这样便实现了描边的效果。

这里将原物体覆盖到描边物体上面就有两种实现的方式:

1.先关闭深度检测,然后绘制描边物体,开启深度检测,绘制原物体。这样由于绘制描边物体时深度检测被关闭了,原物体就会覆盖在描边物体上绘制从而实现描边效果。缺点:当两个物体重合时会出现重合位置没有描边的情况,这是由于第二次绘制的东西覆盖到了第一次描边的物体上,所以先画的边自然就会被遮挡啦~

2.不关闭深度检测,开启背面剪裁,绘制描边物体时将卷绕方向置为顺时针方向(默认是逆时针),在进行绘制,绘制完成之后将卷绕方向设置回顺时针方向。这样背面剪裁的开启使得描边物体只能绘制出它的背面,这样便实现了描边效果,而且由于没有关闭深度测试,该物体的描边效果会根据其位置决定是否遮挡。

  //绘制一帧画面的方法
  function drawFrame()
  {   
   //若还没有加载完则不绘制
   if(!ooTri || !mbTri) {return;}
   
   //清除着色缓冲与深度缓冲
   gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
   
   //保护现场
   ms.pushMatrix();   
   //绕Y轴旋转
   ms.rotate(currentAngle,0,1,0);
//方法1
//   gl.disable(gl.DEPTH_TEST);      //启用深度缓冲写入
//   mbTri.drawSelf(ms);//绘制描边物体
//   gl.enable(gl.DEPTH_TEST);      //关闭深度缓冲写入
//   ooTri.drawSelf(ms);//绘制原物体
//方法2
   gl.enable(gl.CULL_FACE);      //开启剪裁
   gl.cullFace(gl.BACK);       //剪裁背面
   gl.frontFace(gl.CW);       //绘制顺序为顺时针
   mbTri.drawSelf(ms);//绘制描边物体
   gl.frontFace(gl.CCW);       //绘制顺序为逆时针
   ooTri.drawSelf(ms);//绘制原物体


   //恢复现场
   ms.popMatrix();
   
   //修改旋转角度
   currentAngle += incAngle;
   if (currentAngle > 360)
   {
    currentAngle -= 360; 
   }   
  } 
  其着色器代码如下:
uniform mat4 uMVPMatrix;       //总变换矩阵
attribute vec3 aPosition;         //顶点位置
attribute vec3 aNormal;         //顶点法向量
void main(){
 vec3 position=aPosition;      //获取此顶点位置
 position.xyz+=aNormal*0.4;    //将顶点位置沿法线方向挤出
 gl_Position = uMVPMatrix * vec4(position.xyz,1);//根据总变换矩阵计算此次绘制此顶点位置
}
<#BREAK_BN#>
precision mediump float;        //设置浮点默认精度

void main(){
 gl_FragColor = vec4(0.0,1.0,0.0,0.0);     //给此片元颜色值
}

其实这两种描边方法还是有着一些区别(第二种对于复杂物体会产生类似包裹的效果)具体效果还得根据具体的场景来决定。

PS:这里还要注意一点,WebGL是个状态机。我们可以这么理解,假设WebGL中的属性P的值为1,你在某一次操作中,把P的值设置成了2,那么在你下一次设置P的值之前,P的值永远是2。这一点很重要!

Github地址:https://github.com/StringKun/WebGL-object-of-stroke


总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • Three.js中的纹理图像应用和属性调整方法

    Three.js中的纹理图像应用和属性调整方法

    在three.js中纹理贴图是用来给物体表面添加图案、颜色或者其他视觉效果的一种技术,这篇文章主要给大家介绍了关于Three.js中纹理图像应用和属性调整的相关资料,需要的朋友可以参考下
    2024-01-01
  • 微信小程序之几种常见的弹框提示信息实现详解

    微信小程序之几种常见的弹框提示信息实现详解

    这篇文章主要介绍了微信小程序之几种常见的弹框提示信息实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • 关于ES6的六个小特性(二)

    关于ES6的六个小特性(二)

    ES6提供了大量新的好的东西,在过去的一年内,浏览器提供商做了大量的辛勤工作将新的语言特性更新到他们的浏览器中。尽管有重大的更新,很多小的语言更新另我眼前一亮,下面这篇文章主要介绍了关于ES6的六个小特性,需要的朋友可以参考下。
    2017-02-02
  • JavaScript制作简单的日历效果

    JavaScript制作简单的日历效果

    这篇文章主要为大家介绍了JavaScript制作简单的日历效果实现代码,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • p5.js码绘“跳动的小正方形”的实现代码

    p5.js码绘“跳动的小正方形”的实现代码

    这篇文章主要介绍了p5.js码绘“跳动的小正方形”,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • JavaScript中arguments的使用方法详解

    JavaScript中arguments的使用方法详解

    这篇文章主要给大家介绍了关于JavaScript中arguments的使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • JS中的Replace()传入函数时的用法详解

    JS中的Replace()传入函数时的用法详解

    这篇文章主要介绍了JS中的Replace()传入函数时的用法详解,replace方法的语法是:stringObj.replace(rgExp, replaceText)关于js replace 传入函数的用法,大家通过本文学习吧
    2017-09-09
  • JsRender for index循环索引用法详解

    JsRender for index循环索引用法详解

    这篇文章主要介绍了JsRender for index循环索引用法,以实例形式详细分析了JsRender中循环的用法,需要的朋友可以参考下
    2014-10-10
  • js实现双击单元格变成文本输入框效果代码

    js实现双击单元格变成文本输入框效果代码

    单击单元格,即可将其变为文本框,方便编辑测试
    2008-04-04
  • JS中forEach()和map()的区别讲解

    JS中forEach()和map()的区别讲解

    forEach和map方法都是基于数组的迭代器实现的,它们的主要区别在于对回调函数的处理方式,这篇文章主要介绍了JS中forEach()和map()的区别,需要的朋友可以参考下
    2024-02-02

最新评论