天天看点

【Three.js】五、three.js中的材质——Material一、Material二、LineBasicMaterial三、LineDashedMaterial四、MeshBasicMaterial五、MeshDepthMaterial六、MeshLambertMaterial

【Three.js】五、three.js中的材质——Material

  • 一、Material
    • 1.1 Material属性
  • 二、LineBasicMaterial
  • 三、LineDashedMaterial
    • 3.1 LineDashedMaterial属性
  • 四、MeshBasicMaterial
    • 4.1 MeshBasicMaterial属性
  • 五、MeshDepthMaterial
  • 六、MeshLambertMaterial
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();
           
【Three.js】五、three.js中的材质——Material一、Material二、LineBasicMaterial三、LineDashedMaterial四、MeshBasicMaterial五、MeshDepthMaterial六、MeshLambertMaterial

完整示例(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

【Three.js】五、three.js中的材质——Material一、Material二、LineBasicMaterial三、LineDashedMaterial四、MeshBasicMaterial五、MeshDepthMaterial六、MeshLambertMaterial

五、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();
           
【Three.js】五、three.js中的材质——Material一、Material二、LineBasicMaterial三、LineDashedMaterial四、MeshBasicMaterial五、MeshDepthMaterial六、MeshLambertMaterial

完整示例(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();