Orillusion

    • 注册
    • 登录
    • 搜索
    • 版块
    • 最新
    • 标签

    Orillusion入门心得系列(一. 学前准备)

    中文社区
    国产引擎测评系列2
    3
    4
    332
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • B
      betty 最后由 shuangliu 编辑

      引言

      说起WebGPU 3D引擎,我自己在学习之前是一个纯小白懵懵的概念,只感觉3D引擎是一个很深奥的东西,完全不知道如何上手。简单查阅一些资料,会发现它涉及WebGPU机制、图形学、线代等很广很深的知识,自己在短时间内很难去掌握。这时候,我就希望能通过一些简单的示例,去了解整个引擎都有哪些功能,自己能够利用引擎去实现哪些东西。这个系列文章就是想分享一下自己的学习心得,希望让和我一样的零基础同学可以快速上手使用引擎,并了解想要深入学习的话,可以查阅哪些方面的资料。

      第一期分享主要聊聊上手 Orillusion 引擎的学前准备。万事开头难,在懵懂的情况下有一个大致的知识体系梳理,和开发环境搭建,能够帮助新手快速入门。

      我们主要从三个角度出发:环境搭建,前端基础,以及引擎帮助开发者做了什么。希望通过这些简单的介绍,让新入门的朋友可以对使用引擎开发实战项目有一个大体的概念和准备。

      1. 环境搭建

      1.1 安装Chrome Canary浏览器

      WebGPU还没有正式发布,对于大家比较常用的Chrome浏览器,目前只在Canary中支持,所以我们需要下载并安装Chrome Canary版本。

      安装完成后,我们还需要开启浏览器的webgpu特性,步骤如下:
      1)打开Chrome Canary,在上方搜索栏里输入chrome://flags/
      2)搜索 Unsafe WebGPU 选项
      3)将其设置为 Enabled

      c7ae164b-15fd-46fe-b723-41491446e63c-image.png

      1.2 挑选一款喜欢的编辑器

      开发项目需要一个编辑器来编辑代码源文件。
      除了提供编写环境,编辑器通常还可以帮助开发者提供语法高亮、语法检查等功能。
      前端开发常用的编辑器/IDE有 VSCode、Sublime、Atom、WebStorm等。
      在这里我非常推荐使用 VSCode 作为实战项目的编辑器。相较于 Sublime 的插件化,VSCode 集成了更多的类似于IDE的功能,同时也提供了非常多的插件可供功能扩展。Atom 是一款基于HTML的开源编辑器,其本身就带有类似浏览器的调试功能,感兴趣的同学可以尝试使用。WebStorm 则是一款集成式的IDE,也有其特定用户群。

      1.3 创建基本的引擎程序

      完成这两步,就可以创建基本的引擎程序了。
      首先,在VSCode里新建一个index.html文件,然后通过script标签引入 Orillusion 引擎库。方式有两种:
      1)全局引入

      <script src="https://unpkg.com/@orillusion/core/dist/orillusion.umd.js"></script>
      

      通过以下任一方式引入类:

      <script>
        const { Engine3D, Camera3D } = Orillusion
      </script>
      

      或

      <script>
        Orillusion.Engine3D ...
      </script>
      

      2)以 ES Module 的方式导入

      全局引入js变量的加载方式,存在很多缺陷,比如容易造成全局作用域变量命名冲突等。随着ES6的发展,ES Module 的概念被官方提出,用以模块管理。Module允许每个js文件以模块的形式 export 变量或 import 来自其他模块的输出变量。以script标签形式载入ES Module,需要添加 type="importmap" 并使用 imports 引入的对应的 js 库,示例如下:

      <script type="importmap">
      {
        "imports": {
          "Orillusion": "https://unpkg.com/@orillusion/core/dist/orillusion.es.js"
        }
      }
      </script>
      

      加载js库后,与全局引入的方式类似,我们需要引入开发时所用到的类。
      我们可以通过以下任一方式引入类:

      <script type="module">
        import { Engine3D, Camera3D } from 'Orillusion'
      </script>
      

      或

      <script type="module">
        import * as Orillusion from 'Orillusion'
      </script>
      

      接下来,我们就可以进行开发了,写好代码后,只需要在Canary浏览器中打开index.html,就可以看到运行效果。

      1.4 进阶:Node.js与前端构建工具

      对于大一些的项目,开发者通常需要用到多个库,文件结构也比较复杂,仅用传统html/js文件进行编辑开发显得效率不足,甚至有时候不启用本地服务器,在资源加载时还可能出现跨域的问题。这时候,Node.js 是帮助用户开发的一大利器。

      Node.js 是一个基于javascript的运行环境,与我们常在浏览器中运行的js脚本不同,Node.js提供了许多服务器端的功能。Node.js还有一个配套的包管理工具,NPM (Node Package Manager)。js库打包发布到npm上,开发者可以利用npm命令进行包的下载安装,并利用脚本实现项目的构建与启动。在开发模式下,npm管理的前端项目可以利用Node.js启动本地服务器,以托管html/js/css以及资源文件,开发者只需在浏览器中打开本地服务器地址,即可看到程序运行效果。

      Node.js 需要在官网 https://nodejs.org/ 下载,下载时会自动安装 npm。
      Node.js 版本在不断更新,有时新老版本会不兼容,如果需要进行版本管理,需要另行安装 nvm

      安装完Node.js, 我们即可以新建npm项目。
      打开命令行,进入项目目录,可以通过如下指令安装Orillusion库:

      npm install @Orillusion/core --save
      

      安装好Node.js之后,我们还需要选择一款前端构建工具,帮助我们构建前端项目。构建流程包括编译、打包、压缩资源等环节,简而言之,即以自动化的方式帮助开发者整合项目资源。目前常用的前端构建工具有 vite 和 webpack。这里我们选择 vite 进行详细一些的介绍:

      在命令行中输入如下指令,可以快速构建一个 vite 项目:

      npm create vite@latest
      

      对于初学者,我们无需选择任何框架,可以选择基于原生的 Vanilla (香草 - 原生JS) 模版进行开发学习:

      Screen Shot 2022-09-11 at 21.42.14.png

      创建后,我们可以看到在项目根目录下有一个vite.config.js 文件,它包含 vite 的配置信息,包括本地服务器端口信息,插件配置等等,是比较关键的文件。

      在 package.json 中,我们可以定义简单的启动、打包脚本,vite 脚手架会帮助我们自动创建这个文件:

      {
        "scripts": {
          "dev": "vite", // 启动开发服务器
          "build": "vite build", // 为生产环境构建产物
          "preview": "vite preview" // 本地预览生产构建产物
        }
      }
      

      在命令行中输入如下指令,即可启动本地开发服务器:

      npm install
      npm run dev
      

      Vite 会帮我们启动一个开发服务器,管理所有模块加载和依赖,在程序中,我们即可通过以下方式导入 Orillusion 的引擎模块:

      import { Engine3D, Camera3D } from '@Orillusion/core'
      

      或

      import * as Orillusion from '@Orillusion/core'
      

      2. 前端基础

      基于WebGPU的3D引擎同其他前端项目一样,是运行在浏览器环境中的程序,使用引擎开发实际项目,也需要了解一些前端基础概念。

      2.1 JavaScript, CSS, HTML

      在浏览器中运行的前端项目,通常由三部分构成:
      html文件负责页面结构与组件渲染,js负责交互与逻辑程序的编写,css负责样式展示。

      在前端3D项目中,通常来讲,逻辑程序占据主要的地位,所以先来讲讲 js。js,全称 JavaScript, 是一种可以运行于浏览器中的脚本语言。类似大多数编程语言,js拥有条件、循环等基础语法以实现常用算法逻辑,与此同时,js提供了大量与网页交互api,可以用来创建动态更新的内容,控制多媒体,制作图像动画等。详细介绍见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript。

      另外,值得一提的是,Orillusion 引擎是用 ts(typescript)来编写的。Typescript 可以理解为js的超集,除了支持js语法外,还增加了类型定义的句法。我们推荐开发者尝试使用ts来开发程序,使用ts在编译时即可检查类型传递是否一致,可以有效避免在传统js中因弱类型而出现的许多坑。

      HTML,全称 HyperText Markup Language,是一种标记语言,用来结构化我们的网页内容并赋予内容含义,例如定义段落、标题和数据表,或在页面中嵌入图片和视频。HTML提供了大量标签供用户定义网页构成,比如div,span,button等。更多HTML介绍见 https://developer.mozilla.org/zh-CN/docs/Web/HTML。

      CSS 是一种样式规则语言,可将样式应用于 HTML 内容,例如设置背景颜色和字体,在多个列中布局内容。css可以通过id、类、标签来选择元素,并为所选元素设置相应的样式。使用CSS可以方便地定义文档中同类节点的样式,而无需额外的工作。同时css也支持动画的设定。更多CSS介绍见https://developer.mozilla.org/zh-CN/docs/Web/CSS。

      2.2 Canvas, WebGL, WebGPU

      上一小节中我们介绍了传统前端项目的“三件套”,但很多同学可能会感觉,这些内容与3D项目开发,关系似乎不是很大。这一小节中我们就详细介绍一下和3D开发息息相关的前端知识。

      canvas,顾名思义,是一个由HTML定义的画布标签,该标签可以在浏览器页面中创建一张画布,而我们的3D画面,就是渲染在这张画布上的。

      创建 canvas 标签很容易,比如,可以在HTML文件中定义:

      <canvas id="canvas" width="150" height="150"></canvas>
      

      也可以通过js的方式添加:

      let canvas = document.createElement('canvas');
      document.body.appendChild(canvas);
      

      我们可以通过如下方式获取指定id的canvas:

      let canvas = document.getElementById('canvas');
      

      canvas的绘制或渲染是在其上下文中进行的,我们可以由 getContext 方法获取 canvas 对应的上下文,进而对画布进行绘制。

      let ctx = canvas.getContext(contextType, contextAttributes);
      

      其中,contextType决定了该上下文对应的类型,而我们常说的webgl,webgpu,在这里都是单独的上下文类型,也就是说,只有获取到特定类型的上下文,才能使用该上下文提供的绘制、渲染api。
      比如说,获取 webgpu 上下文,可以通过如下方法:

      const context = canvas.getContext('webgpu');
      

      对于上下文获取的介绍可以见 https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/getContext
      特别地,对于 WebGPU 上下文获取的介绍可以见 https://www.w3.org/TR/webgpu/#gpucanvascontext

      目前大多数前端3D项目都是以webgl标准进行渲染的。而webgpu则是W3C正在编写的新一代基于GPU渲染的Web图形api,目前还在试验性阶段。webgpu与webgl类似,都定义了一套web端的图形API,并暴露了GPU硬件的功能。

      有关webgpu与webgl更详细的介绍可以参考如下网站:
      WebGPU: https://www.w3.org/TR/webgpu/#intro
      WebGL: https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API

      3. 引擎帮助开发者做了些什么

      将话题回到引擎本身:为什么开发者通常喜欢使用一个引擎来帮助其开发项目呢?
      很直观的答案是,从底层从零到一的搭建3D项目是一件很复杂的事,其技术门槛与耗时都使大多数开发者更倾向于使用封装好的引擎来实现开发,帮助提升开发效率。
      这么说多少有些抽象,那么我们来看看引擎到底帮助开发者做了哪些工作:

      一. 图形流水线的封装

      底层图形API包含一系列图形流水线的逻辑编写,比如编写顶点着色器、片元着色器等,其中通常包含物体的模型变换、透视变换等复杂数学计算,以及实现材质效果的复杂光照计算。引擎将这些内容抽象出来,为开发者写好了底层逻辑,提供易于理解的api及通用参数供开发者调用修改。

      二. 3D项目中常用功能的封装

      引擎提供了3D项目中常用的功能模块,比如资源加载,物理,动画等等。这些功能每一个模块的编写都非常耗时,且需要更底层的专业知识。将这些内容封装成通用模块,有利于开发者更专注于程序逻辑本身的编写,而不用再费时费力写一些例如模型解析的底层功能。

      三. 基础库的封装

      引擎同样提供了许多3D开发中常用的基础方法,例如数学库等。

      可以说,引擎帮助开发者做了大量繁复的底层工作,可以让开发者更专注于上层用户逻辑的编写,从而提升开发效率。

      1 条回复 最后回复 回复 引用 1
      • shuangliu
        shuangliu 最后由 shuangliu 编辑

        Orillusion 目前仍然在内测中,相应的 @orillusion/core 和 unpkg 链接无法直接访问,我们正在积极准备文档,稍后开放

        1 条回复 最后回复 回复 引用 0
        • L
          lightgm 最后由 编辑

          有没有类似pixijs的2d封装?我本来打算用pixijs渲染我的项目,不知道orillusion会不会提供?或者已经提供了类似的基本2d图形+文字的渲染方法封装?

          shuangliu 1 条回复 最后回复 回复 引用 0
          • shuangliu
            shuangliu @lightgm 最后由 编辑

            @lightgm 目前还没有2d相关封装,后续会扩充相关生态

            1 条回复 最后回复 回复 引用 0
            • First post
              Last post

            Recent Post

            • 请问有没有本次测试所使用的threejs、babylon和orillusion的源码?

              • 阅读更多
            • B

              哪位大佬知道,纹理闪烁是怎么回事吗?.

              • 阅读更多
            • @StephenChips 同求

              • 阅读更多
            • A

              请问这个入门系列有 demo 代码没有

              • 阅读更多
            • O

              经过几次的学习已经能够构建出一个空间(场景),并在空间中创建物体(几何体),物体可以有不同的外观(材质),与现实的效果足够逼真(光照),终于把最重要的相关性最强的几部分3D功能用起来了。不过面对这块空间想做点什么,又感觉缺少了点什么,是的,只能观看不能操作,如果我要通过键盘、鼠标对场景进行实时的干预该如何做呢,经过了解输入系统可以满足我们的要求。

              输入系统

              输入系统是个比较杂乱的部分,不同平台都有对应的封装,我们可以回忆一下Win32编程将键盘和鼠标的输入集成到了事件系统,用户操作按键或操作鼠标会触发对应的消息码,指示消息,附带参数包含具体的按键信息或鼠标信息,按键信息一般包含按键码或鼠标键位。再回忆一下DOM的事件系统,使用addEventListener将click或mouse类的事件挂载,然后在回调函数中获得结果……
              回忆结束我们可以总结出来几个输入系统的特点:1、挂载感兴趣的事件;2、回调函数得到触发时处理业务逻辑。需要注意的是,键盘需要有按键表进行区分按键,对应的是鼠标需要区分不同按键,以及屏幕坐标,辅助键等一些附属信息。
              出于好奇orilluson的输入系统如何实现的,找来源码进行了一个大体的了解,可以看到输入系统的核心类是InputSystem,该类继承于CEventDispatcher类,CEventDispatcher类是可调度事件的所有类的基类,包含了事件的注册,注销,分发和清理等功能实现。内部保存了监听对象列表,当有消息需要处理时通过遍历监听器列表触发回调函数。InputSystem继承了CEventDispatcher类的事件处理能力外着重实现了键盘鼠标的事件处理。
              具体执行步骤如下:

              Engine3D.init:初始化引擎后,实例化了InputSystem类,并将canvas实例传入InputSystem类; InputSystem.initCanvas:InputSystem监听了画布的键盘与鼠标事件; addEventListener:引擎或对象通过addEventListener函数来挂载用户监听; dispatchEvent:当有挂载的监听事件响应时,回调函数会得执行。
              在输入系统的支持下,可以很轻松的使用键盘和鼠标与触控。
              输入系统的回调事件在类CEvent中,先熟悉一下这个类的常用定义: type:事件类型对应的一个字符串常量; param:注册事件时传递的参数,在注册事件时写入的参数在这里可以读出; ctrlKey:事件发生时 Ctrl 是否被按下,通过查询该键的值来判断Ctrl键的状态; altKey:事件发生时 Alt 是否被按下,通过查询该键的值来判断Alt键的状态; shiftKey:事件发生时 Shift 是否被按下,通过查询该键的值来判断Shift键的状态; 关于坐标

              一直以来的学习路径是以实用为主,但是现在必须要接触一点点不能称之为理论的理论了,那就是坐标系统。

              世界坐标

              首先要解决一个困惑的地方,过去在3D空间中的所有坐标都可以称为世界坐标,世界坐标是三维的,有三个维度(x,y,z),一般在引擎中创建可以由系统使用,开发用户程序需要遵守引擎对于世界的规划,相当于场景作为一个空间,世界坐标是对这个空间制定的规则。这里歪个楼,骇客帝国之所以叫矩阵,是不是因为在3D引擎中对空间世界的处理也是以矩阵为基础的。再拉回来,世界坐标一般以(0,0,0)为中心,我们创建的物体默认的位置也是在这里的,这里是世界的中心,一般分为右手或左手坐标系,好了关于世界坐标系这里已经够用了。

              屏幕坐标

              说回到屏幕坐标是我们过去所熟悉的,首先屏幕坐标是一个二维坐标,以像素为单位,屏幕的左下角为起点,向屏幕的左侧和上方依次是x和y坐标的正向。在网页开发中我们通过DOM事件系统获得的当前坐标一般都是指的屏幕坐标。在网页开发中并不是绝对的没有z轴,CSS中的z-index属性是否可以理解成一种z轴坐标呢。

              相互转换

              屏幕坐标是我们最终渲染到屏的最终展现形式,世界坐标是在三维空间内的标识,两者经常需要相互转换,例如今天需要讨论的输入系统的使用。假设在屏幕上点击了一个位置,需要转换到世界坐标,相似的在世界坐标内的位置或距离也需要转换为屏幕坐标。
              坐标转换有标准的算法,这里我们不必如此费力,完全可以借助引擎的工具,经过一翻查找,在相机组件的实现类Camera3D,有坐标转换的工具,可以一起熟悉一下

              object3DToScreenRay:世界坐标转换屏幕坐标; ScreenRayToObject3D:屏幕坐标转换为世界坐标; 键盘输入

              使用键盘输入,首先需要熟悉两种键盘事件:

              KEY_DOWN:键盘按下事件,使用输入系统挂载该事件,将会得到按下键盘事件通知; KEY_UP:键盘弹起事件,使用输入系统挂载该事件,将会得到弹起键盘事件通知;
              下面来一起梳理一下使用流程: 初始化:必要的引擎初始化; 输入挂载:使用键盘挂载系统指定事件和回调; 处理回调:在回调中获取参数。 基础示例

              这里写了一个最基本的示例,只将键盘的事件打印了出来。

              import { Engine3D, Scene3D, Object3D, Camera3D, HoverCameraController, ForwardRenderJob, DirectLight, KeyEvent } from "@orillusion/core"; export default class Keyboard { cameraObj: Object3D; camera: Camera3D; scene: Scene3D; boxObj: Object3D; async run() { await this.init(); await this.setup(); await this.start(); } /*** * 配置并初始化引擎 */ private async init() { // 初始化引擎 await Engine3D.init(); // 创建一个场景 this.scene = new Scene3D(); // 创建一个相机 this.cameraObj = new Object3D(); this.camera = this.cameraObj.addComponent(Camera3D); // 设置相机类型 this.camera.perspective(60, window.innerWidth / window.innerHeight, 1, 5000.0); // 设置相机控制器 let controller = this.cameraObj.addComponent(HoverCameraController); controller.setCamera(20, -20, 25); // 添加相机至场景 this.scene.addChild(this.cameraObj); } /** * 引擎功能代码 */ private async setup() { Engine3D.inputSystem.addEventListener(KeyEvent.KEY_UP, this.keyUp, this); Engine3D.inputSystem.addEventListener(KeyEvent.KEY_DOWN, this.keyDown, this); } /** * 启动渲染 */ private async start() { // 创建前向渲染 let renderJob: ForwardRenderJob = new ForwardRenderJob(this.scene); // 开始渲染 Engine3D.startRender(renderJob); } private keyDown(e: KeyEvent) { console.log('keyDown:', e.keyCode, e); } private keyUp(e: KeyEvent) { console.log('keyUp:', e.keyCode, e); } }

              运行这个示例后,在场景中按下或弹起键盘,在控制台能够看到输出。

              KeyEvent

              在回调函数中获得的参数类型是KeyEvent,KeyEvent是CEvent的子类,除了CEvent类的参数外,对于键盘事件的使用主要在于对该类型的解析,这里需要详细的了解事件的参数细节,常用到的需要进行一个了解:

              keyCode:按键code值,枚举类型可以参考官方文档的KeyCode定义。 鼠标与触控

              电脑端的鼠标操作与移动端的触控操作有许多共同的地方,在具体用法时如果能够合并为一,是可以节省一半的事件挂载操作的,不过需要留意触控与鼠标的事件对应关系。
              有了前面键盘操作的基础,鼠标与触控使用类型,我们先看支持的事件类型:

              POINTER_CLICK:触摸点击事件,对应鼠标的单击事件; POINTER_MOVE:触摸滑动事件,对应鼠标的移动事件 POINTER_DOWN:触摸开始事件, POINTER_UP:触摸结束事件 POINTER_OUT:触摸滑出事件
              既然已经合并了,后面鼠标与触控用触控来说明吧。 基础示例

              先实现一个最基础的触控功能,与键盘类似,先注册事件,然后响应事件。

              import { Engine3D, Scene3D, Object3D, Camera3D, HoverCameraController, ForwardRenderJob, PointerEvent3D } from "@orillusion/core"; export default class Mouse { cameraObj: Object3D; camera: Camera3D; scene: Scene3D; async run() { await this.init(); await this.setup(); await this.start(); } /*** * 配置并初始化引擎 */ private async init() { // 初始化引擎 await Engine3D.init(); // 创建一个场景 this.scene = new Scene3D(); // 创建一个相机 this.cameraObj = new Object3D(); this.camera = this.cameraObj.addComponent(Camera3D); // 设置相机类型 this.camera.perspective(60, window.innerWidth / window.innerHeight, 1, 5000.0); // 设置相机控制器 let controller = this.cameraObj.addComponent(HoverCameraController); controller.setCamera(20, -20, 25); // 添加相机至场景 this.scene.addChild(this.cameraObj); } /** * 引擎功能代码 */ private async setup() { Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_UP, this.onUp, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_DOWN, this.onDown, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_CLICK, this.onPick, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_OVER, this.onOver, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_OUT, this.onOut, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_MOVE, this.onMove, this); } /** * 启动渲染 */ private async start() { // 创建前向渲染 let renderJob: ForwardRenderJob = new ForwardRenderJob(this.scene); // 开始渲染 Engine3D.startRender(renderJob); } private onUp(e: PointerEvent3D) { console.log('onUp:',e); } private onDown(e: PointerEvent3D) { console.log('onDown:',e); } private onPick(e: PointerEvent3D) { console.log('onPick:',e); } private onOver(e: PointerEvent3D) { console.log('onOver:',e); } private onOut(e: PointerEvent3D) { console.log('onOut:',e); } private onMove(e: PointerEvent3D) { console.log('onMove:',e); } } PointerEvent3D

              触控的参数是以PointerEvent3D类型作为回调函数的参数传递到应用,PointerEvent3D是CEvent的子类,除了CEvent类的参数外,需要熟悉一下这个类型的关键字段。

              mouseX:当前鼠标所在位置的X坐标; mouseY:当前鼠标所在位置的Y坐标; movementX:当前事件和上一个鼠标事件之间鼠标在水平方向上的移动值; movementY:当前事件和上一个鼠标事件之间鼠标在垂直方向上的移动值;
              坐标系列的数值请注意,可以使用前面相机组件提供的转换函数进行转换,不必自己写算法进行转换。 由对象挂载

              前面的挂载直接由引擎的输入系统挂载,这样在整个场景中都会响应,如果只需要在一个物体中响应鼠标的事件,我们可以将事件挂在物体上,为什么可以这么做呢,找出来代码可以看到,物体的容器是Object3D类,而Object3D类是Entiry的子类,Entity的父类是CEventDispatcher类,正是因为Object3D通过CEventDispatcher,继承了事件的能力。这一套继承加组件式的结构,实在是太好用了,有没有。
              这样就有了以下的代码:

              // 创建一个对象 this.boxObj = new Object3D(); this.boxObj.localPosition = new Vector3(0,0,0); // 创建渲染组件 let mr: MeshRenderer = this.boxObj.addComponent(MeshRenderer); // 设置形状 mr.geometry = new BoxGeometry(5, 5, 5); // 设置材质 mr.material = new HDRLitMaterial(); // 添加到场景 this.scene.addChild(this.boxObj); boxObj.addEventListener(PointerEvent3D.PICK_CLICK, this.onClick, this); onClick(e: PointerEvent3D) { console.log('onPick:',e); }

              运行后可以在控制台看到输出

              小结

              经过前面几次的学习,已经能够完事的构建出一个空间了,但是这块空间仍然缺乏灵动的能力,不能随时响应我们的操控,输入系统是一个随时干预系统的大杀器,可以让我们获得掌控感,是否控制欲获得了满足。
              今天只是一些最基础的用法,发挥想象力可以使这个空间好玩起来了。
              作为3D新手,后续会不断的记录学习过程,期待与你一起学习一起飞!

              • 阅读更多

            Copyright © 2022 Orillusion | Contact US