• Three.js——基础材质、深度材质、法向材质、面材质、朗伯材质、Phong材质、着色器材质、直线和虚线、联合材质


    个人简介

    👀个人主页: 前端杂货铺
    🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
    📃个人状态: 研发工程师,现效力于中国工业软件事业
    🚀人生格言: 积跬步至千里,积小流成江海
    🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程

    🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

    前言

    大家好,这里是前端杂货铺。

    上篇文章我们学习了 聚光灯、环境光、点光源、平行光、半球光。接下来,我们继续我们 three.js 的学习!

    在学习的过程中,如若需要深入了解或扩展某些知识,可以自行查阅 => three.js官方文档。


    老规矩,我们先把本篇文章需要使用的 ./controls/index.js 补充完毕

    const basicType = {
        // 颜色。默认为一个白色(0xffffff)的 Color 对象。
        color: {
            method: 'addColor',
            getValue: item => item.color.getStyle(),
            setValue: (item, value) => item.color.setStyle(value),
        },
        // 
        skyColor: {
            method: 'addColor',
            getValue: item => item.skyColor.getStyle(),
            setValue: (item, value) => item.skyColor.setStyle(value),
        },
        // 光照强度。默认值为 1
        intensity: {
            method: 'add',
            extends: [0, 2],
            getValue: item => item.intensity,
            setValue: (item, value) => item.intensity = +value,
        },
        // 光源照射的最大距离。默认值为 0(无限远)
        distance: {
            method: 'add',
            extends: [0, 1],
            getValue: item => item.distance,
            setValue: (item, value) => item.distance = +value,
        },
        // 光线照射范围的角度。默认值为 Math.PI/3
        angle: {
            method: 'add',
            extends: [0, Math.PI / 2],
            getValue: item => item.angle,
            setValue: (item, value) => item.angle = +value,
        },
        // 决定了光线强度递减的速度。
        exponent: {
            method: 'add',
            extends: [0, 20],
            getValue: item => item.exponent,
            setValue: (item, value) => item.exponent = +value,
        },
        // 亮度
        opacity: {
            extends: [0, 1],
            getValue: item => item.opacity,
            setValue: (item, value) => item.opacity = +value
        },
        // 透明度
        transparent: {
            getValue: item => item.transparent,
            setValue: (item, value) => item.transparent = value
        },
        // 线框
        wireframe: {
            getValue: item => item.wireframe,
            setValue: (item, value) => item.wireframe = value
        },
        // 显隐
        visible: {
            getValue: item => item.visible,
            setValue: (item, value) => item.visible = value
        },
        cameraNear: {
            extends: [0, 50],
            getValue: (item, camera) => camera.near,
            setValue: (item, value, camera) => camera.near = value
        },
        cameraFar: {
            extends: [50, 200],
            getValue: (item, camera) => camera.far,
            setValue: (item, value, camera) => camera.far = value
        },
        side: {
            extends: [['font', 'back', 'double']],
            getValue: (item, camera) => 'font',
            setValue: (item, value) => {
                switch(value) {
                    case 'font':
                        item.side = THREE.FrontSide;
                        break;
                    case 'back':
                        item.side = THREE.BackSide;
                        break; 
                    case 'double':
                        item.side = THREE.DoubleSide;
                        break;
                }
            }
        },
        // 材料的环境颜色
        ambient: {
            method: 'addColor',
            getValue: (item) => item.ambient.getHex(),
            setValue: (item, value) => item.ambient = new THREE.Color(value),
        },
        // 物体材料本身发出的颜色
        emissive: {
            method: 'addColor',
            getValue: (item) => item.emissive.getHex(),
            setValue: (item, value) => item.emissive = new THREE.Color(value),
        },
        // 设置高亮部分的颜色
        specular: {
            method: 'addColor',
            getValue: (item) => item.specular.getHex(),
            setValue: (item, value) => item.specular = new THREE.Color(value),
        },
        // 设置高亮部分的亮度
        shininess: {
            extends: [0, 100],
            getValue: (item) => item.shininess,
            setValue: (item, value) => item.shininess = value,
        },
        red: {
            extends: [0, 1],
            getValue: (item) => item.uniforms.r.value,
            setValue: (item, value) => item.uniforms.r.value = value,
        },
        alpha: {
            extends: [0, 1],
            getValue: (item) => item.uniforms.a.value,
            setValue: (item, value) => item.uniforms.a.value = value,
        },
        dashSize: {
            extends: [0, 5],
            getValue: (item) => item.dashSize,
            setValue: (item, value) => item.dashSize = +value,
        },
        gapSize: {
            extends: [0, 5],
            getValue: (item) => item.gapSize,
            setValue: (item, value) => item.gapSize = +value,
        }
    }
    
    const itemType = {
        SpotLight: ['color', 'intensity', 'distance', 'angle', 'exponent'], // 聚光灯
        AmbientLight: ['color'], // 环境光
        PointLight: ['color', 'intensity', 'distance'], // 点光源
        DirectionalLight: ['color', 'intensity'], // 平行光
        HemisphereLight: ['groundColor', 'intensity'], // 半球光
        MeshBasicMaterial: ['color', 'opacity', 'transparent', 'wireframe', 'visible'], // 基础网格材质
        MeshDepthMaterial: ['wireframe', 'cameraNear', 'cameraFar'], // 深度网格材质
        MeshNormalMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side'],
        MeshLambertMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side', 'ambient', 'emissive', 'color'], // 朗伯材质
        MeshPhongMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side', 'ambient', 'emissive', 'color', 'specular', 'shininess'], // Phong材质
        ShaderMaterial: ['red', 'alpha'], // 着色器材质
        LineBasicMaterial: ['color'], // 直线
        LineDashedMaterial: ['dashSize', 'gapSize'], // 虚线
    }
    
    function initControls(item, camera) {
        console.log('item', item)
        const typeList = itemType[item.type];
        const controls = {};
    
        if (!typeList || !typeList.length) {
            return;
        }
    
        const gui = new dat.GUI();
    
        for (let i = 0; i < typeList.length; i++) {
            const child = basicType[typeList[i]];
            if (child) {
                controls[typeList[i]] = child.getValue(item, camera);
    
                const childExtends = child.extends || [];
    
                gui[child.method || 'add'](controls, typeList[i], ...childExtends).onChange((value) => {
                    child.setValue(item, value, camera);
                })
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175

    一、基础网格材质

    基础网格材质,是一个以简单着色(平面或线框)方式来绘制几何体的材质。这种材质不受光照的影响。

    new MeshBasicMaterial(parameters: Object);
    
    • 1

    使用场景:适用于不需要光照计算或复杂渲染效果的简单物体。例如,静态的、不需要光照变化的物体。

    特点:不受光照影响,颜色始终保持一致。

    参数名称描述
    color材质颜色
    wireframe是否渲染成线框
    wireframeLinewidth设置线框宽度
    wireframeLinecap线段间的端点如何显示
    wireframeLinejoin线段的连接点如何显示
    shading定义如何着色
    vertexColors为每个顶点定义不同的颜色
    fog是否会受全局雾化效果设置的影响
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.MeshBasicMaterial({
                color: 0xff0000,
                wireframe: false
            });
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    基础网格材质


    二、深度网格材质

    深度网格材质是一种 按深度绘制几何体的材质。深度基于相机远近平面。白色最近,黑色最远。

    new MeshDepthMaterial(parameters: Object);
    
    • 1

    使用场景:用于显示物体的深度信息,通常用于深度测试或特殊视觉效果。

    特点:只渲染物体的深度信息,不显示颜色或纹理。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.MeshDepthMaterial();
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial, camera);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    深度网格材质


    三、法向网格材质

    法向网格材质是一种 把法向量映射到 RGB 颜色的材质

    new THREE.MeshNormalMaterial(parameters: Object);
    
    • 1

    使用场景:适用于低多边形数模型或动态生成的几何形状。通过使用法线贴图,它可以在没有复杂几何形状的情况下创建逼真的凹凸效果。

    特点:基于法向量的颜色映射,MeshNormalMaterial渲染的每一个面颜色都不同;但即使在物体旋转时,这些颜色也基本保持在原来的位置,这使得MeshNormalMaterial在需要保持颜色与面关联的场景中非常有用。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.MeshNormalMaterial();
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial, camera);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    法向网格材质


    四、面材质

    MeshFaceMaterial 在 Three.js 中并不是一个真正的材质,它更像是一个 材质容器。其主要用途是为几何体的每个面指定不同的材质,从而允许每个面具有独特的视觉表现。

    new THREE.MeshFaceMaterial(parameters: Object);
    
    • 1

    注:MeshFaceMaterial 在新版 Three.js 中已经被材质数组所取代。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.MeshFaceMaterial([
                new THREE.MeshBasicMaterial({ color: 0x009e60 }),
                new THREE.MeshBasicMaterial({ color: 0x0051ba }),
                new THREE.MeshBasicMaterial({ color: 0xffd500 }),
                new THREE.MeshBasicMaterial({ color: 0xc41e3a }),
                new THREE.MeshBasicMaterial({ color: 0xffff00 }),
                new THREE.MeshBasicMaterial({ color: 0xff5800 }),
            ]);
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial, camera);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    面材质


    五、朗伯网格材质

    朗伯网格材质是 一种非光泽表面的材质,没有镜面高光

    new THREE.MeshLambertMaterial(parameters: Object);
    
    • 1

    使用场景:适用于需要模拟漫反射光照效果的物体。这种材质对光源的方向和强度敏感,适合表现柔和的表面。

    特点:根据光源方向和强度计算表面颜色,产生柔和的阴影。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 });
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial, camera);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    朗伯网格材质


    六、Phong 网格材质

    Phong 网格材质是一种 用于具有镜面高光的光泽表面的材质

    new THREE.MeshPhongMaterial(parameters: Object);
    
    • 1

    使用场景:适用于需要更高级光照效果的物体,如镜面反射和高光。这种材质可以模拟更真实的光照效果。

    特点:支持漫反射、镜面反射和高光,可以产生更丰富的光影效果。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000 });
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial, camera);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    Phong网格材质


    七、着色器网格材质

    着色器网格材质是一种 使用自定义shader渲染的材质

    const material = new THREE.ShaderMaterial( {
    	uniforms: {
    		time: { value: 1.0 },
    		resolution: { value: new THREE.Vector2() }
    	},
    
    	vertexShader: document.getElementById( 'vertexShader' ).textContent,
    	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
    } );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用场景:适用于需要自定义渲染逻辑的高级场景。通过编写自定义的 GLSL 着色器代码,可以实现各种独特的视觉效果。

    特点:允许用户编写自定义的顶点和片段着色器,实现高度自定义的渲染效果。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const cubeMaterial = new THREE.ShaderMaterial({
                uniforms: {
                    r: {
                        type: 'f',
                        value: 1.0
                    },
                    a: {
                        type: 'f', // float 类型
                        value: 1.0
                    }
                },
                // 顶点着色器
                vertexShader: `
                    void main() {
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                    }
                `,
                // 片元着色器
                fragmentShader: `
                    uniform float r;
                    uniform float a;
                    
                    void main() {
                        gl_FragColor = vec4(r, 0.0, 0.0, a);
                    
                    }
                `,
                transparent: true,
            });
    
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
            
            initControls(cubeMaterial, camera);
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    着色器网格材质


    八、直线和虚线

    基础线条材质(直线)是一种 用于绘制线框样式几何体的材质

    // 直线
    const material = new THREE.LineBasicMaterial({
      color: 0xff0000,
      linewidth: 1,
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    虚线材质(虚线)是一种 用于绘制虚线样式几何体的材质。

    // 虚线
    const material = new THREE.LineDashedMaterial({
      color: 0xff0000,
      dashSize: 1, // 短划线的长度
      gapSize: 1 // 间隔的长度
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加直线和虚线
            const lines = new THREE.Geometry();
            lines.vertices = [
                new THREE.Vector3(0, 2, 5),
                new THREE.Vector3(0, -2, 5)
            ]
    
            // 直线
            // const material = new THREE.LineBasicMaterial({
            //     color: 0xff0000,
            //     linewidth: 1,
            // })
    
            // 虚线
            const material = new THREE.LineDashedMaterial({
                color: 0xff0000,
                dashSize: 1, // 短划线的长度
                gapSize: 1 // 间隔的长度
            });
    
            const line = new THREE.Line(lines, material);
            // 计算点到线的累积长度
            lines.computeLineDistances();
    
            scene.add(line);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
    
            initControls(material, camera);
    
            const animation = () => {
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    直线与虚线


    九、联合材质

    创建联合材质,需要使用 SceneUtils 场景工具,它一个用于操控场景的实用类。

    .createMultiMaterialObject ( geometry : BufferGeometry, materials : Array ) : Group
    geometry – 材料集的几何形状。
    materials – 为物体准备的材料。

    创建一个新组,囊括了在材质中定义的每种材质的新网格。请注意,这和为一个网格定义多种材质的材质数组不同。

    该方法对于同时需要材质和线框绘制的物体非常有用。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../lib/three/three.js"></script>
        <script src="../lib/three/dat.gui.js"></script>
        <script src="../controls/index.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    
    <body>
        <script>
            // 创建场景
            const scene = new THREE.Scene();
            // 创建相机 视野角度FOV、长宽比、近截面、远截面
            const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            // 设置相机位置
            camera.position.set(0, 0, 20);
    
            // 创建渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // 添加立方体
            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
            // 创建立方体材质
            const lambert = new THREE.MeshLambertMaterial({
                color: 0xff0000
            });
            const basic = new THREE.MeshBasicMaterial({
                wireframe: true
            });
    
            const cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [
                lambert, basic
            ]);
    
            // 添加到场景
            scene.add(cube);
    
            // 添加灯光
            const spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-10, 10, 90);
            scene.add(spotLight);
            spotLight.shadowMapWidth = 3456; // 分辨率宽度
            spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
    
            const animation = () => {
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
    
                // 渲染
                renderer.render(scene, camera);
                requestAnimationFrame(animation);
            }
    
            animation();
        </script>
    </body>
    
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    联合材质


    总结

    本篇文章我们讲解了几种常见材质的基本使用,包括基础材质、深度材质、法向材质、面材质、朗伯材质、Phong材质、着色器材质、直线和虚线、联合材质。

    更多内容扩展请大家自行查阅 => three.js官方文档,真心推荐读一读!!

    好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


    参考资料:

    1. Three.js 官方文档
    2. WebGL+Three.js 入门与实战【作者:慕课网_yancy】

    在这里插入图片描述


  • 相关阅读:
    前端技术知识(含八股)总结 - 持续更新中
    机器人关节控制硬件知识——伺服电机、驱动器、控制器
    模型进行MindIR格式文件导出时报错,请问如何定位错误,以及如何解决?
    你为什么做测试/开发程序员?还能回想出来吗......
    计算机组成原理知识点总结——第七章输入/输出系统
    基于智能合约的银行借贷方案设计与实现
    Flink学习20:算子介绍reduce
    【Tomcat】贰-Tomcat集成到Idea:解放双手,让Tomcat的操作没有那么难用
    一文读懂什么是硬件开发、智能硬件、硬件系统?
    【第46篇】RepVGG :让卷积再次伟大
  • 原文地址:https://blog.csdn.net/qq_45902692/article/details/137753290