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>

在这里插入图片描述

设置纹理

 // 导入纹理
 const textureLoader = new THREE.TextureLoader();
 const door = textureLoader.load('../../../../public/color.jpg');
 // 设置材质
 const basicMaterial = new THREE.MeshBasicMaterial(
     {
    
    
         color: 'yellow',
         map: door
     }
 );

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

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 // 必须要设置,否则透明贴图不会生效
    }
);

在这里插入图片描述

环境遮挡贴图

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));

在这里插入图片描述

物料渲染

标准网格材质(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);

在这里插入图片描述

平行光

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);

在这里插入图片描述

位移贴图

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、设置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 // 粗糙度
     }
 );

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

 // 导入粗糙度贴图
 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 // 粗糙度贴图
     }
 );

金属贴图

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 // 金属度
    }
);

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

// 金属贴图
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 // 金属贴图
    }
);

法线贴图

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 // 法线贴图
     }
 );

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

完整代码

<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>

纹理加载进度

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

单张纹理加载

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

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

在这里插入图片描述

设置场景的背景

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

在这里插入图片描述

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;
});

在这里插入图片描述

灯光与阴影

常用光

平行光(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>

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41897680/article/details/127542149