前言
今天带大家了解一下react-fibre-three库,这是一个基于three,然后适配react开发3d的库,我觉得他可以简化我们的3d开发代码量,其实也没减少多少,哈哈,就给大家简单介绍一下好了,具体的大家看看github上的文档,如果是react技术栈想学3d的同学可以了解一下。
使用常规three+react开发3d
这里创建react项目的过程我省略了,学react的同学应该都会,这里直接上three结合react的简单开发过程,首先我们需要安装three
安装three
1 | yarn add three |
初始化样式
我们把App.css修改下
1 | *{ |
类组件使用three
这里的componentDidMount就相当于vue中onMounted的生命周期钩子,挂载完成的意思。
1 | import "./App.css"; |
函数式组件使用three
这里我用了useEffect这个钩子,他相当于挂载完成,因为我们第二个参数是空的,如果是有的话,就还会在那个参数更新的时候执行这个方法,差不多是vue中的watch的意思。
1 | import "./App.css"; |
这里实现出来的效果也是一样的,这里就不贴图了。接下来让我们使用react-fibre-three来实现一下three的开发。
使用react-fibre-three开发3d
安装react-fibre-three和react-three/drei
1 | yarn add react-fibre-three react-three/drei |
创建简单的立方体
这里需要将我们的3d代码使用canvas包裹,OrbitControls就是控制器,mesh里面就是写我们的物体的材质,是不是非常简单。
1 | import "./App.css"; |
给物体打个光
这里我给这个立方体可以简单打个光,也非常简单,就是three中的属性都通过props的方法传递进去就行。
1 | import "./App.css"; |
旋转物体
这里我们是旋转物体,不是上面的旋转控制器哦,这里需要用到useFrame这个钩子,这个钩子是每一帧都会执行的,我们可以在这里写一些动画,这里我就简单的旋转一下物体。
1 | import "./App.css"; |
使用useThree获取three信息
1 | import "./App.css"; |
useLoader使用模型
在react-fibre-three中,我们使用useLoader这个hook来加载gltf的模型,这里我还配置了一个环境贴图,使用了Environment,通过background设置为背景,将相机的位置Canvas camera={{ position: [0, 2, 2] }}
进行了调整。
1 | import "./App.css"; |
纹理材质的使用
搞到这里大家应该也都能看懂了,就是使用了标准材质,配了那些贴图
1 | import "./App.css"; |
demo-3d立体字
ok,讲了那么多,顺便分享个使用three来搭建3d立体字吧。
初步搭建
这里使用了Center居中,以及它自带的Text3D效果,这里的字体我是在网上找的,大家可以自己找一下,然后放到assets/font,这里我用的仿宋,这里字体必须要有,不然会报错。
1 | import "./App.css"; |
调整字体显示样式
这里字体的调整大家可以去看three文档中的TextGeometry这块,那里有具体的文档,比我这详细
- 这里我在canvas里面修改了相机为正交相机,并且设置了位置和缩放比例。
- 我将字体默认旋转了一下,添加了字体间隔属性
letterSpacing
bevelEnabled
该属性指定文本拉伸时是否启用斜角,默认falsebevelThickness
该属性指定文本拉伸体斜角的厚度,默认值是10bevelSize
该属性指定文本拉伸体斜角的高度。默认值是8bevelSegments
该属性指定文本拉伸体斜角的分段数,段数越多斜角越光滑,默认值是3curveSegments
该属性指定文本拉伸时拉伸曲线的分段数,段数越多曲线越光滑,默认值是41
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
48import "./App.css";
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Text3D, Center } from "@react-three/drei";
function App() {
return (
<div className="App">
<Canvas
orthographic
camera={{ position: [10, 20, 20], zoom: 80 }}
>
<OrbitControls />
<ambientLight args={[0xffffff]} intensity={0.5} />
<directionalLight
args={[0xffffff]}
position={[0, 5, 5]}
intensity={0.5}
/>
<Text />
</Canvas>
</div >
);
}
function Text() {
let fontUrl = "./assets/font/FangSong_Regular.json";
return (
<Center>
<Text3D
scale={3}
height={0.25}
font={fontUrl}
rotation={[-Math.PI / 2, 0, 0]}
letterSpacing={-0.03}
bevelEnabled
bevelSize={0.01}
bevelSegments={10}
bevelThickness={0.01}
curveSegments={128}
>
Codesigner
<meshBasicMaterial color={0xff0000} />
</Text3D>
</Center>
);
}
export default App;
添加阴影
这里我使用了累计阴影:AccumulativeShadows
以及随机光源:RandomizedLight
随机光源的定义是这样的:一种随机光源,可在内部运行多个光源并使它们抖动。见下文,您通常会将其与累积阴影配对。该组件是上下文感知的,与累积阴影配对,它将从其父级获取帧数。
我把这些参数文档截图发一下,大家就理解了
1 | import { Canvas, useLoader } from "@react-three/fiber"; |
绘制材质
整体逻辑
- 导入了Three.js库和一些相关的模块。
- 创建了一个继承自MeshPhysicalMaterial的类MeshRefractionMaterialImpl,该类表示折射材质的实现。
- 构造函数中初始化了一些uniform变量,这些变量将在着色器中使用。
- 在onBeforeCompile函数中,对着色器进行修改和替换操作,以实现折射效果。
- 最后通过extend函数将自定义的材质注册到Three.js中,使其可以在场景中使用。
- 导出了一个React组件MeshRefractionMaterial,该组件接受一些属性参数,并将窗口分辨率传递给材质。
代码注解
在onBeforeCompile函数中,代码对着色器进行了修改和替换操作,以实现折射效果。具体来说,代码做了以下几件事情:
添加uniform变量:通过在shader.uniforms中添加自定义的uniform变量,将这些变量传递给着色器程序。
修改fragmentShader:通过替换shader.fragmentShader中的特定代码片段,将折射效果的计算和渲染逻辑插入到原有的渲染流程中。
具体来看,代码的修改步骤如下:
添加uniform变量:通过shader.uniforms = {…shader.uniforms, …this.uniforms};将自定义的uniform变量合并到原有的uniform变量集合中。
uTransparent: 控制折射的透明度。
winResolution: 窗口分辨率,用于计算uv坐标。
uRefractPower: 控制折射的强度。
uRefractNormal: 控制折射的法线方向。
uNoise: 控制折射的噪声。
uSat: 控制颜色饱和度。
uIntensity: 控制折射的强度。
uColor: 折射颜色。
uSceneTex: 场景纹理。
修改fragmentShader:通过字符串替换的方式,在原有的fragmentShader中插入自定义的折射计算和渲染逻辑。
首先,添加了一些自定义的辅助函数:random和sat,用于生成随机数和调整颜色饱和度。
然后,在原有的渲染逻辑之前插入了折射计算的代码。
折射计算部分的代码使用了循环进行多次采样,通过在uv坐标上根据折射方向和强度进行采样,将采样到的颜色累加到refractCol中。
最后,将refractCol除以采样次数,得到平均值,并将其与uIntensity和uColor进行混合,得到最终的折射颜色。
最后,使用替换后的fragmentShader替换掉原有的fragmentShader。
总的来说,onBeforeCompile函数通过修改和替换着色器代码,实现了在场景中物体上的折射效果。这个折射效果是通过对纹理进行采样、颜色调整和混合等操作得到的。
材质代码
1 | import * as THREE from "three"; |
使用材质
这段代码,是用来留下快照的,我这里是用来留下背景的,然后在使用这个背景作为材质的贴图,这里我使用了useFBO这个hook,这个hook是用来创建一个帧缓冲区的,然后我们就可以将这个帧缓冲区的内容作为材质的贴图了。
1 | const fbo = useFBO(1024); |
完整代码
1 | import { RGBELoader } from "three-stdlib"; |
添加gui效果
1 | import { useRef } from "react"; |
结语
好了,本篇文章就介绍到这里,更多内容,敬请期待~~~