翼度科技»论坛 编程开发 JavaScript 查看内容

ThreeJS Shader的效果样例网格平面和网格球体(一)

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
本文中效果主要采用ThreeJS 中的着色器(Shader)以及结合ShaderMaterial实现的。
主要用到的内置方法有:
step:是一个阶跃函数,它将一个浮点数与一个阈值进行比较,并返回一个阶跃值;   比如step(edge, x), 如果 x 小于等于 edge,则返回 0.0, 如果 x 大于 edge ,则返回 1.0。fract:用于获取浮点数的小数部分。它返回输入值的小数部分,即去除整数部分后的部分。比如fract(1.5),返回0.5;一、网格平面
  1. const vertex = '\
  2.     varying vec3 vPos;\
  3.     void main() {\
  4.       vPos = position;\
  5.       gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
  6.     }\
  7.   ';
  8.   const frag = '\
  9.     varying vec3 vPos;\
  10.     void main() {\
  11.       vec3 mask1 = vec3(step(0.5, fract(vPos.x * 2.0)));\
  12.       vec3 mask2 = vec3(step(0.5, fract(vPos.y * 2.0)));\
  13.       vec3 mask3 = vec3(step(0.5, fract(vPos.z * 2.0)));\
  14.       vec3 color = abs(mask1 - mask2);\
  15.       gl_FragColor = vec4(color, 1.0);\
  16.     }\
  17.   ';
复制代码
 原理:如果设置平面的大小为2,那么坐标轴X点的范围为-1.0 ~ 1.0,已X坐标为示例,数据变化形式如下图 
  

    如上图可以将数据分为4个部分,X轴和Y轴同理:
      1) 0~0.25的数据经过fract和step函数处理后数据变为0;
      2)   0.25~0.5的数据经过fract和step函数处理后数据变为1;
      3) 0.5~0.75的数据经过处理变为0;
      4) 0.75~1.0的数据经过处理变为1;
     最后将生成的向量X轴-Y轴数据可以绘制成如下图:
  

  这样就生成了第一象限的图形,第二、三、四象限结果同上。
二、网格状的球体 
   
本列中涉及到GLSL的几个内置函数:
dot:两个向量的点积,可以获得向量的夹角
asin: 反三角函数,获得弧度值
1. 第一个图就是要实现的最终效果,一个网格状的球体,实现原理主要可以分为分别计算经度方向的线圈和纬度方向的线圈。
2. 与平面网格计算颜色值相同,将两个颜色值相减即可得到一个网格球体
3. 如何实现纬度方向的线圈?
          

  实现逻辑:将球体沿球心纵向切一刀生成一个圆形横截面M,将圆分成弧度相等的N个圆弧,然后再间隔开赋予不同的颜色就可以形成图一的效果。
  1. const vertex = '\
  2.     varying vec3 vPos;\
  3.     void main() {\
  4.       vPos = position;\
  5.       gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
  6.     }\
  7.   ';
  8.   // 获取UV点对应的单位向量B
  9.   // 获取Z轴方向的单位向量A
  10.   // 计算向量B和向量A的夹角
  11.   // 通过degree将夹角的弧度转换成角度,除以要拆分的条数latBeta,通过配合fract和step即可获取间隔的0、1值
  12.   // 最后生成间隔的黑白颜色值
  13.   const frag = '\
  14.     uniform float latBeta;\
  15.     varying vec3 vPos;\
  16.     void main() {\
  17.       vec3 latEveryVec = normalize(vPos);\
  18.       vec3 latBaseVec = normalize(vec3(vPos.x, 0, vPos.z));\
  19.       float latAngle = asin(dot(latBaseVec, latEveryVec));\
  20.       vec3 latColor = vec3(step(0.5, fract(degrees(latAngle) / latBeta)));\
  21.       gl_FragColor = vec4(latColor, 1.0);\
  22.     }\
  23.   ';
复制代码
 
4. 如何实现经度方向的线圈?
    

 实现逻辑:与第三步生成纬度方向的线圈类似,将球体沿球心横向切一刀生成一个圆形横截面M,将圆分成弧度相等的N个圆弧,然后再间隔开赋予不同的颜色就可以形成图一的效果。
 
  1. const vertex = '\
  2.     varying vec3 vPos;\
  3.     void main() {\
  4.       vPos = position;\
  5.       gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
  6.     }\
  7.   ';
  8.   // 获取UV点对应的单位向量B
  9.   // 获取X轴正方向的单位向量A
  10.   // 计算向量B和向量A的夹角
  11.   // 通过degree将夹角的弧度转换成角度,除以要拆分的条数lonBeta,通过配合fract和step即可获取间隔的0、1值
  12.   // 最后生成间隔的黑白颜色值
  13.   const frag = '\
  14.     uniform float lonBeta;\
  15.     varying vec3 vPos;\
  16.     void main() {\
  17.       vec3 lonEveryVec = normalize(vec3(vPos.x, 0.0, vPos.z));\
  18.       vec3 lonBaseVec = vec3(0.0, 0.0, 1.0);\
  19.       float lonAngle = asin(dot(lonBaseVec, lonEveryVec));\
  20.       vec3 lonColor = vec3(step(0.5, fract(degrees(lonAngle) / lonBeta)));\
  21.       gl_FragColor = vec4(lonColor, 1.0);\
  22.     }\
  23.   ';
复制代码
 
完整代码如下:
  1. const vertex = '\
  2.     varying vec3 vPos;\
  3.     void main() {\
  4.       vPos = position;\
  5.       gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
  6.     }\
  7.   ';
  8.   const frag = '\
  9.     uniform float latBeta;\
  10.     uniform float lonBeta;\
  11.     varying vec3 vPos;\
  12.     void main() {\
  13.       vec3 latEveryVec = normalize(vPos);\
  14.       vec3 latBaseVec = normalize(vec3(vPos.x, 0, vPos.z));\
  15.       float latAngle = asin(dot(latBaseVec, latEveryVec));\
  16.       vec3 latColor = vec3(step(0.5, fract(degrees(latAngle) / latBeta)));\
  17.       \
  18.       vec3 lonEveryVec = normalize(vec3(vPos.x, 0.0, vPos.z));\
  19.       vec3 lonBaseVec = vec3(0.0, 0.0, 1.0);\
  20.       float lonAngle = asin(dot(lonBaseVec, lonEveryVec));\
  21.       vec3 lonColor = vec3(step(0.5, fract(degrees(lonAngle) / lonBeta)));\
  22.       vec3 color = abs(latColor - lonColor);\
  23.       gl_FragColor = vec4(color, 1.0);\
  24.     }\
  25.   ';
复制代码
来源:https://www.cnblogs.com/codeOnMar/p/18233666
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具