**
Material(+纹理)
**
三维物体的材质,以Material结尾。
1.不真实:MeshBasicMaterial 最最最基本的材质,不参与光照计算unlit,没有阴影。
2.真实效果:MeshPhongMaterial/MeshLambertMaterial 他俩实现图形学中最最基本的光照模型。
3.更好更真实的效果:MeshStardardMaterial/MeshPhysicMaterial 他俩计算量更大,但是会让你的场景足够逼真。
4.动画效果:MeshToonMaterial 实现卡通的效果
map基本纹理贴图+roughmessMap粗糙+normalMap法线贴图+displacementMap高度贴图+aoMap环境光遮罩
1.map:给物体表面贴上基本纹理
2.roughmessMap设定表面不同位置的粗糙程度
3.normalMap 法线贴图,会影响光照的计算,用它来模拟表面凹凸不平的效果
4.diaplacementMap 位移贴图(高度贴图)上下偏移表面顶点坐标,做到真正的物体表面的起伏
5.aoMap(AmbientOcclusion)指定一个“环境光遮罩”贴图,让遮罩的地方变得更暗,从而再进一步提升场景的真实感
https://zhuanlan.zhihu.com/p/145890220
如何实际使用shader。由于threejs已经帮我们完成了很多基础的框架操作,我们只需要把精力专注在shader程序本身就好。
shader的三个写法
shader存放的位置,我们可以将shader写成单独的文件,或者在js代码中使用字符串的形式,或者使用html页面中《script id=“vertexShader” type=“x-shader/x-vertex”>、《script id=“fragmentShader” type=“x-shader/x-fragment”>等标签形式进行shader代码的编写。
1.在html的页面中加入以上两个shader的script标签。
<script id="vertexShader" type="x-shader/x-vertex">
precision mediump float;
precision mediump int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
varying vec3 vPosition;
void main() {
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision mediump float;
precision mediump int;
uniform float ratio;
varying vec3 vPosition;
void main() {
vec3 center = vec3( 0.0,0.0,0.0 );
float dist= distance(vPosition,center)/100.0;
dist = clamp(dist,0.0,1.0);
float color = 1.0-dist ;
gl_FragColor = vec4( color*ratio, color*ratio,0.0,dist );
}
</script>
2.在我们的js代码中使用threejs的RawShaderMaterial来创建一个shader材质。并将html标签中的内容获取赋值给vertexShader,fragmentShader。同时,我们创建了一个uniform 名叫ratio。
const material = new THREE.RawShaderMaterial({
uniforms: {
ratio: {
value: 0.0
}
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent,
});
3.我们把这个材质放在一个平面上,并在主循环中更新uniform的值
const plane = new THREE.Mesh(geometry, material);
plane.rotateX(-Math.PI / 2);
scene.add(plane);
let next = 0;
const animate = function () {
requestAnimationFrame(animate);
next = next + 0.01;
if (next > 1)
next = 0;
plane.material.uniforms.ratio.value = next;
renderer.render(scene, camera);
};
案例2
var sphereGeometry = new SphereBufferGeometry(5, 12, 12);
var material = new THREE.MeshPhongMaterial();
var sphereMesh = new THREE.Mesh(sphereGeometry, material)
scene.add(sphereMesh);
var shaderMaterial = new THREE.ShaderMaterial(
{
vertexShader: `
varying float y;
void main() {
// GLSL的矩阵算法 从右到左
y = position.y;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`,
fragmentShader: `
varying float y;
void main() {
//最终赋给gl_FragColor是一个颜色色变量 r,g,b,alpha
//浮点数数字必须写成2.0 3.0 比如我们有一个float变量5必须写成5.0
if(y>0.0)
gl_FragColor = vec4( 0.0, 1.0, 0.0, 0.5);
else
gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5);
}
`,
transparent: true,
// side: THREE.DoubleSide
}
)
debugger
var sphereGeometry = new SphereBufferGeometry(5, 12, 12);
var sphereMesh = new THREE.Mesh(sphereGeometry, shaderMaterial)
scene.add(sphereMesh);