• threejs视频教程学习(4):贴图、材质、光线


    获取材质贴图(3d模型)

    https://www.poliigon.com/

    https://www.textures.com/

    https://www.qingmo.com/

    https://pixabay.com/zh/

    https://ambientcg.com/list

    网站里提供了一些纹理图片和简单的模型

    map 颜色贴图

    基础网格材质(MeshBasicMaterial)

    一个以简单着色(平面或线框)方式来绘制几何体的材质。这种材质不受光照的影响。 不受光照影响说明不需要添加光源就可以看见物体

    <template>
        <div class="container" id="container"></div>
    </template>
    
    <script setup lang="ts">
    import { onMounted } from 'vue';
    import * as THREE from 'three';
    
    // 导入轨道控制器,模块化开发导入的是jsm不是js
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
    
    onMounted(() => {
        // 添加一个场景
        const scene = new THREE.Scene();
    
        // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置
        const camera = new THREE.PerspectiveCamera(
            75, // 摄像机视锥体垂直视野角度
            window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比
            0.1, // 摄像机视锥体近端面
            1000 // 摄像机视锥体远端面
        );
    
        // 设置相机的位置
        camera.position.set(0, 0, 10); // x、y、z
        // 把相机添加到场景中
        scene.add(camera);
        // 创建几何体
        const geometry = new THREE.BoxGeometry(2, 2, 2);
        // 设置材质
        const basicMaterial = new THREE.MeshBasicMaterial(
            {
                color: '#3f7b9d',
            }
        );
        // 创建物体
        const cube = new THREE.Mesh(geometry, basicMaterial);
        // 将立方体添加到场景中
        scene.add(cube);
    
        // 初始化渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染的尺寸大小
        renderer.setSize(800, 600);
        // 将wbgl渲染的canvas内容添加到dom元素中
        document.getElementById('container')?.appendChild(renderer.domElement);
    
        // 创建轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update()
        controls.enableDamping = true;
    
        // 添加坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);
    
        // 创建一个渲染函数,当场景发生变化后重新渲染
        const render = () => {
            controls.update();
            renderer.render(scene, camera);
            // 使用浏览器自带的请求动画帧函数不断的进行渲染
            requestAnimationFrame(render);
        };
    
        render();
    });
    </script>
    
    • 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

    在这里插入图片描述

    设置纹理

     // 导入纹理
     const textureLoader = new THREE.TextureLoader();
     const door = textureLoader.load('../../../../public/color.jpg');
     // 设置材质
     const basicMaterial = new THREE.MeshBasicMaterial(
         {
             color: 'yellow',
             map: door
         }
     );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    材质的颜色对纹理的颜色是有影响的。

    alphaMap 透明度贴图

    alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。

    透明度贴图可以用于场景空隙,比如铁栅栏。
    在这里插入图片描述

    // 导入纹理
    const textureLoader = new THREE.TextureLoader();
    // 颜色贴图
    const door = textureLoader.load('../../../../public/color.jpg');
    // 透明贴图
    const alpha = textureLoader.load('../../../../public/alpha.jpg');
    
    // 设置材质
    const basicMaterial = new THREE.MeshBasicMaterial(
        {
            color: 'yellow',
            map: door, // 颜色贴图
            alphaMap: alpha, // 透明贴图
            transparent: true // 必须要设置,否则透明贴图不会生效
        }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    环境遮挡贴图

    aoMap,个人觉得用于遮挡物体表面的光照,使物体表面出现阴影

     // 导入纹理
     const textureLoader = new THREE.TextureLoader();
     // 颜色贴图
     const door = textureLoader.load('../../../../public/color.jpg');
     // 透明贴图
     const alpha = textureLoader.load('../../../../public/alpha.jpg');
     // 环境遮挡贴图
     const aoMap = textureLoader.load('../../../../public/ambientOcclusion.jpg');
     // 创建几何体
     const geometry = new THREE.BoxGeometry(2, 2, 2);
    
     // 设置材质
     const basicMaterial = new THREE.MeshBasicMaterial(
         {
             color: 'yellow',
             map: door, // 颜色贴图
             alphaMap: alpha, // 透明贴图
             transparent: true, // 必须要设置,否则透明贴图不会生效
             aoMap: aoMap // 环境遮挡贴图
         }
     );
    
     // 创建物体
     const cube = new THREE.Mesh(geometry, basicMaterial);
     // 将立方体添加到场景中
     scene.add(cube);
     // 环境遮挡贴图需要第二组UV才能够生效,获取材质本身的UV
     geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2));
    
    • 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

    在这里插入图片描述

    物料渲染

    标准网格材质(MeshStandardMaterial)。一种基于物理的标准材质,使用Metallic-Roughness工作流程。
    基于物理的渲染(PBR)最近已成为许多3D应用程序的标准,例如Unity, Unreal和 3D Studio Max。使用标准网格材质必须要添加光源

    环境光

    AmbientLight,环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。

     // 设置材质
     const meshMaterial = new THREE.MeshStandardMaterial(
         {
             color: 'yellow',
             map: door, // 颜色贴图
             alphaMap: alpha, // 透明贴图
             transparent: true, // 必须要设置,否则透明贴图不会生效
             aoMap: aoMap // 环境遮挡贴图
         }
     );
    
     // 创建物体
     const cube = new THREE.Mesh(geometry, meshMaterial);
     // 将立方体添加到场景中
     scene.add(cube);
     // 环境遮挡贴图需要第二组UV才能够生效,获取材质本身的UV
     geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2));
    
     // 添加灯光,环境光,
     const light = new THREE.AmbientLight(0xffffff,0.6);  // 设置环境光的颜色和亮度,亮度最大是1
     scene.add(light);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    平行光

    DirectionalLight,平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 平行光可以投射阴影

    // 添加灯光,环境光
    const light = new THREE.AmbientLight(0xffffff, 0.6);
    scene.add(light);
    // 添加平行光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
    directionalLight.position.set(10, 0, 0); // 设置平行光是从x轴方向照射
    scene.add(directionalLight);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    位移贴图

    displacementMap ,位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象, 以及充当真实的几何体。根据贴图的颜色来进行凸显,颜色约白位置越高。

    贴图材料

    在这里插入图片描述

    // 位移贴图
    const displace = textureLoader.load('../../../../public/height.jpg');
    // 创建几何体,增加顶点数
    const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100);
    
    // 设置材质
    const meshMaterial = new THREE.MeshStandardMaterial(
        {
            color: 'yellow',
            map: door, // 颜色贴图
            alphaMap: alpha, // 透明贴图
            transparent: true, // 必须要设置,否则透明贴图不会生效
            aoMap: aoMap, // 环境遮挡贴图
            displacementMap: displace, // 位移贴图
            displacementScale: 0.2 // 设置位移贴图对网格的影响
        }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意点:
    1、必须给物体增加分段数,默认物体就是一整块,增加分段数后,就是由多块组合而成,这样位移贴图才能生效,使某些板块突出出来
    2、设置displacementScale,设置位移贴图对网格的影响成都
    在这里插入图片描述

    粗糙度贴图

    roughness
    材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。默认值为1.0。如果还提供roughnessMap,则两个值相乘。

    roughnessMap
    该纹理的绿色通道用于改变材质的粗糙度。黑色代表光滑,白色代表不光滑
    在这里插入图片描述

     // 设置材质
     const meshMaterial = new THREE.MeshStandardMaterial(
         {
             color: 'yellow',
             map: door, // 颜色贴图
             alphaMap: alpha, // 透明贴图
             transparent: true, // 必须要设置,否则透明贴图不会生效
             aoMap: aoMap, // 环境遮挡贴图
             displacementMap: displace, // 位移贴图
             displacementScale: 0.2, // 设置位移贴图对网格的影响
             roughness: 0 // 粗糙度
         }
     );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    很明显我们可以看见灯光
    在这里插入图片描述

     // 导入粗糙度贴图
     const roughMap = textureLoader.load('../../../../public/roughness.jpg');
     // 创建几何体,增加顶点数
     const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100);
    
     // 设置材质
     const meshMaterial = new THREE.MeshStandardMaterial(
         {
             color: 'yellow',
             map: door, // 颜色贴图
             alphaMap: alpha, // 透明贴图
             transparent: true, // 必须要设置,否则透明贴图不会生效
             aoMap: aoMap, // 环境遮挡贴图
             displacementMap: displace, // 位移贴图
             displacementScale: 0.2, // 设置位移贴图对网格的影响
             roughness: 1, // 粗糙度
             roughnessMap: roughMap // 粗糙度贴图
         }
     );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    金属贴图

    metalness
    材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。0.0到1.0之间的值可用于生锈金属的外观。如果还提供了metalnessMap,则两个值相乘。
    metalnessMap
    该纹理的蓝色通道用于改变材质的金属度。

    // 设置材质
    const meshMaterial = new THREE.MeshStandardMaterial(
        {
            color: 'yellow',
            map: door, // 颜色贴图
            alphaMap: alpha, // 透明贴图
            transparent: true, // 必须要设置,否则透明贴图不会生效
            aoMap: aoMap, // 环境遮挡贴图
            displacementMap: displace, // 位移贴图
            displacementScale: 0.2, // 设置位移贴图对网格的影响
            roughness: 1, // 粗糙度
            roughnessMap: roughMap, // 粗糙度贴图
            metalness: 1 // 金属度
        }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    设置金属度后,门会变成金属材质,没有光照的部分会看不见。
    在这里插入图片描述
    使用金属贴图,只让金属的部分变成金属材质
    在这里插入图片描述

    // 金属贴图
    const metaMap = textureLoader.load('../../../../public/metalness.jpg');
    // 创建几何体,增加顶点数
    const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100);
    
    // 设置材质
    const meshMaterial = new THREE.MeshStandardMaterial(
        {
            color: 'yellow',
            map: door, // 颜色贴图
            alphaMap: alpha, // 透明贴图
            transparent: true, // 必须要设置,否则透明贴图不会生效
            aoMap: aoMap, // 环境遮挡贴图
            displacementMap: displace, // 位移贴图
            displacementScale: 0.2, // 设置位移贴图对网格的影响
            roughness: 1, // 粗糙度
            roughnessMap: roughMap, // 粗糙度贴图
            metalness: 0, // 金属度
            metalnessMap: metaMap // 金属贴图
        }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    法线贴图

    normalMap
    用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照

    法线贴图的图片是有颜色的图
    在这里插入图片描述

     // 法线贴图
     const normalMap = textureLoader.load('../../../../public/normal.jpg');
     // 创建几何体,增加顶点数
     const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100);
    
     // 设置材质
     const meshMaterial = new THREE.MeshStandardMaterial(
         {
             color: 'yellow',
             map: door, // 颜色贴图
             alphaMap: alpha, // 透明贴图
             transparent: true, // 必须要设置,否则透明贴图不会生效
             aoMap: aoMap, // 环境遮挡贴图
             displacementMap: displace, // 位移贴图
             displacementScale: 0.2, // 设置位移贴图对网格的影响
             roughness: 1, // 粗糙度
             roughnessMap: roughMap, // 粗糙度贴图
             metalness: 0, // 金属度
             metalnessMap: metaMap, // 金属贴图
             normalMap: normalMap // 法线贴图
         }
     );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述
    对比之前的图可以看到,光并不是一个完整的圆圈了。
    在这里插入图片描述

    完整代码

    <template>
        <div class="container" id="container"></div>
    </template>
    
    <script setup lang="ts">
    import { onMounted } from 'vue';
    import * as THREE from 'three';
    
    // 导入轨道控制器,模块化开发导入的是jsm不是js
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
    
    onMounted(() => {
        // 添加一个场景
        const scene = new THREE.Scene();
    
        // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置
        const camera = new THREE.PerspectiveCamera(
            75, // 摄像机视锥体垂直视野角度
            window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比
            0.1, // 摄像机视锥体近端面
            1000 // 摄像机视锥体远端面
        );
    
        // 设置相机的位置
        camera.position.set(0, 0, 10); // x、y、z
        // 把相机添加到场景中
        scene.add(camera);
    
        // 导入纹理
        const textureLoader = new THREE.TextureLoader();
        // 颜色贴图
        const door = textureLoader.load('../../../../public/color.jpg', () => {
            console.log('颜色贴图加载完成');
        });
    
        // 透明贴图
        const alpha = textureLoader.load('../../../../public/alpha.jpg');
        // 环境遮挡贴图
        const aoMap = textureLoader.load('../../../../public/ambientOcclusion.jpg');
        // 位移贴图
        const displace = textureLoader.load('../../../../public/height.jpg');
        // 导入粗糙度贴图
        const roughMap = textureLoader.load('../../../../public/roughness.jpg');
        // 金属贴图
        const metaMap = textureLoader.load('../../../../public/metalness.jpg');
        // 法线贴图
        const normalMap = textureLoader.load('../../../../public/normal.jpg');
        // 创建几何体,增加顶点数
        const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100);
    
        // 设置材质
        const meshMaterial = new THREE.MeshStandardMaterial(
            {
                color: 'yellow',
                map: door, // 颜色贴图
                alphaMap: alpha, // 透明贴图
                transparent: true, // 必须要设置,否则透明贴图不会生效
                aoMap: aoMap, // 环境遮挡贴图
                displacementMap: displace, // 位移贴图
                displacementScale: 0.2, // 设置位移贴图对网格的影响
                roughness: 1, // 粗糙度
                roughnessMap: roughMap, // 粗糙度贴图
                metalness: 0, // 金属度
                metalnessMap: metaMap, // 金属贴图
                normalMap: normalMap // 法线贴图
            }
        );
    
        // 创建物体
        const cube = new THREE.Mesh(geometry, meshMaterial);
        // 将立方体添加到场景中
        scene.add(cube);
        // 环境遮挡贴图需要第二组UV才能够生效,获取材质本身的UV
        geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2));
    
        // 添加灯光,环境光
        const light = new THREE.AmbientLight(0xffffff, 0.6);
        scene.add(light);
        // 添加平行光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
        directionalLight.position.set(10, 0, 0); // 设置平行光是从x轴方向照射
        scene.add(directionalLight);
    
        // 初始化渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染的尺寸大小
        renderer.setSize(800, 600);
        // 将wbgl渲染的canvas内容添加到dom元素中
        document.getElementById('container')?.appendChild(renderer.domElement);
    
        // 创建轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update()
        controls.enableDamping = true;
    
        // 添加坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);
    
        // 创建一个渲染函数,当场景发生变化后重新渲染
        const render = () => {
            controls.update();
            renderer.render(scene, camera);
            // 使用浏览器自带的请求动画帧函数不断的进行渲染
            requestAnimationFrame(render);
        };
    
        render();
    });
    </script>
    
    • 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

    纹理加载进度

    TextureLoader类提供了load方法,前面我们只是用来加载文件,下面看一下它的回调
    TextureLoader提供了几个方法:

    单张纹理加载

     // 导入纹理
     const textureLoader = new THREE.TextureLoader();
     // 颜色贴图
     const door = textureLoader.load('../../../../public/color.jpg', () => {
         console.log('颜色贴图加载完成');
     });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    LoadingManager

    其功能是处理并跟踪已加载和待处理的数据。具体内容见官方文档

    环境贴图

    例如有一个光滑的金属小球,真实情况下,小球表面是可以显示出周围的环境的。这个效果可以通过环境贴图来实现
    在这里插入图片描述

    envMap
    环境贴图,为了能够保证物理渲染准确,您应该添加由PMREMGenerator预处理过的环境贴图,默认为null。

    envMapIntensity
    通过乘以环境贴图的颜色来缩放环境贴图的效果。

    <template>
        <div class="container" id="container"></div>
    </template>
    
    <script setup lang="ts">
    import { onMounted } from 'vue';
    import * as THREE from 'three';
    
    // 导入轨道控制器,模块化开发导入的是jsm不是js
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
    
    onMounted(() => {
        // 添加一个场景
        const scene = new THREE.Scene();
    
        // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置
        const camera = new THREE.PerspectiveCamera(
            75, // 摄像机视锥体垂直视野角度
            window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比
            0.1, // 摄像机视锥体近端面
            1000 // 摄像机视锥体远端面
        );
    
        // 设置相机的位置
        camera.position.set(0, 0, 10); // x、y、z
        // 把相机添加到场景中
        scene.add(camera);
    
        // 环境贴图
        const envMap = new THREE.CubeTextureLoader()
            .setPath('../../../../public/env/')
            .load([
                'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'
            ]);
    
        // 创建球体,半径1,20是分段
        const spherGeometry = new THREE.SphereGeometry(1, 20, 20);
        const spherMaterial = new THREE.MeshStandardMaterial({
            metalness: 0.7, // 金属度
            roughness: 0.1, // 粗糙度
            envMap: envMap // 环境贴图
        });
    
        // 创建物体
        const cube = new THREE.Mesh(spherGeometry, spherMaterial);
        // 将立方体添加到场景中
        scene.add(cube);
    
        // 添加灯光,环境光
        const light = new THREE.AmbientLight(0xffffff, 0.6);
        scene.add(light);
        // 添加平行光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
        directionalLight.position.set(10, 0, 0); // 设置平行光是从x轴方向照射
        scene.add(directionalLight);
    
        // 初始化渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染的尺寸大小
        renderer.setSize(800, 600);
        // 将wbgl渲染的canvas内容添加到dom元素中
        document.getElementById('container')?.appendChild(renderer.domElement);
    
        // 创建轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update()
        controls.enableDamping = true;
    
        // 添加坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);
    
        // 创建一个渲染函数,当场景发生变化后重新渲染
        const render = () => {
            controls.update();
            renderer.render(scene, camera);
            // 使用浏览器自带的请求动画帧函数不断的进行渲染
            requestAnimationFrame(render);
        };
    
        render();
    });
    </script>
    
    • 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

    1、环境贴图的加载必须按照顺序来,分别是px(正方向的x轴贴图)、nx(负方向的x轴贴图)、py(正方形的y轴贴图)、ny(负方向的y轴贴图)、pz(正方形的z轴贴图)、nz(负方向的轴贴图)
    2、必须要给物体设置金属度和光滑度,只设置环境贴图是无用的

    在这里插入图片描述

    设置场景的背景

     // 给场景设置背景
     scene.background = envMap;
     // 给场景内的所有问题添加默认的环境贴图,如果场景内的物体有环境贴图则使用自身的,没有则使用默认的
     scene.environment = envMap;
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    HDR环境图的设置

    对应HDR指令的文件需要使用DataTextureLoader加载器,用于加载二进制文件格式的(rgbe, hdr, …)的抽象类。 内部使用FileLoader来加载文件, 和创建一个新的 DataTexture.

    import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader'
    
    const rgbeloader = new RGBELoader();
    rgbeloader.loadAsync('../../../../public/002.hdr')
    .then((texture) => {
        // 设置纹理映射类型
        texture.mapping = THREE.EquirectangularReflectionMapping;
        scene.background = texture;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    灯光与阴影

    常用光

    平行光(DirectionalLight)、点光源(PointLight)、聚光灯(SpotLight)可以产生阴影。
    平行光:平行光是沿着特定方向发射的光。
    点光源:从一个点向各个方向发射的光源。
    聚光灯:光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。比如手电筒

    环境光(AmbientLight)、平面光(RectAreaLight)不可以产生阴影
    环境光:环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。
    平面光:平面光光源从一个矩形平面上均匀地发射光线。这种光源可以用来模拟像明亮的窗户或者条状灯光光源。

    常用材质
    基础网格材质(MeshBasicMaterial)不受光照的影响 ,标准网格材质(MeshStandardMaterial)受光照的影响。其他材质像我这种入门者应该也用不到就不介绍了。

    灯光阴影

    1、材质要满足对光照有反应
    2、设置渲染器开启阴影的计算
    3、设置光照投射阴影
    4、设置物体投射阴影
    5、设置物体接收阴影
    6、要注意光照的角度

    <template>
        <div class="container" id="container"></div>
    </template>
    
    <script setup lang="ts">
    import { onMounted } from 'vue';
    import * as THREE from 'three';
    
    // 导入轨道控制器,模块化开发导入的是jsm不是js
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
    
    onMounted(() => {
        // 添加一个场景
        const scene = new THREE.Scene();
    
        // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置
        const camera = new THREE.PerspectiveCamera(
            75, // 摄像机视锥体垂直视野角度
            window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比
            0.1, // 摄像机视锥体近端面
            1000 // 摄像机视锥体远端面
        );
    
        // 设置相机的位置
        camera.position.set(0, 0, 10); // x、y、z
        // 把相机添加到场景中
        scene.add(camera);
    
        // 创建球体,半径1,20是分段
        const spherGeometry = new THREE.SphereGeometry(1, 20, 20);
        const material = new THREE.MeshStandardMaterial();
        const cube = new THREE.Mesh(spherGeometry, material); // 球体
        cube.castShadow = true; // 设置球体可以投射阴影
        // 将立方体添加到场景中
        scene.add(cube);
        // 创建平面并添加到场景中
        const planeGeometry = new THREE.PlaneGeometry(10, 10, 10, 10); // 平面物体
        const plane = new THREE.Mesh(planeGeometry, material); // 平面
        plane.position.set(0, -1, 0);
        plane.rotation.x = -Math.PI / 2;
        // 设置平面可以接收来自球的阴影
        plane.receiveShadow = true;
        scene.add(plane);
    
        // 添加灯光,环境光
        const light = new THREE.AmbientLight(0xffffff, 0.6);
        scene.add(light);
        // 添加平行光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
        directionalLight.position.set(15, 10, 0); // 设置平行光是从x轴方向照射
        directionalLight.castShadow = true; // 设置光照产生阴影
        scene.add(directionalLight);
    
        // 初始化渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染的尺寸大小
        renderer.setSize(800, 600);
        // 开启场景阴影渲染
        renderer.shadowMap.enabled = true;
        // 将wbgl渲染的canvas内容添加到dom元素中
        document.getElementById('container')?.appendChild(renderer.domElement);
    
        // 创建轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update()
        controls.enableDamping = true;
    
        // 添加坐标轴辅助器
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);
    
        // 创建一个渲染函数,当场景发生变化后重新渲染
        const render = () => {
            controls.update();
            renderer.render(scene, camera);
            // 使用浏览器自带的请求动画帧函数不断的进行渲染
            requestAnimationFrame(render);
        };
    
        render();
    });
    </script>
    
    • 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

    在这里插入图片描述

  • 相关阅读:
    markdown文档:一个简单标记语言的使用及实际应用(超简单)
    代码随想录笔记--回溯算法篇
    Unity Android(九)USB权限弹窗问题
    高斯消元(Java实现)
    【数据结构】交换排序
    智维专业工程师告诉你,哪款Kvaser多通道CAN总线分析仪性价比最高?
    JavaScript 字符串 原理 + 字符串拼接 + 模板字符串详解 +案例
    通过融合UGV的地图信息和IMU的惯性测量数据,实现对车辆精确位置和运动状态的估计和跟踪研究(Matlab代码实现)
    你是否了解Spring @EventListener注解?
    文章预览 安防监控/视频存储/视频汇聚平台EasyCVR播放优化小tips
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/127542149