当前位置: 首页 > news >正文

Three.js 零基础+概念理解

文章目录

    • 一、Three.js基础概念
      • (一)什么是Three.js
      • (二)核心对象
      • (三)几何体(Geometries)和材质(Materials)
    • 二、基础实例应用
      • (一)创建一个简单的3D立方体场景
      • (二)添加光照效果
    • 透视相机(PerspectiveCamera)与正交相机(OrthographicCamera)
    • 场景、 相机、 渲染器 三者之间的关系
    • 相机 的应用与理解
    • 渲染器
      • 材质系统
      • 着色器
    • Three.js着色器的具体实例
      • 示例一:简单的颜色渐变效果
      • 示例二:模拟水面波动效果
      • 示例三:卡通渲染效果
    • 着色器 函数语法简要理解

一、Three.js基础概念

(一)什么是Three.js

  • Three.js是一个基于JavaScript的3D库,它通过使用WebGL(Web Graphics Library)在浏览器中创建和展示3D图形。WebGL是一个JavaScript API,用于在支持HTML5的浏览器中渲染高性能的交互式3D和2D图形,而Three.js在其基础上提供了更简单、易用的高级接口,让开发者能够轻松地构建3D场景,而无需深入了解底层的WebGL细节。

(二)核心对象

  1. 场景(Scene)
    • 场景是所有3D物体、光源等元素的容器。就像是一个舞台,你可以在这个舞台上放置各种道具(3D模型)和灯光设备(光源)来构建一个完整的3D世界。例如,你要创建一个室内场景,可以将桌子、椅子等模型添加到场景中。
  2. 相机(Camera)
    • 相机用于定义观察3D场景的视角。它决定了我们从哪个位置、方向和角度去看场景中的物体。Three.js中有多种相机类型,如透视相机(PerspectiveCamera)和正交相机(OrthographicCamera)。透视相机模拟人眼的视觉效果,离相机近的物体看起来大,远的物体看起来小;正交相机则不会产生这种近大远小的效果,常用于2D游戏或建筑设计等需要精确尺寸显示的场景。
  3. 渲染器(Renderer)
    • 渲染器的主要任务是将场景中的物体和光源通过相机视角渲染成2D图像显示在浏览器中。它负责处理WebGL的底层绘图操作,根据场景和相机的设置,计算每个像素的颜色和光照效果等信息。常见的渲染器是WebGLRenderer,它可以充分利用浏览器对WebGL的支持来生成高质量的3D图形。

(三)几何体(Geometries)和材质(Materials)

  1. 几何体
    • 几何体定义了3D物体的形状。Three.js提供了许多基本的几何体类型,如立方体(BoxGeometry)、球体(SphereGeometry)、圆柱体(CylinderGeometry)等。例如,要创建一个简单的3D方块,就可以使用BoxGeometry。你还可以通过修改几何体的顶点(Vertices)等属性来创建自定义的形状。
  2. 材质
    • 材质决定了物体表面的外观,包括颜色、纹理、透明度等特性。例如,你可以创建一个简单的漫反射材质(MeshBasicMaterial),设置它的颜色为红色,然后将这个材质应用到一个立方体几何体上,这个立方体就会显示为红色。材质还可以包含纹理(Texture),比如你可以将一张木材纹理的图片应用到一个长方体上,使其看起来像一个木质的盒子。

二、基础实例应用

(一)创建一个简单的3D立方体场景

  1. 引入Three.js库
    • 首先,需要在HTML文件中引入Three.js库。你可以通过下载Three.js文件并在本地引用,也可以使用CDN(内容分发网络)链接。例如:
    <script 
    src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"
    ></script>
    
  2. 创建场景、相机和渲染器
    • 在JavaScript代码中,首先创建一个场景、一个透视相机和一个WebGL渲染器。
    // 创建场景
    const scene = new THREE.Scene();
    // 创建相机
    const camera = new THREE.PerspectiveCamera
    (75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 5;
    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    • 在上述代码中,PerspectiveCamera的第一个参数75是视野角度(Field of View),它定义了相机可视区域的垂直角度范围。window.innerWidth / window.innerHeight是宽高比,用于保持场景在不同屏幕尺寸下的正确比例。0.11000分别是近裁剪平面(Near Clipping Plane)和远裁剪平面(Far Clipping Plane)的距离,只有在这个距离范围内的物体才会被渲染。
  3. 创建几何体和材质并添加到场景中
    • 接着,创建一个立方体几何体和一个基础材质,将材质应用到几何体上形成一个网格(Mesh),然后将网格添加到场景中。
    // 创建立方体几何体
    const geometry = new THREE.BoxGeometry();
    // 创建基础材质
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    // 创建网格
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    
    • 这里BoxGeometry创建了一个边长为1的立方体,MeshBasicMaterial设置了材质的颜色为绿色(0x00ff00是十六进制的颜色代码),Mesh对象将几何体和材质组合在一起,最后通过scene.add将立方体添加到场景中。
  4. 渲染场景
    • 最后,定义一个渲染循环来不断更新和渲染场景。
    function animate() {requestAnimationFrame(animate);cube.rotateX(0.01);cube.rotateY(0.01);renderer.render(scene, camera);
    }
    animate();
    
    • requestAnimationFrame是一个浏览器提供的API,它会在浏览器下一次重绘之前调用传入的函数(在这里是animate函数),这样可以实现流畅的动画效果。在animate函数中,让立方体绕X轴和Y轴每次旋转一个小角度(0.01弧度),然后通过renderer.render使用相机渲染场景,这样就可以在浏览器中看到一个不断旋转的绿色立方体。

(二)添加光照效果

  1. 点光源(Point Light)示例
    • 在上面的例子基础上,可以添加一个点光源来照亮立方体。
    // 创建点光源
    const pointLight = new THREE.PointLight(0xffffff, 1, 100);
    pointLight.position.set(0, 0, 5);
    scene.add(pointLight);
    
    • 这里创建了一个白色(0xffffff)的点光源,强度为1,照射距离可达100。通过position.set设置光源的位置在(0, 0, 5),最后将光源添加到场景中。同时,需要将立方体的材质修改为能够响应光照的材质,如MeshPhongMaterial
    const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
    
    • 这样,立方体就会被点光源照亮,并且根据光照和物体表面的角度等因素产生明暗效果。

透视相机(PerspectiveCamera)与正交相机(OrthographicCamera)

  1. 透视相机(PerspectiveCamera)与正交相机(OrthographicCamera)的区别
    • 投影方式
      • 透视相机:采用透视投影,模拟人眼的视觉效果。在这种投影方式下,离相机近的物体看起来大,离相机远的物体看起来小。这种投影方式符合我们日常生活中的视觉感知,能够产生深度感和真实感。例如,在一个3D游戏场景中,远处的山脉看起来比近处的树木小很多,这就是透视投影的效果。
      • 正交相机:使用正交投影,物体的大小不会因为距离相机的远近而改变。在正交投影中,所有平行于相机平面的线条在渲染后仍然保持平行。例如,在绘制建筑蓝图或者2D游戏的地图时,使用正交投影可以确保物体的尺寸在屏幕上的显示是精确的,不会因为距离而产生缩放。
    • 视锥体(View Frustum)形状
      • 透视相机:其视锥体是一个截头锥体(frustum)。视锥体的近平面和远平面是两个平行的平面,但是近平面的尺寸小于远平面的尺寸。靠近相机的物体占据视锥体近平面的较大部分,而远处的物体占据远平面的较小部分,从而产生近大远小的效果。
      • 正交相机:视锥体是一个长方体形状。相机看到的场景就像是通过一个平行于相机平面的“窗口”观察,这个窗口的大小从近平面到远平面是不变的,所以物体在整个视锥体范围内的大小保持一致。
    • 数学模型和计算方式
      • 透视相机:在透视投影的数学模型中,涉及到透视除法。对于空间中的一个点((x,y,z)),在投影到屏幕空间时,其坐标计算会根据距离相机的远近((z)坐标)进行非线性变换。例如,一个点((x,y,z))在透视投影后的屏幕坐标((x’,y’))的计算会涉及到(x’ = x/z),(y’ = y/z)(这是简化的模型,实际计算还涉及到视口变换等其他因素)等类似的运算,这种计算方式导致了近大远小的效果。
      • 正交相机:正交投影的计算相对简单。对于空间中的一个点((x,y,z)),在正交投影到屏幕空间时,其坐标((x’,y’))的计算是线性的,通常是(x’ = x),(y’ = y)(同样是简化模型,还需要考虑视口和相机位置等因素),只要点在相机的视锥体范围内,其投影后的大小和位置只与点在相机坐标系中的相对位置有关,而与距离无关。
  2. 应用场景
    • 透视相机的应用场景
      • 3D游戏场景:在大多数3D游戏中,透视相机是主要的选择。比如第一人称射击游戏(FPS),玩家通过角色的视角观察游戏世界,远处的敌人看起来较小,近处的武器和物品看起来较大,这种透视效果能够增强游戏的沉浸感和真实感。像《使命召唤》系列游戏,玩家在游戏中穿梭于各种复杂的地形和建筑之间,透视相机能够很好地呈现出远近物体的大小差异,让玩家感受到真实的空间环境。
      • 3D建模和动画软件的视图操作:在3D建模软件如Blender、Maya等中,透视视图是常用的一种视图模式。当艺术家在创建3D模型,如人物、建筑、机械等模型时,透视视图可以帮助他们更好地把握模型的比例和空间关系。在进行动画制作时,透视相机也能准确地呈现出动画角色在场景中的运动轨迹和空间位置变化,就像制作一部3D动画电影,透视相机能够让观众感受到场景的深度和层次感。
      • 虚拟现实(VR)和增强现实(AR)应用:在VR和AR场景中,透视相机的使用也非常重要。例如在VR游戏中,玩家完全沉浸在虚拟世界中,透视效果能够让玩家感觉自己就像在真实的世界中一样,增强了虚拟现实的体验。在AR应用中,当虚拟物体与现实世界相结合时,透视相机可以根据现实世界的空间感知,正确地显示虚拟物体的大小和位置,如在一些AR家居装修应用中,用户可以通过手机屏幕看到虚拟的家具在真实房间中的透视效果,从而更好地判断家具的大小是否合适。
    • 正交相机的应用场景
      • 2D游戏开发:许多2D游戏,特别是像素风格的游戏或者横版卷轴游戏,通常使用正交相机。例如《超级马里奥》这样的横版过关游戏,游戏中的角色、道具和场景元素的大小在屏幕上始终保持一致,无论角色是在屏幕的左边还是右边。这是因为正交相机保证了游戏世界的精确呈现,开发者可以更容易地控制游戏元素的布局和碰撞检测等。
      • 建筑设计和CAD(计算机辅助设计)软件:在建筑设计图纸的绘制过程中,正交投影是必不可少的。建筑师需要精确地展示建筑物的平面图、剖面图和立面图等,正交相机能够确保建筑的各个部分在图纸上的尺寸准确无误。在CAD软件中,工程师在设计机械零件、电路板等产品时,正交视图可以提供准确的尺寸信息,方便设计和制造过程中的精度控制。
      • 地图绘制和数据可视化:在地图制作中,尤其是绘制城市地图、地形图等,正交相机可以确保地图上的地理信息(如建筑物、道路等)按照实际的比例和相对位置准确地显示。在数据可视化领域,当需要展示一些具有精确尺寸关系的数据集,如统计图表的3D柱状图或者方格状的数据网格时,正交相机可以避免因透视效果而导致的数据误解,保证数据的清晰和准确呈现。

场景、 相机、 渲染器 三者之间的关系

  1. 场景(Scene)是基础元素的容器

    • 场景就像是一个虚拟的3D世界舞台,它包含了所有要展示的3D物体(如立方体、球体等几何体)、光源(点光源、平行光源等)以及其他辅助对象。这些对象在场景中有自己的位置、方向和属性。例如,在一个室内场景中,场景对象会包含家具模型(作为几何体)、照亮房间的灯光(光源)等。
    • 场景定义了整个3D空间的内容和布局,是相机观察和渲染器渲染的对象。它提供了一个空间框架,使得所有3D元素能够在其中相互作用并且被正确地展示。
  2. 相机(Camera)是观察场景的视角设定工具

    • 相机决定了从哪个位置、方向和角度去观察场景中的元素。它就像是观众的眼睛或者拍摄场景的摄像机。不同类型的相机(如透视相机和正交相机)会以不同的方式“捕捉”场景中的画面。
    • 相机的位置、朝向和视野范围等参数影响着最终渲染出来的图像内容。例如,通过调整相机的位置,可以展示场景的不同部分;改变相机的视角方向,能够从不同的角度观察物体;而相机的视野角度(对于透视相机而言)或者视口大小(对于正交相机而言)则决定了能够看到场景中的多少内容。
    • 相机与场景紧密相连,它观察场景中的元素,并将观察到的信息传递给渲染器,告知渲染器哪些部分需要被渲染以及如何渲染这些部分。
  3. 渲染器(Renderer)是将场景通过相机视角转化为2D图像的工具

    • 渲染器的主要职责是根据场景中的物体、光源以及相机的设置,将3D场景转换为可以在浏览器或者其他显示设备上显示的2D图像。它处理复杂的图形计算,如光照计算、材质纹理映射、物体投影等诸多细节。
    • 渲染器依赖于场景提供的物体和光源信息,以及相机提供的视角信息。例如,渲染器会根据相机的位置和方向来确定场景中哪些物体在视野范围内,然后根据场景中的物体材质(如颜色、纹理等)和光源设置(如光照强度、光照类型等)来计算每个像素的颜色和亮度等属性,最终生成一张完整的2D图像。
  4. 三者之间的相互协作关系

    • 场景是核心,它包含了所有要展示的3D内容。相机观察场景,其观察的结果(视角范围内的场景元素)作为输入提供给渲染器。渲染器则根据相机的观察结果和场景中的物体、光源等信息进行渲染,最终生成在屏幕上显示的2D图像。
    • 可以把这个过程想象成拍摄电影。场景是电影的拍摄场地,包含了演员(3D物体)和灯光设备(光源)等。相机是拍摄电影的摄像机,它选择拍摄的角度和范围。渲染器则是后期制作设备,将摄像机拍摄到的原始素材(相机观察到的场景)进行处理,如添加特效(光照效果等),最终制作出可以在屏幕上播放的电影画面(2D图像)。这三者相互配合,缺一不可,共同实现了3D场景在屏幕上的可视化。

相机 的应用与理解

  1. 相机在Three.js中的作用

    • 视角定义

      • 相机在Three.js中最基本的作用是定义观察3D场景的视角。它确定了我们从何处、以何种角度来查看场景中的物体。例如,通过设置相机的位置(camera.position),可以决定是从场景的上方、侧面还是内部来观察物体。如果将相机位置设置为(0, 0, 5),就表示相机位于场景的正前方距离原点5个单位的位置来观察场景。
      • 不同类型的相机(如透视相机和正交相机)提供了不同的投影方式,从而产生不同的视觉效果。透视相机能够模拟人眼的视觉,产生近大远小的效果,适合用于创建具有真实感和深度感的3D场景,如游戏场景、建筑外观展示等。正交相机则保证物体的大小不受距离的影响,适合用于需要精确尺寸展示的场景,如2D游戏、建筑图纸等。
    • 视野范围控制

      • 相机的参数还包括视野角度(Field of View,对于透视相机而言)。这个参数决定了相机能够看到的场景范围的大小。例如,一个较大的视野角度(如90度)会使相机看到更广阔的场景,但同时可能会导致物体看起来较小且变形;而一个较小的视野角度(如30度)会聚焦在一个较小的区域,使物体看起来更大,但看到的场景范围有限。
      • 相机的近裁剪平面(Near Clipping Plane)和远裁剪平面(Far Clipping Plane)参数也很重要。只有位于近裁剪平面和远裁剪平面之间的物体才会被相机捕捉并传递给渲染器进行渲染。这可以避免处理距离相机过远或过近的不必要的物体,提高渲染效率,同时也有助于控制场景的可见范围。
    • 场景筛选与聚焦

      • 相机实际上起到了筛选场景内容的作用。通过调整相机的位置、方向和参数,能够选择将场景中的哪些部分展示给用户。例如,在一个复杂的室内场景中,通过移动相机可以聚焦在房间的某个角落或者某件家具上,而忽略其他部分。这种聚焦能力使得开发者可以引导用户的注意力,突出场景中的重要元素。
  2. 相机与物体运动的关系

    • 相对运动产生视觉效果
      • 物体运动和相机运动是相对的,当物体在场景中移动时,从相机的视角看,就像是物体在运动;同样,当相机移动时,也会给人一种物体在运动或者场景在变化的感觉。例如,在一个飞行模拟游戏中,飞机(物体)向前飞行,从固定的相机视角看,飞机在向前移动;但如果相机附着在飞机上(如第一人称视角),那么地面和天空等场景元素就会看起来在向后移动。
    • 相机运动引导物体运动感知
      • 相机的运动可以用来引导观众对物体运动的感知。例如,在电影制作中常用的“跟拍”技巧,在Three.js场景中可以通过让相机跟随物体运动来实现。如果一个小球在滚动,相机以相同的速度和方向在小球旁边移动并始终聚焦在小球上,就会给观众一种强烈的视觉暗示,让观众更加关注小球的运动细节。
    • 物体运动与相机参数的交互影响
      • 物体的运动可能会导致其离开相机的视野范围。当物体靠近相机的近裁剪平面或远离相机的远裁剪平面时,可能会出现物体突然消失或进入视野的情况。这就需要合理调整相机的近裁剪平面和远裁剪平面参数,以适应物体的运动范围。
      • 物体的运动也可能影响相机的自动调整策略。例如,在一些3D游戏中,当角色(物体)快速移动时,相机可能需要自动调整其位置、视野角度等来保持角色在视野范围内并且能够提供良好的视觉体验。这种自动调整通常涉及到复杂的算法,如根据物体的速度和方向来动态改变相机的位置和方向。

渲染器

  1. Three.js渲染器的定义

    • 在Three.js中,渲染器(Renderer)是一个至关重要的组件,它的主要职责是将3D场景(Scene)中的物体和光源,通过相机(Camera)所定义的视角,转换为可以在浏览器或者其他显示设备上显示的2D图像。简单来说,它就像是一个翻译器,把复杂的3D场景信息“翻译”成屏幕上能够被用户看到的视觉内容。
  2. Three.js渲染器的组成部分

    • 渲染上下文(Rendering Context)
      • 渲染器依赖于WebGL(Web Graphics Library)或者其他图形API(如CSS3D Renderer可以利用CSS 3D Transforms来渲染场景)提供的渲染上下文。对于WebGL渲染器(WebGLRenderer),这个渲染上下文是通过WebGL的API与浏览器的图形硬件进行交互的接口。它负责处理底层的图形渲染操作,如创建和管理纹理、缓冲区(Buffer)、帧缓冲(Framebuffer)等。
      • 例如,在WebGL中,通过渲染上下文可以创建顶点缓冲区(Vertex Buffer)来存储3D模型的顶点数据,以及索引缓冲区(Index Buffer)来指定顶点的连接顺序,从而构建出复杂的几何形状。
    • 渲染循环(Render Loop)
      • 渲染循环是渲染器的核心部分之一。它是一个不断重复执行的过程,用于持续更新和渲染3D场景。通常使用requestAnimationFrame函数来实现渲染循环。这个函数会在浏览器下一次重绘之前调用指定的函数,确保渲染的流畅性和高效性。
      • 在渲染循环中,渲染器会执行一系列操作,如更新物体的位置、姿态(对于动态场景),计算光照效果,处理相机的移动和视角变化等。然后,根据这些信息和场景中的物体材质、几何形状等,计算每个像素的颜色和其他属性,最终生成并更新2D图像。例如,在一个简单的3D动画场景中,渲染循环会在每次循环中使物体绕某个轴旋转一定角度,然后重新渲染场景,让用户看到物体在旋转的动画效果。
    • 材质系统(Material System)与着色器(Shader)管理
      • 渲染器需要管理和应用各种材质(Materials)到3D场景中的物体上。材质决定了物体表面的外观特性,如颜色、纹理、透明度、光泽度等。Three.js渲染器与材质系统紧密配合,将材质的属性传递给相应的着色器程序(顶点着色器和片元着色器)进行处理。
      • 对于不同类型的材质(如MeshBasicMaterial、MeshPhongMaterial等),渲染器会选择和编译合适的着色器组合。例如,MeshPhongMaterial用于实现具有光照效果的材质,渲染器会使用包含光照计算的顶点着色器和片元着色器来处理这种材质,以正确地呈现出物体在光照环境下的外观,包括高光、漫反射和环境光反射等效果。
    • 光照处理(Light Processing)
      • 渲染器负责处理3D场景中的光照效果。它会根据场景中不同类型的光源(如点光源、平行光源、环境光等)和物体的材质属性,计算光照对物体表面的影响。这涉及到复杂的光照模型,如兰伯特(Lambert)漫反射模型和Phong高光反射模型等。
      • 例如,当场景中有一个点光源时,渲染器会计算从点光源发出的光线如何照射到物体表面,根据物体表面的法线方向(通过顶点着色器传递)和光源位置,确定每个片元(像素)的光照强度和颜色变化。在计算过程中,还会考虑环境光的影响,即即使物体没有直接被光源照射,也会有一定的基础亮度,以避免物体在阴影区域完全变黑。
    • 场景图(Scene Graph)遍历与渲染对象管理
      • 渲染器需要遍历3D场景中的对象树(Scene Graph),也就是场景中的所有物体、光源和其他辅助对象按照一定的层次结构组织起来的树形结构。它会从根节点开始,依次访问每个子节点,判断对象是否在相机的视野范围内,是否需要渲染等。
      • 对于需要渲染的对象,渲染器会管理它们的渲染顺序,以确保正确的遮挡关系(例如,离相机近的物体遮挡离相机远的物体)。同时,渲染器还会处理对象的更新和删除操作,例如,当一个新的物体添加到场景中时,渲染器会将其纳入下一次渲染循环的考虑范围;当一个物体从场景中删除时,渲染器会停止对其渲染。

    材质系统

    1. Three.js材质系统介绍
    • 材质的基本概念
      • 在Three.js中,材质(Materials)决定了3D物体表面的外观特性。它就像是物体的“皮肤”,定义了物体看起来是什么样子,包括颜色、纹理、透明度、光泽度、反射率等诸多属性。例如,一个红色的、有光泽的、带有木纹纹理的球体,其外观就是由材质来定义的。
    • 材质的类型
      • MeshBasicMaterial:这是一种基础的材质类型。它不考虑光照效果,物体的颜色是均匀分布的,比较简单直接。适用于创建简单的、不受光照影响的3D模型,如一些用于示意的几何形状。例如,在展示一个3D模型的结构框架时,可以使用MeshBasicMaterial,让模型以单一颜色显示,便于观察形状。
      • MeshLambertMaterial:基于兰伯特(Lambert)光照模型的材质。它会考虑漫反射光照,使物体表面能够根据光照方向和物体表面法线方向产生明暗变化,模拟出真实的光照效果。这种材质适合用于创建具有漫反射特性的物体,如室内场景中的墙壁、地面等,能够让这些物体在光照下呈现出自然的明暗过渡。
      • MeshPhongMaterial:在MeshLambertMaterial的基础上,增加了高光反射效果。它可以模拟出物体表面的高光区域,使物体看起来更加光滑和有光泽。常用于表现具有光泽表面的物体,如金属制品、玻璃制品等。例如,一个金属球体使用MeshPhongMaterial后,在光照下会有明显的高光亮点,增强了物体的真实感。
      • MeshStandardMaterial:这是一种基于物理的材质,它遵循物理规律来计算光照效果,包括漫反射、高光反射、环境光遮挡等。它提供了更真实的光照模拟,并且可以方便地设置材质的粗糙度(Roughness)和金属度(Metallic)等参数。在现代3D图形应用中,这种材质被广泛使用,例如在游戏场景中的高质量模型或者建筑可视化中的建筑材料模拟。
      • TextureMaterial:用于将纹理(Texture)应用到物体表面。纹理可以是一张图片(如木纹图片、大理石图片等)或者通过程序生成的图案。通过将纹理与合适的材质(如MeshBasicMaterial或MeshStandardMaterial)结合,可以让物体表面呈现出各种复杂的图案和细节。例如,将一张石头纹理的图片应用到一个立方体上,使其看起来像一个真实的石头方块。
    1. Three.js材质系统应用

      • 创建和应用基本材质
        • 以创建一个简单的红色立方体为例,首先需要创建一个几何体(如BoxGeometry),然后创建一个MeshBasicMaterial并设置颜色为红色(0xff0000),最后将几何体和材质组合成一个网格(Mesh)对象并添加到场景中。
        const geometry = new THREE.BoxGeometry();
        const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);
        
      • 应用光照相关材质
        • 当场景中有光源时,为了让物体能够正确地响应光照,需要使用光照相关的材质。例如,创建一个使用MeshPhongMaterial的球体,并添加点光源来照亮它。
        const sphereGeometry = new THREE.SphereGeometry();
        const sphereMaterial = new THREE.MeshPhongMaterial({color: 0x00ff00});
        const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        scene.add(sphere);
        const pointLight = new THREE.PointLight(0xffffff, 1, 100);
        pointLight.position.set(0, 0, 5);
        scene.add(pointLight);
        
        • 在这个例子中,球体的材质MeshPhongMaterial会根据点光源的位置和强度,以及球体自身的表面法线方向,计算出每个片元(像素)的颜色,从而呈现出高光和漫反射等光照效果。
      • 应用纹理材质
        • 要应用纹理材质,首先需要加载纹理图片。可以使用THREE.TextureLoader来加载纹理,然后将纹理应用到合适的材质上。例如,将一张地球纹理图片应用到一个球体上,使其看起来像地球。
        const textureLoader = new THREE.TextureLoader();
        const earthTexture = textureLoader.load('earth.jpg');
        const earthGeometry = new THREE.SphereGeometry();
        const earthMaterial = new THREE.MeshBasicMaterial({map: earthTexture});
        const earth = new THREE.Mesh(earthGeometry, earthMaterial);
        scene.add(earth);
        
        • 在这里,MeshBasicMaterialmap属性用于指定要应用的纹理。当渲染这个球体时,纹理图片中的像素颜色会根据球体表面的纹理坐标映射到球体表面的片元上,从而让球体看起来像地球的样子。

    着色器

    1. 着色器的基本概念
      - 在Three.js中,着色器(Shader)是运行在GPU(图形处理器)上的小程序,它们对于创建高质量、高性能的3D图形至关重要。着色器主要分为顶点着色器(Vertex Shader)和片元着色器(Fragment Shader),它们在图形渲染管线(Graphics Rendering Pipeline)中发挥不同的作用。
      - 整个渲染过程可以看作是一个数据处理流水线,着色器就像是流水线上的工人,对3D模型的数据进行加工处理。从原始的3D模型顶点数据和其他属性开始,经过顶点着色器的处理,再到片元着色器确定每个像素(片元)的最终颜色,最终生成可以在屏幕上显示的2D图像。

    2. 顶点着色器(Vertex Shader)

      • 主要作用
        • 顶点位置变换:顶点着色器负责将3D模型的顶点从模型空间(物体自身的局部坐标系)转换到世界空间(整个3D场景的坐标系),再转换到视图空间(相机坐标系),最后转换到裁剪空间(用于确定哪些顶点在相机的可视范围内)。这一系列的变换通常是通过矩阵乘法来实现的。例如,通过一个4x4的模型视图投影矩阵(Model - View - Projection Matrix,简称MVP矩阵)来一次性完成这些变换。
        • 顶点属性计算与传递:它还可以计算和修改顶点的其他属性,如顶点的法线向量(用于光照计算)、纹理坐标等,并将这些属性传递给下一个阶段(通常是片元着色器)。例如,可以根据顶点的位置来调整其颜色,或者对顶点的法线向量进行空间转换。
      • 代码示例与解释
        • 以下是一个简单的顶点着色器代码片段:
          // 定义一个变量,用于将顶点法线向量传递给片元着色器
          varying vec3 vNormal;
          void main() {// 将顶点法线从模型空间转换到视图空间并归一化vNormal = normalize(normalMatrix * normal);// 计算顶点在裁剪空间中的位置gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
          }
          
        • 在这个代码中,vNormal是一个varying变量,它可以在顶点着色器和片元着色器之间传递数据。main函数是顶点着色器的入口点。normalize(normalMatrix * normal)部分是将顶点法线从模型空间转换到视图空间并进行归一化处理,其中normalMatrix是法线矩阵,normal是顶点的原始法线向量。gl_Position是一个特殊的内置变量,用于存储经过一系列变换后的顶点在裁剪空间中的位置,projectionMatrix * modelViewMatrix * vec4(position, 1.0)这一系列乘法运算实现了将顶点位置从模型空间转换到裁剪空间的操作,projectionMatrix是投影矩阵,modelViewMatrix是模型视图矩阵,vec4(position, 1.0)将顶点位置转换为齐次坐标形式。
    3. 片元着色器(Fragment Shader)

      • 主要作用
        • 颜色计算与纹理映射:片元着色器的主要任务是为每个片元(可以简单理解为像素)确定最终的颜色。这可以通过多种方式实现,例如根据从顶点着色器传递过来的属性(如颜色、法线等)进行光照计算,以确定片元在光照环境下的颜色。同时,片元着色器还用于纹理映射,即将纹理图像中的像素颜色应用到片元上。例如,对于一个带有木材纹理的3D模型,片元着色器会根据模型表面的纹理坐标,从木材纹理图像中获取相应的像素颜色,并将其应用到模型表面的片元上。
        • 高级效果实现:它还可以用于实现各种高级的图形效果,如透明效果、反射效果、阴影效果等。例如,通过在片元着色器中计算光线反射的方向和强度,可以在模型表面模拟出反射效果,让模型看起来像是反射了周围环境的光线。
      • 代码示例与解释
        • 以下是一个简单的片元着色器代码片段,用于简单的光照计算:
          // 接收从顶点着色器传递过来的顶点法线向量
          varying vec3 vNormal;
          void main() {// 定义一个简单的光照方向(假设光从正前方照射)vec3 lightDir = vec3(0.0, 0.0, 1.0);// 计算法线向量和光照方向的点积,用于确定光照强度float diff = max(dot(vNormal, lightDir), 0.0);// 根据光照强度计算片元的RGB颜色值,并设置透明度为1(不透明)gl_FragColor = vec4(diff, diff, diff, 1.0);
          }
          
        • 在这个代码中,vNormal是从顶点着色器传递过来的顶点法线向量。lightDir定义了一个简单的光照方向(这里假设光从正前方(0, 0, 1)方向照射)。dot(vNormal, lightDir)计算了法线向量和光照方向的点积,用于确定光照强度。max(dot(vNormal, lightDir), 0.0)确保光照强度不会为负数(因为光照强度最小为0)。gl_FragColor是一个特殊的内置变量,用于存储片元的最终颜色。vec4(diff, diff, diff, 1.0)根据光照强度计算出片元的RGB颜色值,并设置透明度为1(不透明)。
    4. 着色器的使用流程

      • 编写着色器代码:首先需要使用GLSL(OpenGL Shading Language)编写顶点着色器和片元着色器代码,GLSL是一种专门用于编写着色器程序的高级编程语言,它与C语言有相似的语法结构。
      • 创建着色器对象并编译:在Three.js中,需要将编写好的着色器代码创建为着色器对象,并进行编译。例如,可以使用THREE.ShaderMaterial来创建一个使用自定义着色器的材质。在这个过程中,Three.js会将GLSL代码传递给GPU进行编译,如果代码有错误,会在控制台显示编译错误信息。
      • 应用着色器材质到物体上:编译成功后的着色器可以通过ShaderMaterial应用到3D物体上。将ShaderMaterial与几何体组合成一个网格(Mesh)对象,然后添加到场景中,这样在渲染场景时,物体就会按照着色器代码所定义的方式进行渲染。例如,通过自定义的着色器可以实现一些特殊的图形效果,如卡通渲染效果、风格化渲染效果等。

Three.js着色器的具体实例

示例一:简单的颜色渐变效果

  1. 顶点着色器代码
varying vec3 vColor;void main() {// 获取顶点的y坐标值,范围是从-1到1(假设模型在标准的归一化空间)float y = position.y;// 根据y坐标值在0到1之间进行映射,生成一个渐变因子float t = (y + 1.0) / 2.0;// 定义起始颜色和结束颜色vec3 startColor = vec3(1.0, 0.0, 0.0); // 红色vec3 endColor = vec3(0.0, 0.0, 1.0); // 蓝色// 根据渐变因子线性插值计算顶点的颜色vColor = mix(startColor, endColor, t);// 进行常规的顶点位置变换gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

在这个顶点着色器中,我们首先获取顶点的y坐标值,并将其映射到01的范围,得到一个渐变因子t。然后根据定义的起始颜色(红色)和结束颜色(蓝色),通过线性插值函数mix计算出每个顶点的颜色vColor,最后进行顶点位置的常规变换。

  1. 片元着色器代码
varying vec3 vColor;void main() {// 将顶点颜色直接赋给片元颜色,实现颜色渐变效果gl_FragColor = vec4(vColor, 1.0);
}

片元着色器很简单,只是将从顶点着色器传递过来的顶点颜色vColor直接赋给片元颜色gl_FragColor,这样在渲染时就能看到物体表面呈现出从红色到蓝色的颜色渐变效果。

  1. 应用到物体上
// 创建一个几何体,这里以球体为例
const geometry = new THREE.SphereGeometry();
// 创建一个使用自定义着色器的材质
const material = new THREE.ShaderMaterial({vertexShader: document.getElementById('vertexShader').textContent,fragmentShader: document.getElementById('fragmentShader').textContent
});
// 创建一个网格对象,将几何体和材质组合起来
const sphere = new THREE.Mesh(geometry, material);
// 将网格对象添加到场景中
scene.add(sphere);

在这里,我们先创建了一个球体几何体,然后通过ShaderMaterial创建了一个使用自定义着色器的材质,将编写好的顶点着色器和片元着色器代码(假设存储在HTML页面的idvertexShaderfragmentShader的元素中)赋给该材质。最后将组合好的网格对象添加到场景中,渲染后就能看到球体呈现出颜色渐变效果。

示例二:模拟水面波动效果

  1. 顶点着色器代码
varying vec3 vNormal;
varying vec3 vPosition;void main() {// 获取原始顶点法线向量vNormal = normal;// 获取原始顶点位置vPosition = position;// 定义一个时间变量,用于模拟波动随时间变化float time = 0.5 * iGlobalTime;// 定义波动的频率和振幅float frequency = 2.0;float amplitude = 0.1;// 根据顶点的x和z坐标以及时间,计算波动偏移量float offset = amplitude * sin(frequency * (vPosition.x + vPosition.z + time));// 对顶点位置进行垂直方向的偏移,模拟水面波动position.y += offset;// 进行常规的顶点位置变换gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

在这个顶点着色器中,我们首先获取顶点的法线向量和位置向量并传递给片元着色器。然后定义了一个时间变量(假设iGlobalTime是由外部传入的全局时间变量,可通过Three.js的动画循环机制来提供),以及波动的频率和振幅。接着根据顶点的xz坐标以及时间,计算出波动偏移量,并对顶点位置进行垂直方向的偏移,以模拟水面波动效果,最后进行顶点位置的常规变换。

  1. 片元着色器代码
varying vec3 vNormal;
varying vec3 vPosition;void main() {// 定义一个基础颜色,这里假设为浅蓝色vec3 baseColor = vec3(0.2, 0.5, 0.8);// 根据顶点法线向量计算光照强度,简单模拟光照效果float diff = max(dot(vNormal, vec3(0.0, 1.0, 0.0)), 0.0);// 根据光照强度调整颜色vec3 color = baseColor * diff;// 将调整后的颜色赋给片元颜色gl_FragColor = vec4(color, 1.0);
}

片元着色器中,我们首先定义了一个基础颜色(浅蓝色),然后根据从顶点着色器传递过来的顶点法线向量,简单模拟光照效果,通过计算顶点法线向量与一个假设的光照方向(垂直向上)的点积来确定光照强度,并根据光照强度调整颜色,最后将调整后的颜色赋给片元颜色。

  1. 应用到物体上
// 创建一个几何体,这里以平面几何体为例,模拟水面
const geometry = new THREE.PlaneGeometry(10, 10);
// 创建一个使用自定义着色器的材质
const material = new THREE.ShaderMaterial({vertexShader: document.getElementById('vertexShader').textContent,fragmentShader: document.getElementById('fragmentShader').textContent
});
// 创建一个网格对象,将几何体和材质组合起来
const plane = new THREE.Mesh(geometry, material);
// 将网格对象添加到厅子中
scene.add(plane);

在这里,我们先创建了一个平面几何体来模拟水面,然后通过ShaderMaterial创建了一个使用自定义着色器的材质,将编写好的顶点着色器和片元着色器代码(假设存储在HTML页面的idvertexShaderfragmentShader的元素中)赋给该材质。最后将组合好的网格对象添加到场景中,渲染后就能看到平面呈现出模拟水面波动且有简单光照效果的画面。

示例三:卡通渲染效果

  1. 顶点着色器代码
varying vec3 vNormal;void main() {// 将顶点法线从模型空间转换到视图空间并归一化vNormal = normalize(normalMatrix * normal);// 进行常规的顶点位置变换gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

这个顶点着色器主要进行常规的顶点位置变换以及将顶点法线从模型空间转换到视图空间并归一化,为片元着色器提供处理的数据。

  1. 片元着色器代码
varying vec3 vNormal;void main() {// 定义一个简单的光照方向,假设光从正前方照射vec3 lightDir = vec3(0.0, 0.0, 1.0);// 计算法线向量和光照方向的点积,用于确定光照强度float diff = max(dot(vNormal, lightDir), 0.0);// 将光照强度进行离散化处理,使其只有0或1两种值,模拟卡通效果if (diff > 0.5) {diff = 1.0;} else {diff = 0.0;}// 定义一个基础颜色,这里假设为黄色vec3 baseColor = vec3(1.0, 1.0, 0.0);// 根据离散化后的光照强度计算片元的RGB颜色值,并设置透明度为1(不透明)gl_FragColor = vec4(baseColor * diff, 1.0);
}

片元着色器中,首先根据从顶点着色器传递过来的顶点法线向量,计算出光照强度。然后将光照强度进行离散化处理,使其只有0或1两种值,这样就模拟出了卡通效果。接着定义一个基础颜色(黄色),根据离散化后的光照强度计算片元的RGB颜色值,并设置透明度为1(不透明)。

  1. 应用到物体上
// 创建一个几何体,这里以立方体为例
const geometry = new THREE.BoxGeometry();
// 创建一个使用自定义着色器的材质
const material = new THREE.ShaderMaterial({vertexShader: document.getElementById('vertexShader').textContent,fragmentShader: document.getElementById('fragmentShader').textContent
} );
// 创建一个网格对象,将几何体和材质组合起来
const cube = new THREE.Mesh(geometry, material);
// 将网格对象添加到场景中
scene.add(cube);

在这里,我们先创建了一个立方体几何体,然后通过ShaderMaterial创建了一个使用自定义着色器的材质,将编写好的顶点着色器和片元着色器代码(假设存储在HTML页面的id为vertexShaderfragmentShader的元素中)赋给该材质。最后将组合好的网格对象添加到场景中,渲染后就能看到立方体呈现出卡通渲染效果。

着色器 函数语法简要理解

  1. GLSL函数基础语法介绍

    • 函数定义
      • 在GLSL(OpenGL Shading Language,用于编写着色器的语言)中,函数定义的基本格式如下:
        返回值类型 函数名(参数列表) {// 函数体return 返回值;
        }
        
      • 例如,定义一个简单的函数来计算两个浮点数的和:
        float add(float a, float b) {return a + b;
        }
        
      • 这里float是返回值类型,表示函数返回一个浮点数。add是函数名,(float a, float b)是参数列表,函数体中通过return a + b返回两个参数相加的结果。
    • 变量声明与作用域
      • 在函数内部声明变量时,需要指定变量的类型。变量的作用域通常限定在声明它的函数内部。例如:
        void myFunction() {float localVariable;localVariable = 3.0;
        }
        
      • 这里localVariable是在myFunction函数内部声明的一个浮点数变量,它的作用域仅限于myFunction函数内部,在函数外部无法访问这个变量。
    • 数据类型
      • GLSL支持多种数据类型,如float(单精度浮点数)、vec2(二维向量,通常用于存储二维坐标或纹理坐标等)、vec3(三维向量,可用于表示颜色、顶点位置等)、vec4(四维向量)、mat2(2x2矩阵)、mat3(3x3矩阵)、mat4(4x4矩阵)等。
      • 例如,声明一个三维向量来表示颜色:
        vec3 color = vec3(1.0, 0.0, 0.0); // 表示红色
        
    • 基本运算与操作符
      • GLSL支持常见的算术运算(如+-*/)、关系运算(如><>=<===!=)和逻辑运算(如&&||!)。
      • 例如,在一个函数中比较两个浮点数并返回一个布尔值:
        bool compareFloats(float a, float b) {return a > b;
        }
        
  2. 函数在着色器中的运用

    • 顶点着色器中的运用

      • 顶点位置变换:可以编写函数来进行顶点位置的变换。例如,将顶点位置绕某一轴旋转一定角度。以下是一个简单的绕y轴旋转顶点位置的函数:
        mat4 rotateY(float angle) {float c = cos(angle);float s = sin(angle);return mat4(c, 0.0, s, 0.0,0.0, 1.0, 0.0, 0.0,-s, 0.0, c, 0.0,0.0, 0.0, 0.0, 1.0);
        }
        void main() {// 假设angle是一个外部传入的旋转角度mat4 rotationMatrix = rotateY(angle);gl_Position = projectionMatrix * modelViewMatrix * rotationMatrix * vec4(position, 1.0);
        }
        
      • 在这个例子中,rotateY函数根据传入的角度angle构建一个绕y轴旋转的4x4矩阵,然后在main函数中,将这个旋转矩阵应用到顶点位置变换中,实现顶点绕y轴旋转的效果。
      • 顶点属性计算与传递:编写函数来计算顶点属性也是常见的用法。例如,根据顶点位置计算顶点颜色,使颜色在顶点之间产生渐变效果。
        varying vec3 vColor;
        vec3 calculateColor(vec3 position) {// 根据顶点的y坐标计算颜色float t = (position.y + 1.0) / 2.0;return mix(vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), t);
        }
        void main() {vColor = calculateColor(position);gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
        
      • 这里calculateColor函数根据顶点位置的y坐标计算出一个颜色,通过线性插值函数mix在红色和蓝色之间进行渐变。在main函数中,调用calculateColor函数计算顶点颜色并存储到vColor变量中,然后将其传递给片元着色器。
    • 片元着色器中的运用

      • 颜色计算与纹理映射:在片元着色器中,可以编写函数来进行更复杂的颜色计算。例如,实现一个带有阴影效果的光照模型。
        varying vec3 vNormal;
        varying vec3 vPosition;
        vec3 calculateLighting(vec3 normal, vec3 position) {// 定义环境光强度vec3 ambientLight = vec3(0.2, 0.2, 0.2);// 定义一个点光源位置vec3 lightPosition = vec3(0.0, 3.0, 0.0);// 计算光照方向vec3 lightDir = normalize(lightPosition - position);// 计算漫反射光照强度float diff = max(dot(normal, lightDir), 0.0);// 计算最终颜色return ambientLight + diff * vec3(1.0, 1.0, 1.0);
        }
        void main() {vec3 color = calculateLighting(vNormal, vPosition);gl_FragColor = vec4(color, 1.0);
        }
        
      • 这个calculateLighting函数根据顶点法线向量vNormal和顶点位置vPosition计算光照效果。首先定义了环境光强度,然后计算从点光源到顶点的光照方向,接着计算漫反射光照强度,最后将环境光和漫反射光相加得到最终颜色。在main函数中,调用calculateLighting函数计算片元颜色并赋给gl_FragColor变量。
      • 高级效果实现:对于实现高级效果,如反射效果,可以编写函数来计算反射向量。
        varying vec3 vNormal;
        varying vec3 vPosition;
        vec3 calculateReflection(vec3 normal, vec3 viewDir) {return reflect(-viewDir, normal);
        }
        void main() {// 假设viewDir是一个从外部传入的观察方向向量vec3 reflectionDir = calculateReflection(vNormal, viewDir);// 根据反射方向进行后续的纹理查找或其他操作来实现反射效果//...
        }
        
      • 这里calculateReflection函数使用reflect函数(GLSL内置函数)计算反射向量。在main函数中,计算出反射方向后,可以根据这个反射方向进行纹理查找或者其他操作来实现反射效果,比如通过反射方向从反射纹理中获取颜色来模拟物体表面的反射。

相关文章:

Three.js 零基础+概念理解

文章目录 一、Three.js基础概念&#xff08;一&#xff09;什么是Three.js&#xff08;二&#xff09;核心对象&#xff08;三&#xff09;几何体&#xff08;Geometries&#xff09;和材质&#xff08;Materials&#xff09; 二、基础实例应用&#xff08;一&#xff09;创建一…...

c#使用COM接口设置excel单元格宽高匹配图片,如何计算?

c#使用COM接口设置excel单元格宽高如何换算 在实际工作中&#xff0c;经常需要在excel中插入图片。并设置单元格与图片对齐。但是excel单元格的宽度和高度使用不同的单位。单元格的宽度以字符宽度为单位&#xff0c;而高度以点为单位。如果按照实际值来设置&#xff0c;例如设…...

Excel模板下载\数据导出

pom <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version> </dependency><build><resources><resource><!--将xlsx打包到jar--><director…...

Vite初始化Vue3+Typescrpt项目

初始化项目 安装 Vite 首先&#xff0c;确保你的 Node.js 版本 > 12.0.0。然后在命令行中运行以下命令来创建一个 Vite Vue 3 TypeScript 的项目模板&#xff1a; npm init vitelatest进入项目目录 创建完成后&#xff0c;进入项目目录&#xff1a; cd vue3-demo启动…...

深入剖析【C++继承】:单一继承与多重继承的策略与实践,解锁代码复用和多态的编程精髓,迈向高级C++编程之旅

​​​​​​​ &#x1f31f;个人主页&#xff1a;落叶 &#x1f31f;当前专栏: C专栏 目录 继承的概念及定义 继承的概念 继承定义 定义格式 继承基类成员访问⽅式的变化 继承类模板 基类和派⽣类间的转换 继承中的作⽤域 隐藏规则 成员函数的隐藏 考察继承【作⽤…...

地级市能源消耗数据(2006至2021)含原始数据、计算过程、计算结果-最新出炉

能源消耗数据分析-2006-2021年地级市能源消耗数据&#xff08;原始数据计算过程结果&#xff09; 下载链接-点它&#x1f449;&#x1f449;&#x1f449;&#xff1a;https://download.csdn.net/download/qq_67479387/89911272 全国能源消耗概况 2021年&#xff0c;我国单位…...

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并

MySQL技巧之跨服务器数据查询&#xff1a;基础篇-A数据库与B数据库查询合并 上一篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的链接名: MY_ODBC_MYSQL 以…...

AutoSAR CP DoIP规范导读

主要功能和用途 诊断通信协议实现 遵循标准&#xff1a;遵循ISO 13400 - 2标准&#xff0c;实现了诊断通信在IP网络上的传输协议和网络层服务&#xff0c;包括数据封装、传输、路由等功能。 多种消息支持 车辆识别与公告&#xff1a;能够进行车辆识别请求和响应&#xff0c;…...

Window下PHP安装最新sg11(php5.3-php8.3)

链接: https://pan.baidu.com/s/10yyqTJdwH_oQJnQtWcwIeA 提取码: qz8y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 (链接失效联系L88467872) 1.下载后解压文件&#xff0c;将对应版本的ixed.xx.win文件放进php对应的ext目录下&#xff0c;如图所示 2.修改ph…...

2024华为OD机试真题---中文分词模拟器

华为OD机试中的中文分词模拟器题目&#xff0c;通常要求考生对给定的不包含空格的字符串进行精确分词。这个字符串仅包含英文小写字母及英文标点符号&#xff08;如逗号、分号、句号等&#xff09;&#xff0c;同时会提供一个词库作为分词依据。以下是对这类题目的详细解析 一…...

Kubernetes网络揭秘:从DNS到核心概念,一站式综述

文章目录 一.overlay vs underlayL2 underlayL3 underlay 二、calico vs flannel2.1 calico架构2.2 flannel架构 三、iptables四、Vxlan五、kubernetes网络架构综述六、DNS七、Kubernetes域名解析策略 一.overlay vs underlay overlay网络是在传统网络上虚拟出一个虚拟网络&am…...

C#封装EPPlus库为Excel导出工具

1&#xff0c;添加NUGet包 2&#xff0c;封装工具类 using OfficeOpenXml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection;namespace GMWPF.utils {public class ExcelUtil<T>{/// <summary>///…...

【LeetCode】【算法】461. 汉明距离

LeetCode 461. 汉明距离 题目描述 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y&#xff0c;计算并返回它们之间的汉明距离。 思路 思路&#xff1a;将两个数转成二进制后求异或结果&#xff0c;就是它们之间的汉明距离。…...

Docker Compose部署Rabbitmq(延迟插件已下载)

整个工具的代码都在Gitee或者Github地址内 gitee&#xff1a;solomon-parent: 这个项目主要是总结了工作上遇到的问题以及学习一些框架用于整合例如:rabbitMq、reids、Mqtt、S3协议的文件服务器、mongodb github&#xff1a;GitHub - ZeroNing/solomon-parent: 这个项目主要是…...

生信技能62 - 常用机器学习算法的R语言实现

1. 加载R包和数据 # 安装R包, 是否update统一选择不更新n BiocManager::install("caret") BiocManager::install("randomForest") BiocManager::install("gbm") BiocManager::install("kernlab") BiocManager::install("glmnet…...

【3D Slicer】的小白入门使用指南二

3D Slicer中DICOM数据加载和三维可视化 任务 数据集下载和解压缩 加载和查看DICOM数据 1)将第一个数据集文件夹,整个往3Dslicer左侧拖动即可 得到 2)选中右侧patient 1就可显示出该患者的基本信息 (第二行蓝色是研究信息;第三行蓝色是序列信息)...

部署搭建AI相关项目时,不用魔法也能轻松自动下载所需大模型

背景 最近搭建了许多AI相关的自动化服务&#xff0c;有些时候因为国内服务器墙了 huggingface.co 访问&#xff0c;导致一些依赖文件和模型下载不下来&#xff0c;手动去下载又特别麻烦&#xff0c;今天教你一个小招&#xff0c;轻松解决这个问题 开搞 1&#xff1a;首先确定…...

zookeeper之节点基本操作

ZooKeeper是一个分布式协调服务,它的节点操作包括创建、查询、更新、删除等,以下是ZooKeeper节点的基本操作介绍: 1. 创建节点 持久节点(Persistent Node) 含义:持久节点是ZooKeeper中最基本的节点类型。创建后,除非显式删除,否则它将一直存在于ZooKeeper树中,即使创…...

技术最好 ≠ 最适合:数字化转型切忌盲目追求最先进的技术

企业引入新兴技术时面临的挑战 企业在引入新兴技术时会面临一定挑战&#xff0c;根据调查结果显示&#xff0c;企业在引入新兴技术时做出决策的三个最重要考量因素分别是&#xff1a; 价格与投资回报 新兴技术成熟度 新兴技术与业务的适配性 不要盲目追求最先进的技术 企业…...

数字IC后端教程之Innovus hold violation几大典型问题

今天小编给大家分享下数字IC后端实现Physical Implementation过程中经常遇到的几个hold violation问题。每个问题都是小编自己在公司实际项目中遇到的。 数字后端实现静态时序分析STA Timing Signoff之min period violation Q1: 在Innouvs postCTS时序优化的log中我们经常会看…...

rust并发

文章目录 Rust对多线程的支持std::thread::spawn创建线程线程与 move 闭包 使用消息传递在线程间传送数据std::sync::mpsc::channel()for received in rx接收两个producer 共享状态并发std::sync::Mutex在多个线程间共享Mutex&#xff0c;使用std::sync::Arc 参考 Rust对多线程…...

力扣 最小路径和

又是一道动态规划基础例题。 题目 这道题可以类似不同路径。先把左上角格子进行填充&#xff0c;然后用一个数组去更新每走到一个格的数字总和&#xff0c;首先处理边界问题&#xff0c;把最左边的列只能由上方的行与原来的格子数值的和&#xff0c;同理&#xff0c;最上方的行…...

Scala中的可变Map操作:简单易懂指南 #Scala Map #Scala

引言 在编程中&#xff0c;Map是一种常见的数据结构&#xff0c;用于存储键值对。Scala提供了不可变Map和可变Map两种类型&#xff0c;它们在处理数据时有不同的特性和用途。本文将通过一个简单的示例&#xff0c;带你了解Scala中可变Map的基本操作&#xff0c;包括添加元素、…...

【go从零单排】XML序列化和反序列化

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在 Go 语言中&#xff0c;处理 XML 数据主要使用 encoding/xml 包。这个包提供了…...

在 Oracle Linux 8.9 上安装Oracle Database 23ai 23.5

在 Oracle Linux 8.9 上安装Oracle Database 23ai 23.5 1. 安装 Oracle Database 23ai2. 连接 Oracle Database 23c3. 重启启动后&#xff0c;手动启动数据库4. 重启启动后&#xff0c;手动启动 Listener5. 手动启动 Pluggable Database6. 自动启动 Pluggable Database7. 设置开…...

在 Ubuntu 上安装 `.deb` 软件包有几种方法

在 Ubuntu 上安装 .deb 软件包有几种方法&#xff0c;可以使用命令行工具&#xff0c;也可以通过图形界面进行安装。以下是几种常见的安装方法&#xff1a; 方法 1&#xff1a;使用 dpkg 命令安装 .deb 包 打开终端。 使用 dpkg 命令安装 .deb 包&#xff1a; sudo dpkg -i /…...

一文了解Android本地广播

在 Android 开发中&#xff0c;本地广播&#xff08;Local Broadcast&#xff09;是一种轻量级的通信机制&#xff0c;主要用于在同一应用进程内的不同组件之间传递消息&#xff0c;而无需通过系统的全局广播机制。这种方法既可以提高安全性&#xff08;因为广播仅在应用内传播…...

Ingress nginx 公开TCP服务

文章目录 背景搞起拓展( PROXY Protocol )参考 背景 公司业务繁多&#xff0c; HTTP、GRPC、TCP多种协议服务并存&#xff0c;Kubernetes流量入口复杂&#xff0c;所以萌生了通过LoadBalancer Ingress-nginx 的方式完全的结果入口流量&#xff0c;当然在高并发的场景下可以对…...

谷歌浏览器支持的开发者工具详解

谷歌浏览器&#xff08;Google Chrome&#xff09;是全球最受欢迎的网页浏览器之一&#xff0c;它不仅提供了快速、安全的浏览体验&#xff0c;还为开发者提供了强大的开发者工具。本文将详细介绍如何使用谷歌浏览器的开发者工具&#xff0c;并解答一些常见问题。&#xff08;本…...

【数据结构】汇编 、机器语言 高级语言 简析。

汇编语言、机器语言和高级语言 1. 机器语言&#xff08;Machine Language&#xff09; 定义&#xff1a;机器语言是计算机能够直接执行的、用二进制编码的指令集&#xff0c;属于最低级别的编程语言。它由 0 和 1 组成&#xff0c;每条指令由一串二进制数表示。机器语言与计算…...