本段内容会写在0篇以外所有的,本人所编写的Threejs教程中
对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久
如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS
【ThreeJS基础教程-初识Threejs】1.4.1 更好的视觉效果-使用材质与灯光
在这一篇中,我们提到了标准网格材质MeshStandardMaterial(以下均简称为Standard材质) ,但是仅仅只是在MeshBasicMaterial(以下均简称为Basic材质)的基础上,做了受灯光影响的效果,在后面的学习中,我们又粗略的使用了 transparent和opacity为模型添加透明效果和设置透明度,以及用wireframe来让模型变成线框模式,那么,关于纹理我们还能做什么样的操作呢?
查阅Threejs文档后,我们发现,几乎所有的材质,都会继承一个Material的类,这个类为所有材质的超类,所以在查阅相关文档时,不仅要查阅对应的材质的文档,还要查阅超类Material的文档
以下为笔者从文档中提取出的常用和易理解的属性,其余属性将在threejs进阶教程中提及
超类材质的官方文档
属性名 | 默认值 | 官方说明 | 笔者备注 |
---|---|---|---|
alphaTest | 0 | 如果不透明度低于此值则不渲染该材质 | alphaTest常用于处理png贴图的渲染透明错误,特殊情况下也可以用于处理一些透明物体的显示与隐藏,下方演示了aplhaTest的基本用法 |
depthTest | true | 是否在渲染此材质时启用深度测试 | |
depthWrite | true | 渲染此材质是否对深度缓冲区有任何影响 | 这两个属性都设置为false的时候,渲染的图形将无视位置始终被渲染在屏幕最前方,下面演示了禁用深度写入和深度测试的基本用法 |
needsUpdate | false | 指定需要重新编译材质 | 当你的材质发生大的改变时,比如说更换纹理贴图,修改混合属性后,将它设置为true,当渲染一次后,这个值会恢复为false,用于提醒渲染器这个材质发生了改变 |
transparent | false | 定义此材质是否透明 | |
opacity | 1.0 | 材质透明度 | opacity和transparent一般成对出现,transparent设置为false的时候opacity不生效,必须先允许材质透明后,材质才能透明 |
side | THREE.FrontSide | 定义要渲染哪一面,正面背面或两者 | 在之前的BufferGeometry篇里提到,这里渲染的正面,为geometry的面片的面法线方向的面,THREE.Backside为面法线方向的背面,THREE.DoubleSide为双面渲染,下方演示了side的基本用法 |
visible | true | 材质是否可见 | 用于控制部分材质的物体可见与不可见,比如说你的场景用了N个同样材质的物体,你想让这些物体同时消失,一种方法是把这些物体丢进组,然后让组visible = false,另一种方法就是material.visible设置材质不可见 |
如下代码,当设置到alphaTest大于opacity时,本次材质不会被渲染,下列代码不会有任何结果,但是设置alphaTest < opacity时,box将会出现
function addMesh(){
let geometry = new THREE.BoxGeometry(1,1,1);
let material = new THREE.MeshBasicMaterial({
alphaTest:0.5,
opacity:0.4,
transparent:true,
color:0xffffff * Math.random()
});
let mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
}
alphaTest常用于处理透明度错误,比如说部分纹理贴图使用的是png,并且存在部分透明通道,那么我们可以稍微设置一点alphaTest的值来让透明部分不渲染即可
当我们不开启深度测试时,物体的渲染就是正常的谁在前渲染谁
function addMesh(){
let geometry = new THREE.BoxGeometry(1,1,1);
let material = new THREE.MeshBasicMaterial({
color:0xffffff * Math.random(),
// depthTest:false
});
let mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
}
效果,注意看,此时我们的网格辅助线,一部分被方块遮挡,这是正常的谁距离近谁在前方的渲染模式
当设置了禁用深度测试和深度写入后
//在材质中修改depthTest和depthWrite为false即可
let material = new THREE.MeshBasicMaterial({
color:0xffffff * Math.random(),
depthTest:false,
depthWrite:false,
});
关闭这两个属性,用于创建一些始终在最前方的物体,以及对物体设置透视效果
这两个值笔者在使用时,一般是成对出现,两个都设置为false即可
为了让效果更明显,这里我们使用相机灯,来增强Standard材质的渲染效果
如果材质不受光照影响,设置渲染哪一面也没有明显的效果
function init(){
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({
alpha:true,
antialias:true
});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.01,50000);
camera.position.set(10,10,10);
orbitControls = new OrbitControls(camera,renderer.domElement);
let helper = new THREE.GridHelper(50,10);
scene.add(helper);
//添加相机灯
camera.add(new THREE.PointLight());
scene.add(camera);
}
function addMesh(){
let geometry = new THREE.BoxGeometry(1,1,1);
let material = new THREE.MeshStandardMaterial({
color:0xffffff * Math.random(),
side:THREE.BackSide
});
let mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
}
上述代码渲染的效果
当我们转动视角时,发现,原本正对我们的面,现在均变成了透明,而背对我们的面被渲染了出来
FrontSide 就是正常我们使用材质时,看到的效果
BackSide 是我们只能看到模型的背面,一般用于制作案例时用Box快速做一个小房间效果
DoubleSide 是两个面都会渲染,当你把相机拉入到设置了FrontSide的物体中,你会发现物体竟然就消失了,而当你把相机拉入到设置了BackSide的物体中,你会发现你是处于物体内部的,而DoubleSide是综合了两者后的效果
DoubleSide常用于渲染一些单面片但是要两面都显示的物体,比如说简单的树木花草,单面片的玻璃墙面等等
属性名 | 默认值 | 官方说明 | 笔者备注 |
---|---|---|---|
color | 白色0xffffff | 材质的颜色 | 标注是材质颜色,其实是当颜色贴图map为null时渲染的颜色,如果颜色贴图map不为null,则这里的颜色会与颜色贴图map的颜色叠加 |
map | null | 颜色贴图 | 简单说就是最基本的贴图,当你的map不为null时,颜色应设置为白色以防止颜色叠加出现颜色错误问题 |
metalness | 0 | 材质与金属的相似度 | Standard材质的核心之一,基本上好看的效果都要依赖调节这个属性和下方的roughness,下面演示了metalness的基本用法 |
metalnessMap | null | 金属度贴图 | 简单说就是用一张贴图来控制金属度,而不用metalness来控制,此贴图一般由建模师提供 |
roughness | 1.0 | 材质的粗糙程度 | StandardMaterial的核心之一,下面演示了roughness的基本用法 |
roughnessMap | null | 粗糙度贴图 | 简单说就是用一张贴图来控制粗糙度,而不用roughness来控制,此贴图一般由建模师提供 |
wireframe | false | 将几何体渲染为线框 | 简称线框模式,线框模式用于查看模型的点线信息,一般用于检查模型或给模型添加基本的边线,在文档中还有三条关于wireframe的属性,wireframeLinecap,wireframeLineJjoin,wireframeLineWidth,都是在wireframe为true时生效 |
我们是可以在创建material的时候,直接通过写16进制数字或者css颜色代码来修改它的颜色的,但是,后续我们要更改颜色时,则不能这样写
function addMesh(){
let geometry = new THREE.BoxGeometry(1,1,1);
let material = new THREE.MeshStandardMaterial({
color:0xffffff * Math.random()
});
//错误的颜色修改方式
material.color = 0xff0000;
let mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
}
上述写法会导致物体变成一团黑,因为Standrad材质的Color是THREE.Color对象
正确的颜色修改方式
//这里的参数可以为16进制数字,基本css颜色样式
material.color = new THREE.Color(0xff0000);
这里我们以官方案例为例
当roughness为0时,此时材质的反光效果达到最佳
当roughness为0,metalness最高时,物体效果最接近不锈钢金属
细微调节后,颜色为白色,metalness为 0.288,roughness为0时,物体效果最接近陶瓷
开启transparent,透明度设置为0.68,metalness设置为0.593时,此时物体最接近白色玻璃
一般关于材质的属性,我们都是会借助lil.gui或者dat.gui,或者自定义gui来调整,0.1的差距就可能让物体显示效果出现差别,所以这里从来没有固定值
以上的代码极其简单,理解上述两个属性比在代码中使用更为重要
let material = new THREE.MeshStandardMaterial({
color:0xffffff * Math.random(),
roughness:0.5,
metalness:0.5
});
roughness和metalness这两个值基本可以调节出任何我们想要的基本物体效果
同时,standardMaterial还提供了众多可以再提升物体效果的属性,这些属性将在下一篇展开讲解
MeshStandardMaterial进阶