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   // 重点!!!
});
相关推荐
前端之虎陈随易5 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·vue.js·人工智能·typescript·node.js
一路向北he5 小时前
字节钢铁军团--“提供情境,而非控制”
java·开发语言·前端
kyriewen6 小时前
豆包和千问同时关了智能体,我用它们搭的 3 个自动化全废了——迁移方案整理
前端·javascript·ai编程
前端一小卒6 小时前
我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行
前端·agent
铁皮饭盒6 小时前
用 Bun.cron 定时 7 月 7 日,为啥? 看图1
javascript
大圣编程8 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang8 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆8 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜9 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞10 小时前
异步HttpModule的实现方式
java·服务器·前端