three | 材质 Material

之前讲的都是几何体 Geometry 的相关知识,本文说一说"材质 Material "。

通过之前的代码可以知道,对于一些封装好的模型,three 提供了专门的方法。比如点模型的材质方法:

javascript 复制代码
const material = new THREE.PointsMaterial({
 color: new THREE.Color('orange'),
 size: 10
});

线模型的材质方法:

javascript 复制代码
const material = new THREE.LineBasicMaterial({
 color: new THREE.Color('orange')
});

还有网格模型的材质方法(不受光照影响):

javascript 复制代码
const material = new THREE.MeshBasicMaterial(({
 color: new THREE.Color('orange'),
 wireframe: true,
}));

同一种几何体,加上不同的材质,就可以渲染出不同的效果。

下面我们依旧是学一下 Material 的通用属性:color 颜色、map 颜色贴图 。

javascript 复制代码
import * as THREE from 'three';
const geometry = new THREE.PlaneGeometry(100, 100);
const material = new THREE.MeshBasicMaterial(({
 color: new THREE.Color('orange')
}));
const mesh = new THREE.Mesh(geometry, material);
console.log(mesh);
export default mesh;

这是一个经典的网格模型,设置了color。我们再来看下控制台打印:

mesh 除了 geometry 属性,也有 material 属性。

material.color 是一个 Color 对象,我们可以用各种 get 方法拿到它的颜色值:

javascript 复制代码
console.log(color.getHSL());
console.log(color.getHex());
console.log(color.getRGB());
console.log(color.getHexString());
console.log(color.getStyle());

还可以用各种 set 方法修改颜色值:

javascript 复制代码
color.setStyle('blue');

如果我们希望材质有一定透明度,也可以用 transparent :

javascript 复制代码
constmaterial =newTHREE.MeshBasicMaterial(({
	color:newTHREE.Color('orange'),
	transparent:true,
	opacity:0.5
}));

但也有一些时候,我们不是要设置颜色,而是要设置一张图片。这时候可以用 map 属性:

javascript 复制代码
import * as THREE from 'three';

const loader = new THREE.TextureLoader();
const texture = loader.load('./haha.png');
const geometry = new THREE.SphereGeometry(100);
const material = new THREE.MeshBasicMaterial({
    map: texture
});
const mesh =new THREE.Mesh(geometry, material);

export default mesh;

SphereGeometry 是球体:

如果这时候我们再在 MeshBasicMaterial 中加入:

javascript 复制代码
color:newTHREE.Color('orange'),

设置平面物体 PlaneGeometry 效果也是一样:

javascript 复制代码
import * as THREE from 'three';

const loader = new THREE.TextureLoader();
const texture = loader.load('./haha.png');
texture.wrapS=THREE.RepeatWrapping
texture.wrapT=THREE.RepeatWrapping
texture.repeat.set(3,3);
const geometry = new THREE.PlaneGeometry(1000, 1000);
const material = new THREE.MeshBasicMaterial({
    map: texture
});
const mesh =new THREE.Mesh(geometry, material);

export default mesh;

不过在设置平面物体时一定要考虑一点:相机视角!

如果你在调用上面这个代码后相机那里还按之前的这么写:

javascript 复制代码
const camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);

根据上上一片文章中说到的"近截面远截面"的知识,你得到的大概率是一个很有倾斜角度、展示不完全的图片,但是如果我们让物体远一点:

javascript 复制代码
const camera = new THREE.PerspectiveCamera(60, width / height, 1, 10000);

这样就不会被裁剪了。所以你经常看到代码里近裁截面设置了 0.1,远裁截面设置了好几万,就是为了让视椎体的范围能覆盖全部场景。

我们还可以修改相机的位置达到效果:

javascript 复制代码
camera.position.set(90, 200, 1000);

那如果我们想让图片在水平/垂直方向重复呢?直接设置在水平(wrapS)和竖直(wrapT)方向重复,然后设置重复次数就可以了:

javascript 复制代码
const texture = loader.load('./haha.png');
texture.wrapS=THREE.RepeatWrapping
texture.wrapT=THREE.RepeatWrapping
texture.repeat.set(3,3);

写到这我发现一件事,这贴图怎么这么泛白,原图是有很深的颜色的。于是我找到了这个方法:

javascript 复制代码
texture.colorSpace=THREE.SRGBColorSpace;

修改图片对象的颜色空间。

但是直到这里,图片依然"失真",这里说的不是图片本身和原图的真假,而是和现实的真假。因为我们是有"光照"的,如果是模型线条本身也是可以的,但这里是贴图, map 只是把贴图的颜色加上去了,没有做进一步的处理,如果你想要那种受环境光影响的凹凸感,需要设置 aoMap 属性:

javascript 复制代码
const material = new THREE.MeshBasicMaterial({
    map: texture,
    aoMap: texture   // 重点!!!
});
相关推荐
zuoerjinshu2 小时前
WebSpoon9.0(KETTLE的WEB版本)编译 + tomcatdocker部署 + 远程调试教程
前端
lxmyzzs2 小时前
解决Windows安装OpenClaw报错:无法加载npm.ps1,禁止运行脚本
前端·windows·npm·openclaw
昨日余光2 小时前
建议收藏!我开发了一个免费无限制的AI绘画公益站!
开发语言·前端·javascript·ai作画·typescript
意疏2 小时前
openJiuwen实战:用AsyncCallbackFramework为Agent增强器添加可观测性
java·服务器·前端
llxxyy卢2 小时前
polar中等web部分题目
前端
wuhen_n2 小时前
5年前端,我为什么要all in AI Agent?
前端·vue.js·ai编程
我爱切图2 小时前
echart 移动端进行双指缩放时,当放大到最大级别后,手指没有离开屏幕,图表还会自动移动问题修复
前端
optimistic_chen2 小时前
【Vue入门】创建Vue工程环境和响应式函数
前端·javascript·vue.js·前端框架·html
南城书生2 小时前
Android Handler 机制源码分析
前端