开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
最近回看了下之前的文章,感觉可能讲的比较粗糙。很多细节方面,被忽略了。于是乎,今天我就来说下threejs使用着色器材质的细节;
着色器材质有哪些?
首先,我们看文档可以知道,着色器材质,一共有两个:ShaderMaterial和RawShaderMaterial。
ShaderMaterial
我一般是使用这个材质来自定义shader渲染材质,顺便介绍下,shader是glsl编写的在gpu上运行的小程序。每个管线都会并发执行,且管线之间不具有互通性。每一个线程之前都是独立的,盲视的。并且,gpu的管道一直都处理数据,一个线程不可能知道它上一刻在做什么。它是无记忆的。因此,也导致glsl是出了名的难学。有兴趣可以挑战下。语法类似c++,数学也要求一定基础。
代码示例:
` const material = new THREE.ShaderMaterial( {
uniforms: { time: { value: 1.0 },
resolution: { value: new THREE.Vector2() } },
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );`
RawShaderMaterial
至于这个类,其实和ShaderMaterial没啥太大区别,只是内置的uniforms和attributes的定义不会自动添加到glsl中。使用起来比较繁琐,所以,我一般也不用这个。shaderMaterial基本上是够用了。这个类也不是非用不可。
着色器实战案例
定义就这些,说了再多,也不如实际运用。
通常,我们通过uniforms传入一些固定的参数,着色器通过每个点的位置不同来展示各种不同的颜色。比如,我们可以传入一个贴图,每个管线根据uv坐标可以取到当前的位置的在贴图对应位置的颜色。也可以取到周围的颜色。如果我们做一个卷积的操作,也就实现了对图片模糊的操作。实现将贴图打上马赛克的效果。是不是很棒?
回归主题,由于我们是基础篇,我们先实现一个在3d场景显示纯色的效果。 因为3d的场景下,有光影关系的影响,所以我们一般材质展示的颜色,和我们设置的颜色都不一致。会混合其他颜色。如果遇到一定要色值一样的情况,就可以用着色器材质。毕竟前端最重要的是所见即所得(好像不太对)。
我们只要将颜色作为uniforms传给shaderMaterial。剩下的就交给glsl就行了。
glsl部分也是简单的把color给展示出来即可( gl_FragColor = vec4(color,1.0))
代码如下:
let material = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0x00d5ff) },
},
//顶点着色器
vertexShader: void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); },
//片元着色器
fragmentShader: uniform vec3 color; void main() { gl_FragColor = vec4(color,1.0); },
});