111 |
112 |
113 | width:{urlParams.width}
114 | height:{urlParams.height}
115 | depth:{urlParams.depth}
116 |
117 |
118 | )
119 | ```
120 |
121 | 对应的样式:
122 |
123 | ```
124 | .full-screen, canvas {
125 | display: block;
126 | height: inherit;
127 | width: inherit;
128 | }
129 |
130 | .debug {
131 | position: fixed;
132 | top: 20px;
133 | left: 20px;
134 | width: 80px;
135 | padding: 20px;
136 | background-color: rgba($color: #FFFFFF, $alpha: 0.7);
137 | }
138 |
139 | .debug span {
140 | display: block;
141 | }
142 | ```
143 |
144 | 这样当我们调试网页的时候,就可以直接在左上角,看到 立方体的尺寸具体的值。
145 |
146 | > 本示例演示的立方体尺寸是固定的,若通过 useState 来定义尺寸,且尺寸会发生修改,那么左上角的展示的参数也可以对应修改成动态可变动的。
147 |
148 | > 依次类推,可以延展成其他参数展示
149 |
150 |
151 |
152 | #### 7、把 window.requestAnimationFrame 添加在靠后位置
153 |
154 | 在之前的一些示例中,渲染场景的函数,可能如下:
155 |
156 | ```
157 | const render = () => {
158 | renderer.render(scene, camera)
159 | window.requestAnimationFrame(render)
160 | }
161 | window.requestAnimationFrame(render)
162 | ```
163 |
164 | 你是否考虑过,假设我们修改成这样:
165 |
166 | ```
167 | const render = () => {
168 | window.requestAnimationFrame(render) //代码顺序改变
169 | renderer.render(scene, camera)
170 | }
171 | window.requestAnimationFrame(render)
172 | ```
173 |
174 | 代码顺序调整后,会有什么问题吗?
175 |
176 | 答:这里可能会产生一个隐患——由于 window.requestAnimationFrame 代码在前,renderer.render(scene, camera) 代码在后,那么意味着 即使 renderer.render() 执行发生错误,那么代码依然在下一帧中继续执行。
177 |
178 | 而我们之前的顺序是 renderer.render() 在前,window.requestAnimationFrame 在后,那么万一 renderer.render() 执行时发生错误,此时 浏览器即报错,JS 停止运行,那么后面的 window.requestAnimationFrame 就不会再执行了。
179 |
180 | 结论:应该尽量把 window.requestAnimationFrame 添加到靠后位置。
181 |
182 |
183 |
184 | #### 8、检查 Three.js 中的单位
185 |
186 | 在 Three.js 中,单位并没有统一,具体表现在:
187 |
188 | 1. 镜头的角度使用的是度数、而其他地方涉及角度时单位使用的是 弧度。
189 | 2. 默认情况下,对于距离、尺寸的数值 1 表示 1 米,但是也可以通过配置让数值 1 表示为 1 厘米。
190 |
191 | 因此,在使用 Three.js 时,关于数值单位请格外留意。
192 |
193 |
194 |
195 | #### 9、添加辅助对象、添加镜头轨道控制器
196 |
197 | 在开发阶段,可以多添加一些辅助对象,例如:坐标辅助对象、灯光辅助对象、镜头辅助对象。
198 |
199 | 辅助对象可以比较直观得帮助我们去观察,去调试。
200 |
201 | 同时也要添加镜头轨道控制器,例如 OrbitControls,可以让我们比较方便操控、查看场景。
202 |
203 |
204 |
205 | #### 10、必要时可以将物体材质设置为 MeshBasicMaterial
206 |
207 | 假设你设置的物体材质是可反光材料,但是渲染时发现并没有渲染出该物体。
208 |
209 | 这个时候,你可以先将物体材质修改为不反光的 MeshBasicMaterial,这样可以快速排除一些问题。
210 |
211 | 假设物体材质不反光,此时若依然渲染不出物体,那么就可以肯定问题没有出在灯光上。
212 |
213 | 反之,则应该去检查灯光的问题。
214 |
215 |
216 |
217 | #### 11、检查镜头的 near 和 far 配置
218 |
219 | 有些时候场景没有渲染出物体,那么你也要去检查一下镜头的 near 和 far 的值。
220 |
221 | 比如我们可以暂时性的将镜头的 far 设置为 10000,或者将 near 设置为 0.001,在这种极端配置下,再去看场景是否渲染出物体。
222 |
223 | 调试结束后,记得将 near 和 far 调整会合理的精度范围。
224 |
225 |
226 |
227 | #### 12、遇到疑惑的地方,查文档,查源码
228 |
229 | 遇到某些 Three.js 疑惑的地方,例如某属性,某方法,请记得一定先去查阅官方文档,如果没有解决就直接去看 Three.js 的源码。
230 |
231 | Three.js 的源码并不是特别复杂,要敢于查看源码来解决疑惑。
232 |
233 |
234 |
235 | ## 使用GUI调试场景中的参数
236 |
237 | **图形用户界面( Graphical User Interface ) 简称 GUI。**
238 |
239 | > 主要目的是用来帮我们快速搭建可视化调试参数面板。
240 |
241 |
242 |
243 | **针对 JS 的 GUI ——dat.gui**
244 |
245 | 官网地址:https://github.com/dataarts/dat.gui
246 |
247 |
248 |
249 | **针对 React 的 GUI——react-dat-gui**
250 |
251 | 官网地址:https://github.com/claus/react-dat-gui
252 |
253 |
254 |
255 | **react-dat-gui 的具体用法,请查看我的另外一篇文章:[React中使用GUI.md](https://github.com/puxiao/notes/blob/master/React%E4%B8%AD%E4%BD%BF%E7%94%A8GUI.md)**
256 |
257 |
258 |
259 | 本教程所有示例都是基于 react + typescript 的,所以我们选择使用 react-dat-gui
260 |
261 | 在我们后续的示例中,就会使用到 react-dat-gui。
262 |
263 |
264 |
265 | ## 调试GLSL
266 |
267 | **图形库着色语言( Graphic Library Shader Language ) 简称 GLSL。**
268 |
269 | > 学不动了,学不动了!
270 |
271 | GLSL 的相关介绍,可查阅:
272 |
273 | WebGL与GLSL:https://webglfundamentals.org/webgl/lessons/zh_cn/webgl-shaders-and-glsl.html
274 |
275 | WebGL2与GLSL:https://webgl2fundamentals.org/webgl/lessons/zh_cn/webgl-shaders-and-glsl.html
276 |
277 |
278 |
279 | 由于我个人没有学习过 WebGL和 GLSL,所以暂时先不讨论如何调试 GLSL。
280 |
281 | > 谷歌浏览器还有一个专门用来调试着色器的插件:Shader Editor
282 | >
283 | > https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob?hl=en
284 |
285 |
286 |
287 | 关于 Three.js 的调试技巧,就讲到这里。
288 |
289 | 接下来讲解 Canvas 的一些常用小技巧。
--------------------------------------------------------------------------------
/02 初始化Three.js项目.md:
--------------------------------------------------------------------------------
1 | # 02 初始化Three.js项目
2 |
3 | 本文以 Yarn 而不是 NPM 安装 Three.js。
4 |
5 | **第1步:全局安装 create-react-app**
6 |
7 | ```
8 | yarn global add create-react-app
9 | ```
10 |
11 |
12 |
13 | **第2步:初始化React+TypeScript项目**
14 |
15 | > 我用的是 create-react-app 4.0.2 版本,对应的是 React 17.0.1
16 |
17 | ```
18 | yarn create react-app test-threejs --template typescript
19 | ```
20 |
21 |
22 |
23 | **第3步:初次修改 tsconfig.json 配置**
24 |
25 | 1. 修改 TS 编译目标 ES版本为 es2017
26 |
27 | ```
28 | "target": "es2017"
29 | ```
30 |
31 | 2. 添加一些本人 TS 配置偏好
32 |
33 | ```
34 | "noUnusedLocals": true,
35 | "noUnusedParameters": true,
36 | "sourceMap": true,
37 | "removeComments": false
38 | ```
39 |
40 |
41 |
42 | **第4步:配置 alias,安装对应模块**
43 |
44 | 由 create-react-app 创建的 React 项目中,配置 alias(路径映射),我采用的方案是:react-app-rewired + react-app-rewire-alias
45 |
46 | ```
47 | yarn add --dev react-app-rewired react-app-rewire-alias
48 | ```
49 |
50 |
51 |
52 | **第5步:完善 alias 配置**
53 |
54 | 1. 在项目根目录,新建文件 tsconfig.paths.json,内容暂时设置为:
55 |
56 | ```
57 | {
58 | "compilerOptions": {
59 | "baseUrl": ".",
60 | "paths": {
61 | "@/src/*": ["./src/*"],
62 | "@/components/*": ["./src/components/*"]
63 | }
64 | }
65 | }
66 | ```
67 |
68 | > 我们暂时先添加 2 个路径映射 src 和 components,具体路径还会根据将来实际开发过程中所需要创建不同的目录结构进行修改。
69 | >
70 | > 补充:根据 typescript 官方更新说明文档,baseUrl 这一项是可以省略的,但是上面代码中还是遵循了之前的配置方式,继续添加上了 baseUrl。
71 |
72 | 2. 在项目根目录,新建文件 config-overrides.js,内容为:
73 |
74 | ```
75 | const { alias, configPaths } = require('react-app-rewire-alias')
76 |
77 | module.exports = function override(config) {
78 | alias(configPaths('./tsconfig.paths.json'))(config)
79 |
80 | return config
81 | }
82 | ```
83 |
84 | > 注意是 .js 文件 而不是 .ts 文件,鼠标放到 require 上后也许会显示提示文字:文件是 CommonJS 模块;它可能会转换为 ES6 模块。
85 | >
86 | > 请忽略这个提示,这并不是什么错误信息。
87 | >
88 | > require 是 Nodejs 导入模块的方式,TypeScript 导入模块使用的是 import。
89 |
90 | 3. 在项目根目录,新建文件 global.d.ts,内容为:
91 |
92 | > 注意:本步骤的目的是为了让 TS 忽略对 react-app-rewire-alias 和其他一些非常规格式文件的导入检查。
93 | >
94 | > 本步骤是可选的,不是必须的,你可以跳过本步骤。
95 |
96 | ```
97 | declare module '*.png';
98 | declare module '*.gif';
99 | declare module '*.jpg';
100 | declare module '*.jpeg';
101 | declare module '*.svg';
102 | declare module '*.css';
103 | declare module '*.less';
104 | declare module '*.scss';
105 | declare module '*.sass';
106 | declare module '*.styl';
107 | declare module 'react-app-rewire-alias';
108 | ```
109 |
110 | 4. 修改 tsconfig.json 文件,添加以下一行内容:
111 |
112 | ```
113 | {
114 | "extends": "./tsconfig.paths.json",
115 | "compilerOptions": {
116 | ...
117 | }
118 | }
119 | ```
120 |
121 | > 请注意 extends 是和 compilerOptions 平级的。
122 |
123 | 至此,我们的 tsconfig.json 最终内容如下:
124 |
125 | ```
126 | {
127 | "extends": "./tsconfig.paths.json",
128 | "compilerOptions": {
129 | "target": "es2017",
130 | "lib": [
131 | "dom",
132 | "dom.iterable",
133 | "esnext"
134 | ],
135 | "allowJs": true,
136 | "skipLibCheck": true,
137 | "esModuleInterop": true,
138 | "allowSyntheticDefaultImports": true,
139 | "strict": true,
140 | "forceConsistentCasingInFileNames": true,
141 | "noFallthroughCasesInSwitch": true,
142 | "module": "esnext",
143 | "moduleResolution": "node",
144 | "resolveJsonModule": true,
145 | "isolatedModules": true,
146 | "noEmit": true,
147 | "jsx": "react-jsx",
148 | "noUnusedLocals": true,
149 | "noUnusedParameters": true,
150 | "sourceMap": true,
151 | "removeComments": false
152 | },
153 | "include": [
154 | "src"
155 | ]
156 | }
157 | ```
158 |
159 |
160 |
161 | **第6步:修改 package.json 中的 scripts 命令**
162 |
163 | 将命令中 start、build、test 3 条命令中的 react-scripts 修改为 react-app-rewired
164 |
165 | ```
166 | "scripts": {
167 | "start": "react-app-rewired start",
168 | "build": "react-app-rewired build",
169 | "test": "react-app-rewired test",
170 | "eject": "react-scripts eject"
171 | },
172 | ```
173 |
174 |
175 |
176 | **第7步:安装 scss**
177 |
178 | ```
179 | yarn add node-sass --dev
180 | ```
181 |
182 | > 假设你使用的是较早版本的 create-react-app,那么当时还不支持最新版 node-sass 5.0,所以你只能安装: `yarn add node-sass@4.14.1 --dev`
183 |
184 |
185 |
186 | **第8步:安装three.js**
187 |
188 | ```
189 | //npm install --save three
190 | yarn add three
191 | ```
192 |
193 |
194 |
195 | > 以下更新于 2021.04.11
196 |
197 | **关于 .d.ts 文件的特别说明:**
198 |
199 | 写这篇文章的时候是 2020年11月底,当时应该是 r124 版本,当时的 Three.js 版本里内置了 .d.ts 文件,但是随着 Three.js 版本升级,大约在 r126 版本以后官方已经将内置的 .d.ts 文件移除,目前最新的版本是 r128。
200 |
201 | **所以,我们现在还需要额外安装对应的 .d.ts 文件包:**
202 |
203 | ```
204 | //npm install @types/three
205 | yarn add @types/three
206 | ```
207 |
208 |
209 |
210 |