首页 > 其他分享 >ThreeJS Shader的效果样例网格平面和网格球体(一)

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

时间:2024-07-19 15:19:40浏览次数:16  
标签:ThreeJS 1.0 0.5 样例 网格 fract step vec3 vPos

本文中效果主要采用ThreeJS 中的着色器(Shader)以及结合ShaderMaterial实现的。

主要用到的内置方法有:

step:是一个阶跃函数,它将一个浮点数与一个阈值进行比较,并返回一个阶跃值;    比如step(edge, x), 如果 x 小于等于 edge,则返回 0.0, 如果 x 大于 edge ,则返回 1.0。 fract:用于获取浮点数的小数部分。它返回输入值的小数部分,即去除整数部分后的部分。比如fract(1.5),返回0.5;

一、网格平面

const vertex = '\
    varying vec3 vPos;\
    void main() {\
      vPos = position;\
      gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
    }\
  ';
  const frag = '\
    varying vec3 vPos;\
    void main() {\
      vec3 mask1 = vec3(step(0.5, fract(vPos.x * 2.0)));\
      vec3 mask2 = vec3(step(0.5, fract(vPos.y * 2.0)));\
      vec3 mask3 = vec3(step(0.5, fract(vPos.z * 2.0)));\
      vec3 color = abs(mask1 - mask2);\
      gl_FragColor = vec4(color, 1.0);\
    }\
  ';

 原理:如果设置平面的大小为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个圆弧,然后再间隔开赋予不同的颜色就可以形成图一的效果。

const vertex = '\
    varying vec3 vPos;\
    void main() {\
      vPos = position;\
      gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
    }\
  ';
  // 获取UV点对应的单位向量B
  // 获取Z轴方向的单位向量A
  // 计算向量B和向量A的夹角
  // 通过degree将夹角的弧度转换成角度,除以要拆分的条数latBeta,通过配合fract和step即可获取间隔的0、1值
  // 最后生成间隔的黑白颜色值
  const frag = '\
    uniform float latBeta;\
    varying vec3 vPos;\
    void main() {\
      vec3 latEveryVec = normalize(vPos);\
      vec3 latBaseVec = normalize(vec3(vPos.x, 0, vPos.z));\
      float latAngle = asin(dot(latBaseVec, latEveryVec));\
      vec3 latColor = vec3(step(0.5, fract(degrees(latAngle) / latBeta)));\
      gl_FragColor = vec4(latColor, 1.0);\
    }\
  ';

 

4. 如何实现经度方向的线圈?

    

 实现逻辑:与第三步生成纬度方向的线圈类似,将球体沿球心横向切一刀生成一个圆形横截面M,将圆分成弧度相等的N个圆弧,然后再间隔开赋予不同的颜色就可以形成图一的效果。

 

const vertex = '\
    varying vec3 vPos;\
    void main() {\
      vPos = position;\
      gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
    }\
  ';
  // 获取UV点对应的单位向量B
  // 获取X轴正方向的单位向量A
  // 计算向量B和向量A的夹角
  // 通过degree将夹角的弧度转换成角度,除以要拆分的条数lonBeta,通过配合fract和step即可获取间隔的0、1值
  // 最后生成间隔的黑白颜色值
  const frag = '\
    uniform float lonBeta;\
    varying vec3 vPos;\
    void main() {\
      vec3 lonEveryVec = normalize(vec3(vPos.x, 0.0, vPos.z));\
      vec3 lonBaseVec = vec3(0.0, 0.0, 1.0);\
      float lonAngle = asin(dot(lonBaseVec, lonEveryVec));\
      vec3 lonColor = vec3(step(0.5, fract(degrees(lonAngle) / lonBeta)));\
      gl_FragColor = vec4(lonColor, 1.0);\
    }\
  ';

 

完整代码如下:

const vertex = '\
    varying vec3 vPos;\
    void main() {\
      vPos = position;\
      gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); \
    }\
  ';
  const frag = '\
    uniform float latBeta;\
    uniform float lonBeta;\
    varying vec3 vPos;\
    void main() {\
      vec3 latEveryVec = normalize(vPos);\
      vec3 latBaseVec = normalize(vec3(vPos.x, 0, vPos.z));\
      float latAngle = asin(dot(latBaseVec, latEveryVec));\
      vec3 latColor = vec3(step(0.5, fract(degrees(latAngle) / latBeta)));\
      \
      vec3 lonEveryVec = normalize(vec3(vPos.x, 0.0, vPos.z));\
      vec3 lonBaseVec = vec3(0.0, 0.0, 1.0);\
      float lonAngle = asin(dot(lonBaseVec, lonEveryVec));\
      vec3 lonColor = vec3(step(0.5, fract(degrees(lonAngle) / lonBeta)));\
      vec3 color = abs(latColor - lonColor);\
      gl_FragColor = vec4(color, 1.0);\
    }\
  ';

标签:ThreeJS,1.0,0.5,样例,网格,fract,step,vec3,vPos
From: https://www.cnblogs.com/codeOnMar/p/18233666

相关文章

  • 算法金 | 最难的来了:超参数网格搜索、贝叶斯优化、遗传算法、模型特异化、Hyperopt、O
    ​大侠幸会,在下全网同名「算法金」0基础转AI上岸,多个算法赛Top「日更万日,让更多人享受智能乐趣」今日215/10000抱个拳,送个礼为模型找到最好的超参数是机器学习实践中最困难的部分之一1.超参数调优的基本概念机器学习模型中的参数通常分为两类:模型参数和超......
  • UE Spline 样条网格体组件添加碰撞
    最近做的一个功能是通过Spline生成管道模型。如下图所示:遇到的一个问题是需要给生成的管路加上碰撞。其中需要两个重要的步骤:设置SplineMeshComponent的碰撞预设找到“样条网格体组件”节点,点击节点,出现详情面板,在详情面板中,把碰撞预设从默认的“NoCollision”改成“B......
  • 智能小车开源样例运行
    环境准备前置条件按照官方指导文档完成CANN包安装CANN版本需要>=5.0.4.alpha001(本教程使用5.04alpha005)软件准备源码包:samples:CANNSamples(gitee.com)模型:cplusplus/contrib/Ascbot/README_CN.md·Ascend/samples-Gitee.com建议下载模型,权重和配置文件后本地使......
  • threejs可以做游戏吗
    Three.js非常适合用于开发Web端的3D游戏。‌实际上,‌Three.js已经被广泛用于开发各种类型的游戏,‌包括但不限于塔防游戏、‌RPG游戏等。‌在塔防游戏中,‌Three.js可以用来创建3D的游戏场景、‌角色和道具,‌以及处理游戏逻辑和动画。‌通过使用requestAnimationFrame方法,‌Three.......
  • 求助!!![TJOI2009] 开关样例过不了,如何解决?(语言-c++)
    题目链接:https://www.luogu.com.cn/problem/P9869我的输出:1  12#include<bits/stdc++.h>usingnamespacestd;constintN=100300;intn,m,c,a,b;structnode{intf=0;intsum,l,r;//sum为开灯总数}tr[N<<2];voidup(intk){tr[k].sum+=tr[k......
  • 使用 Vue 和 Plotly.js 创建交互式 3D 网格图
    本文由ScriptEcho平台提供技术支持项目地址:传送门使用Vue和Plotly.js创建交互式3D网格图应用场景介绍3D网格图是一种强大的可视化工具,可用于表示具有三个维度的数据。它们广泛应用于科学、工程和医学等领域,用于显示复杂数据并揭示潜在模式。代码基本功能介绍......
  • threejs画布叠加在cesium画布上不显示
    这个问题可能是由于Three.js和Cesium在渲染顺序或者渲染上下文方面存在冲突导致的。Three.js和Cesium都是用于创建3D或2D地图的库,它们各自管理自己的渲染画布(WebGL上下文)。解决方法: 确保Cesium初始化先于Three.js。Cesium需要完全初始化并且渲染其画布之后,Three.js才能在同......
  • threadLocal详细认识(使用场景与局限性)与样例测试
    Threadlocal的介绍与使用1,是什么?ThreadLocal是Java提供的一个工具类,用于在多线程环境中为每个线程提供独立的变量副本。它是Java标准库中的一部分,提供了线程局部存储的功能,这意味着每个线程都有自己独立的变量副本,这些副本在其他线程中不可见。2,有啥特点?线程隔离:Th......
  • HTML5+CSS3小实例:响应式漫画网格布局
    实例:响应式漫画网格布局技术栈:HTML+CSS效果:源码:【HTML】<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0">......
  • 服务网格新篇章:Eureka与分布式服务网格的协同共舞
    服务网格新篇章:Eureka与分布式服务网格的协同共舞引言在微服务架构的浪潮中,服务网格(ServiceMesh)技术以其微服务间通信的精细化控制而备受瞩目。Eureka作为Netflix开源的服务发现框架,虽然本身不直接提供服务网格功能,但可以与服务网格技术如Istio、Linkerd等无缝集成,实现服......