Three.js 自定义着色器程序 ShaderMaterial

发布于 2021-11-18 13:07:55 字数 4006 浏览 1461 评论 0

自定义 three.js 着色器程序需要用到着色器语言 GLSL ES 和相关的 WebGL API,因此在学习本节课之前最好具有一定 WebGL 基础。

着色器程序至少包含顶点着色器程序和片元着色器程序,对于原生WebGL应用而言,使用着色器语言GLSL编写好顶点、片元着色器程序后,需要借助 WebGL 相关 API 进行编译处理后发送到GPU渲染管线的顶点、片元着色器单元执行,three.js引擎提供了一个接口着色器材质对象 ShaderMaterial,通过 ShaderMaterial 对象的属性 vertexShader和 fragmentShader 用来接收着色器程序,着色器程序如何编译、如何传递给GPU的处理单元,这些过程已经被 three.js 引擎封装,three.js 通过 ShaderMaterial 对象接收到着色器程序后会自动化为处理,说到这里大家可以看出three.js引擎的好处与作用,对WebGL API和着色器语言进行封装,一方面是降低 Web3D 的学习成本,另一方面是对原生的WebGL程序进行封装,工程师更多的精力放在应用开发上。

下面的代码完整的展示了如何利用 ShaderMaterial 对象加载着色器程序,如何把顶点相关的数据传输到顶点着色器程序中。

<body>
<!--顶点着色器程序-->
<script type="x-shader/x-vertex" id="vertexshader">
void main() {
  gl_PointSize = 20.0;
  gl_Position = vec4( position, 1.0 );
}
</script>
<!--片元着色器程序-->
<script type="x-shader/x-fragment" id="fragmentshader">
void main() {
  gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
</script>
<script>
...
...
/**
 * 创建模型对象
 */
//类型数组创建顶点数据
var vertices = new Float32Array([
  0.5,  0.5,  0.5,//顶点0
  -0.5,  0.5,  0.5,//顶点1
  -0.5, -0.5,  0.5,//顶点2
  0.5, -0.5,  0.5,//顶点3
]);
//类型数组格式顶点数据转为BufferAttribute对象
var verticesPosition = new THREE.BufferAttribute( vertices, 3 );
var geometry = new THREE.BufferGeometry();//缓冲几何对象
//顶点数据关联着色器程序
geometry.addAttribute('position',verticesPosition);
var material=new THREE.ShaderMaterial({
  //加载顶点着色器程序
  vertexShader:   document.getElementById( 'vertexshader' ).textContent,
  //加载片元着色器程序
  fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
});//着色器材质对象
var points=new THREE.Points(geometry,material);//模型对象
scene.add(points);//模型添加到场景中

...
...
</script>
</body>

加载着色器程序

ShaderMaterial 对象的基类是材质对象 MAterial,ShaderMaterial 对象除了具有材质对象的属性和方法以外,与其它材质对象不同的是 ShaderMaterial 对象还具有处理着色器程序的相关属性或方法,或者换句话说其它的各种材质对象对着色器程序进行了封装,three.js 引擎会把材质对象的颜色属性、纹理贴图属性转化为着色器程序中的代码。

vertexShader、fragmentShader 是着色器材质对象 ShaderMaterial 属性,属性值是字符串格式着色器程序,着色器程序可以编写在任何 html 标签中,通过 getElementById 获取标签表示的元素对象,textContent 属性返回的是标签里面的着色器程序,数据类型是字符串。下面代码是以构造函数 THREE.ShaderMaterial 参数的形式把顶点和片元着色器程序分别赋值给vertexShader属性、 fragmentShader 属性。

    var material=new THREE.ShaderMaterial({
    //加载顶点着色器程序
    vertexShader:   document.getElementById( 'vertexshader' ).textContent,
    //加载片元着色器程序
    fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
});//着色器材质对象

传入着色器顶点相关数据

所谓的三维模型效果本质上都是通过顶点数据渲染出来,通过原生 WebGL 编写三维应用,需要在着色器通过 attribute 等关键字声明一个变量,然后通过 JavaScript 可以控制的 WebGL API 把顶点数据传递给着色器,关联到该变量。three.js 对这些代码进行了封装,对于工程师来说更加友好易用。

BufferGeometry

缓冲几何体对象 BufferGeometry 和几何体对象 Geometry 功能基本相似,都可使用来创建几何体,只是处理数据的方式有些差异。

比如 Geometry 对象具有顶点位置属性 vertices、顶点颜色属性 colors,而 BufferGeometry 对象不具有这些属性,BufferGeometry 对象的顶点位置、颜色等数据需要通过方法 .addAttribute() 添加。

BufferAttribute

通过类型数组构造函数 Float32Array 创建一系列的顶点数据,这些数据可以作为顶点位置、颜色、法向量顶数据,代码中是作为位置使用,THREE.BufferAttribute(vertices, 3) 的含义表示类型数组的元素三个是一组,表示一个顶点的位置,相当于 Vector3 向量。

对象 BufferAttribute 可以作为 BufferGeometry 对象 addAttribute 方法的参数,实现顶点位置数据与顶点着色器程序中的位置变量块关联。

addAttribute

geometry.addAttribute('position',verticesPosition); 代码的作用相当于在顶点着色器中创建代码 attribute vec4 position,然后把包含顶点数据的 BufferAttribute 对象与着色器程序中的 position 变量进行关联。直接使用 WebGL API 编写程序,需要在着色器程序中编写代码 attribute vec4 position,有了 three.js 引擎自然不要,在执行方法 .addAttribute('position') 的时候,就相当于在着色器程序中添加了该语句。

//类型数组创建顶点数据
var vertices = new Float32Array([
    0.5,  0.5,  0.5,//顶点0
    -0.5,  0.5,  0.5,//顶点1
    -0.5, -0.5,  0.5,//顶点2
    0.5, -0.5,  0.5,//顶点3
]);
//类型数组格式顶点数据转为BufferAttribute对象
var verticesPosition = new THREE.BufferAttribute( vertices, 3 );
var geometry = new THREE.BufferGeometry();//缓冲几何对象
//顶点数据关联着色器程序
geometry.addAttribute('position',verticesPosition);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

想挽留

暂无简介

0 文章
0 评论
20372 人气
更多

推荐作者

醉城メ夜风

文章 0 评论 0

远昼

文章 0 评论 0

平生欢

文章 0 评论 0

微凉

文章 0 评论 0

Honwey

文章 0 评论 0

qq_ikhFfg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文