【Three.js】五、three.js中的材质——Material
three.js中的材质就是几何体表面的材料。所有材质均继承自Material。
一、Material
材质基类,Material拥有的属性,其子类均可使用。
1.1 Material属性
属性 | 说明 |
---|---|
color | 材质颜色 |
transparent | 定义此材质是否透明,该值设为true才可以使用透明 |
alphaTest | 不透明度低于此值,则不会渲染材质。默认值为0。 |
opacity | 透明度 |
side | 材质被应用与哪一面,正面(TREE.FrontSide)or反面(THREE.BackSide)or两面(DoubleSide) |
depthTest | 是否在渲染此材质时启用深度测试。默认为 true。 |
depthWrite | 渲染此材质是否对深度缓冲区有任何影响。默认为true。 |
fog | 材质是否受雾的影响 |
vertexColors | 是否使用顶点着色。默认值为THREE.NoColors。 其他选项有THREE.VertexColors 和 THREE.FaceColors。 |
以上属性可在MeshBasicMaterial中的示例中看到展示效果
二、LineBasicMaterial
一种用于绘制线框样式几何体的材质。
LineBasicMaterial相关属性(color/light除外)只能使用CanvasRenderer渲染器渲染时才有效。CanvasRenderer在r98版本之后已被移除。
import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {initStats, initTrackballControls} from "../../util/util";
function init(){
let stats = initStats();
let scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
let camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,10000);
let renderer = new THREE.WebGLRenderer({antialias: true});
camera.position.set(-30, 60,70);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio( window.devicePixelRatio );
scene.add(camera);
document.body.appendChild(renderer.domElement);
// 创建曲线
let curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -10, 0, 10 ),
new THREE.Vector3( -5, 5, 5 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 5, -5, 5 ),
new THREE.Vector3( 10, 0, 10 )
],true);
let points = curve.getPoints(500);
let lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
let lineMaterial = new THREE.LineBasicMaterial( {
color: 0xff0000
} );
let line = new THREE.Line(lineGeometry, lineMaterial);
line.position.set(0,0,0);
scene.add(line);
camera.lookAt(scene.position);
let trackballControl = initTrackballControls(camera, renderer);
function render(){
stats.update();
trackballControl.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
init();
完整示例(src/pages/three_LineBasicMaterial_demo):https://github.com/MAXLZ1/threejs_demo
三、LineDashedMaterial
一种用于绘制虚线线框样式几何体的材质。
3.1 LineDashedMaterial属性
属性 | 说明 |
---|---|
color | 线条颜色 |
dashSize | 虚线的大小,是指破折号和间隙之和。默认值为 3 |
gapSize | 间隙的大小,默认值为 1 |
scale | 线条中虚线部分的占比。默认值为 1 |
示例:
import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {initStats, initTrackballControls} from "../../util/util";
function init(){
let stats = initStats();
let scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
let camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,10000);
let renderer = new THREE.WebGLRenderer({antialias: true});
camera.position.set(-30, 60,70);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio( window.devicePixelRatio );
scene.add(camera);
document.body.appendChild(renderer.domElement);
// 创建曲线
let curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -10, 0, 10 ),
new THREE.Vector3( -5, 5, 5 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 5, -5, 5 ),
new THREE.Vector3( 10, 0, 10 )
],true);
let points = curve.getPoints(500);
let lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
let lineMaterial = new THREE.LineDashedMaterial( {
color: 0xff0000,
dashSize: 1,
gapSize: 0.5,
scale: 1
} );
let line = new THREE.Line(lineGeometry, lineMaterial);
line.computeLineDistances();
line.position.set(0,0,0);
scene.add(line);
camera.lookAt(scene.position);
let gui = new dat.GUI();
let controls = {
color: lineMaterial.color.getStyle(),
dashSize: lineMaterial.dashSize,
gapSize: lineMaterial.gapSize,
scale: lineMaterial.scale
};
gui.addColor(controls, 'color').onChange(value => lineMaterial.color.setStyle(value));
gui.add(controls, 'dashSize', 0, 10).onChange(value => lineMaterial.dashSize = value);
gui.add(controls, 'gapSize', 0, 10).onChange(value => lineMaterial.gapSize = value);
gui.add(controls, 'scale', 0, 10).onChange(value => lineMaterial.scale = value);
let trackballControl = initTrackballControls(camera, renderer);
function render(){
stats.update();
trackballControl.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
init();
完整示例(src/pages/three_LineDashedMaterial_demo):https://github.com/MAXLZ1/threejs_demo
四、MeshBasicMaterial
一个以简单着色(平面或线框)方式来绘制几何体的材质。这种材质不受光照的影响。
4.1 MeshBasicMaterial属性
属性 | 说明 |
---|---|
wireframe | 将几何体渲染为线框。默认值为false(即渲染为平面多边形) |
map | 颜色贴图 |
envMap | 环境贴图 |
reflectivity | 环境贴图对表面的影响程度,默认值为1,有效范围介于0(无反射)和1(完全反射)之间 |
refractionRatio | 空气的折射率(约为1)除以材质的折射率,默认0.98,不能超过1 |
import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import brickImage from '../../assets/images/brick_roughness.jpg'
import nx from '../../assets/images/nx.jpg';
import ny from '../../assets/images/ny.jpg';
import nz from '../../assets/images/nz.jpg';
import px from '../../assets/images/px.jpg';
import py from '../../assets/images/py.jpg';
import pz from '../../assets/images/pz.jpg';
import {initStats, initTrackballControls, initThree} from "../../util/util";
import {
BackSide,
CubeRefractionMapping,
DoubleSide,
FrontSide,
RepeatWrapping, RGBFormat,
TextureLoader
} from "../../libs/three.module";
function init(){
let stats = initStats();
let {camera, scene, renderer} = initThree({
sceneOption:{
color: 0x444444
}
});
let ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
let fog = new THREE.Fog(0xff0000, 0, 200);
scene.fog = fog;
// 创建环形管道
let torusGeometry = new THREE.TorusKnotGeometry(10, 3, 100, 16);
let torusMaterial = new THREE.MeshBasicMaterial({
color: 0xffff00,
skinning: true
});
let torus = new THREE.Mesh(torusGeometry, torusMaterial);
scene.add(torus);
// 创建贴图加载器
let textureLoader = new THREE.TextureLoader();
let cubeTextureLoader = new THREE.CubeTextureLoader();
let maps = (function(){
// 创建贴图
let bricks = textureLoader.load(brickImage);
bricks.wrapS = RepeatWrapping;
bricks.wrapT = RepeatWrapping;
bricks.repeat.set(9,1);
return {
none: null,
bricks
}
})();
let envMaps = (function(){
let urls = [px, nx, py, ny, pz, nz];
let reflection = cubeTextureLoader.load(urls);
reflection.format = RGBFormat;
let refraction = cubeTextureLoader.load(urls);
refraction.format = RGBFormat;
refraction.mapping = CubeRefractionMapping;
return {
none: null,
reflection,
refraction
}
})();
let gui = new dat.GUI();
let controls = {
color: torusMaterial.color.getStyle(),
alphaTest: torusMaterial.alphaTest,
transparent: torusMaterial.transparent,
opacity: torusMaterial.opacity,
side: torusMaterial.side,
depthTest:torusMaterial.depthTest,
depthWrite: torusMaterial.depthWrite,
fog: torusMaterial.fog,
vertexColors: torusMaterial.vertexColors,
wireframe: torusMaterial.wireframe,
envMap: Object.keys(envMaps)[0],
map: Object.keys(maps)[0],
reflectivity: torusMaterial.reflectivity,
refractionRatio: torusMaterial.refractionRatio
};
let fogControls = {
fog: scene.fog != null,
color: fog.color.getStyle()
};
let fogGui = gui.addFolder('THREE.Fog');
let basicGui = gui.addFolder('Material');
let selfGui = gui.addFolder('MeshBasicMaterial');
let contains = {
side: {
'THREE.FrontSide': THREE.FrontSide,
'THREE.BackSide': THREE.BackSide,
'THREE.DoubleSide': THREE.DoubleSide
},
vertexColors: {
'THREE.NoColors':THREE.NoColors,
'THREE.VertexColors': THREE.VertexColors,
'THREE.FaceColors': THREE.FaceColors
}
};
fogGui.add(fogControls, 'fog').onChange(value => value ? scene.fog = fog : scene.fog = null);
fogGui.addColor(fogControls, 'color').onChange(value => fog.color.setStyle(value));
basicGui.addColor(controls, 'color').onChange(value => torusMaterial.color.setStyle(value));
basicGui.add(controls, 'transparent').onChange(value => torusMaterial.transparent = value);
basicGui.add(controls, 'alphaTest', 0, 1).onChange(value => torusMaterial.alphaTest = value);
basicGui.add(controls, 'opacity', 0, 1).onChange(value => torusMaterial.opacity = value);
basicGui.add(controls, 'fog').onChange(value => {
torusMaterial.fog = value;
torusMaterial.needsUpdate = true;
});
basicGui.add(controls, 'side', contains.side).onChange(value => {
// 这里必须parseInt?
torusMaterial.side = parseInt(value);
torusMaterial.needsUpdate = true;
});
basicGui.add(controls, 'depthTest').onChange(value => torusMaterial.depthTest = value);
basicGui.add(controls, 'depthWrite').onChange(value => torusMaterial.depthWrite = value);
basicGui.add(controls, 'vertexColors',contains.vertexColors).onChange(value => {
torusMaterial.vertexColors = parseInt(value);
torusMaterial.needsUpdate = true;
});
selfGui.add(controls, 'wireframe').onChange(value => torusMaterial.wireframe = value);
selfGui.add(controls, 'map', Object.keys(maps)).onChange(value =>{
torusMaterial.map = maps[value];
torusMaterial.needsUpdate = true;
});
selfGui.add(controls, 'envMap', Object.keys(envMaps)).onChange(value => {
torusMaterial.envMap = envMaps[value];
torusMaterial.needsUpdate = true;
});
selfGui.add(controls, 'reflectivity', 0, 1).onChange(value => torusMaterial.reflectivity = value);
selfGui.add(controls, 'refractionRatio', 0, 1).onChange(value => torusMaterial.refractionRatio = value);
let trackballControls = initTrackballControls(camera, renderer);
render();
function render(){
stats.update();
trackballControls.update();
torus.rotation.x += 0.005;
torus.rotation.y += 0.005;
torus.rotation.z += 0.005;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
}
init();
完整示例(src/pages/three_MeshBasicMaterial_demo):https://github.com/MAXLZ1/threejs_demo
五、MeshDepthMaterial
一种按深度绘制几何体的材质。深度基于相机远近平面。白色最近,黑色最远。
import '../../stylus/index.styl'
import {initStats,initThree,initTrackballControls} from "../../util/util";
import * as THREE from 'three'
import * as dat from 'dat.gui'
function init(){
let {camera, scene, renderer} = initThree({
sceneOption:{
color: 0x444444
}
});
camera.near = 15;
camera.updateProjectionMatrix();
let stats = initStats();
let torusGeometry = new THREE.TorusKnotGeometry(10,3, 100, 16);
let torusMaterial = new THREE.MeshDepthMaterial();
let torus = new THREE.Mesh(torusGeometry, torusMaterial);
scene.add(torus);
let gui = new dat.GUI();
let controls = {
near: camera.near,
far: camera.far
};
let cameragui = gui.addFolder('camera');
cameragui.add(controls,'near', 0, 50).onChange(value => {
camera.near = value;
camera.updateProjectionMatrix()
});
cameragui.add(controls, 'far', 0, 1000).onChange(value => {
camera.far = value;
camera.updateProjectionMatrix();
});
let trackballControls = initTrackballControls(camera, renderer);
render();
function render(){
stats.update();
trackballControls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
}
init();
完整示例(src/pages/three_MeshDepthMaterial_demo):https://github.com/MAXLZ1/threejs_demo
六、MeshLambertMaterial
一种非光泽表面的材质,没有镜面高光。
该材质使用基于非物理的Lambertian模型来计算反射率。 这可以很好地模拟一些表面(例如未经处理的木材或石材),但不能模拟具有镜面高光的光泽表面(例如涂漆木材)
import '../../stylus/index.styl'
import {initStats,initThree,initTrackballControls} from "../../util/util";
import * as THREE from 'three'
import * as dat from 'dat.gui'
function init(){
let {camera, scene, renderer} = initThree({
sceneOption:{
color: 0x444444
}
});
camera.near = 15;
camera.updateProjectionMatrix();
let stats = initStats();
let spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-70, 60, 0);
scene.add(spotLight);
let torusGeometry = new THREE.TorusKnotGeometry(10,3, 100, 16);
let torusMaterial = new THREE.MeshLambertMaterial({
color: 0x0000ff
});
let torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.castShadow = true;
scene.add(torus);
let gui = new dat.GUI();
let controls = {
near: camera.near,
far: camera.far
};
let cameragui = gui.addFolder('camera');
cameragui.add(controls,'near', 0, 50).onChange(value => {
camera.near = value;
camera.updateProjectionMatrix()
});
cameragui.add(controls, 'far', 0, 1000).onChange(value => {
camera.far = value;
camera.updateProjectionMatrix();
});
let trackballControls = initTrackballControls(camera, renderer);
render();
function render(){
stats.update();
trackballControls.update();
torus.rotation.x += 0.01;
torus.rotation.y += 0.01;
torus.rotation.z += 0.01;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
}
init();