R3F(React Three Fiber)基础篇

2024-02-25 03:36

本文主要是介绍R3F(React Three Fiber)基础篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前一直在做ThreeJS方向,整理了两篇R3F(React Three Fiber)的文档,这是基础篇,如果您的业务场景需要使用R3F,您又对R3F不太了解,或者不想使用R3F全英文文档,您可以参考一下这篇,作为学习R3F的基础教程使用。

经验篇:⬇️

R3F(React Three Fiber)经验篇

一、R3F基础

文章目录

  • 一、R3F基础
    • 一、React Three Fiber基础
      • 1. 基础场景搭建
      • 2. 自定义Geometry
      • 3. useFrame
      • 4. toneMapping (色调映射)
    • 二、@react-three/drei
      • 1. OrbitControls
      • 2. TransformControls
      • 3. PivotControls
      • 4. Html
      • 5. Text
      • 6. Float
      • 7. 镜面反射材质
    • 三、Debugger
      • 1. leva
      • 2. r3f-perf
      • 3. useHelper
    • 三、Environment
      • 1. 设置背景颜色
      • 2. 配置阴影
      • 3. 天空盒
      • 4. 场景HDR文件
    • 四、Load Models
      • 1. useLoader
      • 2. Suspense
      • 3. useGLTF
      • 4. GLTF Clone(模型克隆)
      • 5. GLTF Animation
      • 6. Text3D
      • 7. useMatcapTexture
      • 8. Multiple model processing
    • 五、Mouse Event
      • 1. EventHandler
      • 2. Event Kind
    • 六、Post Processing
      • 1. Install
      • 2. multisampling 多重采样
      • 3. vignette 晕映
      • 4. Glitch 失灵
      • 5. Noise 噪点
      • 6. Bloom
      • 7. DepthOfField 景深
    • 七、Physics
      • 1. Installation
      • **2. RigidBody:刚体**
      • 3. Controll rigidbody movement
      • 4. grvity 重力
      • 5. gravityScale,restitution,friction
      • 6. RigidBody mass 刚体重力

一、React Three Fiber基础

1. 基础场景搭建

function App() {const cameraSettings = {fov: 1,zoom: 100,near: 0.1,far: 200,position: new Vector3(3, 2, 6)}return (<><Canvasorthographic={true}camera={{ ...cameraSettings }}><Experience /></Canvas></>)
}

相机场景配置

const cameraSettings = {// fov: 1,// zoom: 100,near: 0.1,far: 200,position: new Vector3(3, 2, 6)
}<Canvasgl={ {antialias: true,toneMapping: ACESFilmicToneMapping,outputEncoding: LinearEncoding} }// orthographic={true}  // orthographic 会影响Environment组件camera={{ ...cameraSettings }}shadows={true}onCreated={created}
><Experience />
</Canvas>

Experience.tsx

import "@react-three/fiber";
import { useRef } from "react";
import { Group } from "three";
import {extend, useFrame, useThree} from "@react-three/fiber";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import CustomObject from "./CustomObject.tsx";extend({ OrbitControls })export default function Experience() {const { camera, gl } = useThree();const cubeRef = useRef<any>(null!);const groupRef = useRef<Group>(null!);useFrame(() => {cubeRef.current.rotation.y += 0.01;})return <>{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}{/* @ts-ignore */}<orbitControls args={ [camera, gl.domElement] } /><directionalLight position={ [ 1, 2, 3 ] } intensity={ 1.5 } /><ambientLight intensity={ 0.5 } /><group ref={groupRef}><mesh><sphereGeometry/><meshStandardMaterial color={'orange'}/></mesh><mesh ref={cubeRef} rotation-y={Math.PI * 0.25} position-x={2} scale={1.5}><boxGeometry/><meshStandardMaterial color={"mediumpurple"} wireframe={false}/></mesh><mesh position-y={-1} rotation-x={-Math.PI * 0.5} scale={10}><planeGeometry/><meshStandardMaterial color={"greenyellow"}/></mesh></group></>
}

2. 自定义Geometry

import { DoubleSide, BufferGeometry } from "three";
import {useEffect, useMemo, useRef} from "react";export default function CustomObject() {const geometryRef = useRef<BufferGeometry>(null!);const verticesCount = 10 * 3;const positions = useMemo(() => {const positions = new Float32Array(verticesCount * 3);for (let i = 0; i < verticesCount; i++) {positions[i] = (Math.random() - 0.5) * 3;}return positions;}, [verticesCount]);useEffect(() => {geometryRef.current.computeVertexNormals();}, []);return <mesh><bufferGeometry ref={geometryRef}><bufferAttributeattach={"attributes-position"}count={verticesCount}itemSize={3}array={positions}/></bufferGeometry><meshBasicMaterial color={"red"} side={ DoubleSide } /></mesh>
}

3. useFrame

useFrame((state, delta) => {// delta 一直是 1.33console.log(delta);// 开始渲染时间console.log(state.clock.getElapsedTime());console.log(state.clock.elapsedTime);cubeRef.current.rotation.y += delta;
})

摄像机周期运动

useFrame((state, delta) => {const angle = state.clock.elapsedTime;state.camera.position.x = Math.sin(angle);state.camera.position.z = Math.cos(angle);state.camera.lookAt(0, 0, 0);
})

让Canvas绘制得更好的一些效果

<Canvasgl={ {antialias: true // 抗锯齿} }orthographic={true} // 效果不详camera={{ ...cameraSettings }}
>

4. toneMapping (色调映射)

https://threejs.org/docs/#api/en/constants/Renderer

CineonToneMapping,ACESFilmicToneMapping(HDR)

<Canvasgl={ {antialias: true,toneMapping: ACESFilmicToneMapping} }orthographic={true}camera={{ ...cameraSettings }}
>

二、@react-three/drei

1. OrbitControls

自由旋转镜头组件

import {extend, useFrame, useThree} from "@react-three/fiber";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';extend({ OrbitControls })const { camera, gl } = useThree();
<orbitControls args={ [camera, gl.domElement] } />

import {OrbitControls} from "@react-three/drei";
<OrbitControls />

2. TransformControls

物体Transform组件(会在物体中心多出一个坐标系)

import { TransformControls } from "@react-three/drei";
<TransformControls><mesh ref={cubeRef} rotation-y={Math.PI * 0.25} position-x={2} scale={1.5}><boxGeometry/><meshStandardMaterial color={"mediumpurple"} wireframe={false}/></mesh>
</TransformControls>

另一种写法:

<TransformControls object={ cubeRef } />

注意

同时使用OrbitControls和TransformControls,OrbitControls要给makeDefault属性。

<OrbitControls makeDefault={true}/>

Props

TransformControlsProps:mode?: 'translate' | 'rotate' | 'scale';

3. PivotControls

效果类似TransformControls,但是好像比它好用。

<PivotControls anchor={[2, 0, 0]} depthTest={false}>

Props

PivotControlsPropsscale?: number;lineWidth?: number;rotation?: [number, number, number];axisColors?: [string | number, string | number, string | number];anchor?: [number, number, number];depthTest?: boolean;

4. Html

创建3D字体(HTML标签)

<mesh position-x={-2}><sphereGeometry/><meshStandardMaterial color={'orange'}/><HtmlwrapperClass={ 'label' } // label > div { color: white }position={ [1, 1, 0] }centerdistanceFactor={ 0.01 } // 越大,字体越大occlude={ [ cubeRef ] } // 文字遮挡效果>This is sphere.</Html>
</mesh>

Generating a 3D text geometry has its limits

  1. We can notice the polygons
  2. Takes a lot of CPU resources
  3. Some fonts won’t look very good
  4. Doesn’t support line breaks

5. Text

一个更好的,性能开销更少的文字组件,但是不支持occlude。

<Textfont={ '' }fontSize={ 1 }color={'salmon'}position-y={ 2 }maxWidth={ 3 }textAlign={ 'center' }
>I Love R3F
</Text>

6. Float

让一个物体 飘来飘去

<Float speed={4}><Textfont={''}fontSize={ 1 }color={'salmon'}position-y={ 2 }maxWidth={ 3 }textAlign={ 'center' }>I Love R3F</Text>
</Float>

7. 镜面反射材质

注意:仅可用于平面

<mesh rotation={[-Math.PI / 2, 0, 0]} position={[-10, 0, 25]}><planeGeometry args={[250, 250]} /><MeshReflectorMaterialblur={[300, 100]}resolution={2048}mixBlur={1}mixStrength={80}roughness={1}depthScale={1.2}minDepthThreshold={0.4}maxDepthThreshold={1.4}color="#050505"metalness={0.5}mirror={0}/>
</mesh>

三、Debugger

1. leva

useControls

import { useControls, button } from 'leva';
const {position: ct_position,color: ct_color,visible: ct_visible,
} = useControls('sphere', {position: {value: { x: -2, y: 0 },step: 0.01,joystick: 'invertY'},color: '#ff0000',visible: true,myInterval: {min: 0,max: 10,value: [ 4, 5 ]},choice: { options: ['a', 'b', 'c'] },clickMe: button(() => console.log('ok'))
})

2. r3f-perf

import { Perf } from "r3f-perf";
<Perf position={'top-left'}/>

3. useHelper

可以展示光线的路径

import { useHelper, } from "@react-three/drei";
import { DirectionalLightHelper, DirectionalLight } from "three";const directionalLight = useRef<DirectionalLight>(null!);
useHelper(directionalLight, DirectionalLightHelper);

三、Environment

1. 设置背景颜色

  1. 通过 color 标签
<Canvasgl={ {antialias: true,toneMapping: ACESFilmicToneMapping,outputEncoding: LinearEncoding} }orthographic={true}camera={{ ...cameraSettings }}shadows={true}
><color args={ ['#ff0000'] } attach={"background"} /><Experience />
</Canvas>
  1. 通过 onCreated 钩子函数
const created = (state: RootState) => {console.log('canvas created! ');const { gl, scene } = state;gl.setClearColor('#ff0000', 1);scene.background = new Color('red');
}<Canvasgl={ {antialias: true,toneMapping: ACESFilmicToneMapping,outputEncoding: LinearEncoding} }orthographic={true}camera={{ ...cameraSettings }}shadows={true}onCreated={created}
><Experience />
</Canvas>
  1. 通过CSS样式
*, html, body {padding: 0;margin: 0;
}html,
body,
#root {position: fixed;top: 0;left: 0;width: 100%;height: 100%;overflow: hidden;
}

2. 配置阴影

  1. 阴影参数
{/*shadow-mapSize:阴影精度,越大精度越高*/}
{/*shadow-camera-top,right,bottom,left 阴影是否柔和,越大阴影越柔和*/}
<directionalLightref={ directionalLight }position={ [ 1, 2, 3 ] }intensity={ 1.5 }castShadow={ true }shadow-mapSize={ [1024 * 4, 1024 * 4] }shadow-camera-near={ 1 }shadow-camera-far={ 10 }shadow-camera-top={ 200 }shadow-camera-right={ 200 }shadow-camera-bottom={ - 200 }shadow-camera-left={ - 200 }
/>
  1. 阴影烘焙,在适当的场景下 添加BakeShadows组件
<BakeShadows />
  1. 柔和阴影SoftShadows
<SoftShadowssize={100}focus={0}samples={10}
/>
  1. 累积阴影AccumulativeShadows
<AccumulativeShadowsposition={ [ 0, - 0.99, 0 ] }scale={ 10 }color={ '#316d39' }opacity={ 0.8 }// frames={ Infinity }// temporal={ true }// blend={ 100 }
><RandomizedLightamount={ 8 }radius={ 1 }ambient={ 0.5 }intensity={ 1 }position={ [ 1, 2, 3 ] }bias={ 0.001 }/>
</AccumulativeShadows>
  1. 接触阴影ContactShadows
const {position: cs_position,color: cs_color,opacity: cs_opacity,blur: cs_blur,
} = useControls('ContactShadows', {position: { value: { x: 0, y: - 0.99 }, step: 0.01, joystick: 'invertY' },color: '#000000',opacity: { value: 0.5, min: 0, max: 1 },blur: { value: 1, min: 0, max: 10 },clickMe: button(() => console.log('ok'))
})<ContactShadowsposition={ [cs_position.x, cs_position.y, 0] }scale={ 10 }resolution={ 128 }far={ 5 }color={ cs_color }blur={ cs_blur }opacity={ cs_opacity }
/>

3. 天空盒

<Sky distance={20} />

4. 场景HDR文件

HDR文件下载:https://polyhaven.com/

<Environmentbackgroundfiles={ '/industrial.hdr' }// ground={{//   radius: 1,//   scale: 100,//   height: 0// }}// preset="apartment" 预设场景
/>

通过suspend-react,可将Environment转为异步组件,支持Suspense的方式调用

import { suspend } from 'suspend-react'
const city = import('@pmndrs/assets/hdri/city.exr').then((module) => module.default)<Environment files={suspend(city)} />

四、Load Models

1. useLoader

import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js";const modelCyberpunk = useLoader(GLTFLoader, './cyberpunk.glb');

自定义加载器

https://threejs.org/docs/#examples/en/loaders/DRACOLoader

Draco是一个用于压缩和解压缩 3D 网格和点云的开源库。压缩后的几何图形可以明显更小,但代价是客户端设备上需要额外的解码时间。

const modelCyberpunk = useLoader(GLTFLoader, './cyberpunk.glb', loader => {const dracoLoader = new DRACOLoader()dracoLoader.setDecoderPath('./draco/')loader.setDRACOLoader(dracoLoader);
});

2. Suspense

<Suspense fallback={<PlaceHolder scale={5}/>}><ModelCyberpunk />
</Suspense>

PlaceHolder.tsx

const PlaceHolder = (props: MeshProps) => {return <mesh {...props}><boxGeometry /><meshStandardMaterial wireframe={true} color={ 'red' } /></mesh>
}export default PlaceHolder;

3. useGLTF

Secondary Encapsulation of useLoadler(useLoadler的二次封装)

export declare function useGLTF<T extends string | string[]>(path: T, useDraco?: boolean | string, useMeshOpt?: boolean, extendLoader?: (loader: GLTFLoader) => void): T extends any[] ? import("three-stdlib").GLTF[] : import("three-stdlib").GLTF;

可选配置:useDraco,useMeshOpt,extendLoader

Extend the useGLTF return value type(对useGLTF 的返回值类型进行拓展)

declare type GLTFEnhance = import('three-stdlib').GLTF & {nodes: Record<string, import("three").Mesh>;materials: Record<string, import("three").MeshStandardMaterial>;
};const { nodes, materials } = useGLTF('/cyberpunk.glb', true) as C_GLTF;

GLTF 预加载(preload)

// Remember to write outside the component.
useGLTF.preload('/cyberpunk.glb')

4. GLTF Clone(模型克隆)

Object3D.clone()

/*** Returns a clone of `this` object and optionally all descendants.* @param recursive If true, descendants of the object are also cloned. Default `true`** clone(recursive?: boolean): this;*/
<primitive object={scene.clone()}></primitive>

Clone Component

https://github.com/pmndrs/drei#clone

Declarative abstraction around THREE.Object3D.clone. This is useful when you want to create a shallow copy of an existing fragment (and Object3D, Groups, etc) into your scene, for instance a group from a loaded GLTF. This clone is now re-usable, but it will still refer to the original geometries and materials.

import {Clone} from "@react-three/drei";<group {...props} dispose={null}><Clone object={scene.clone()} position-x={ -10 }></Clone><Clone object={scene.clone()} position-x={ 0 }></Clone><Clone object={scene.clone()} position-x={ 10 }></Clone>
</group>

5. GLTF Animation

const { animations: gAnimations, scene} = useGLTF('./dog.glb', true) as GLTFEnhance;
const { actions } = useAnimations(gAnimations, scene);useEffect(() => {const play_dead =  actions["0|play_dead_0"]!const rollover =  actions["0|rollover_0"]!const shake =  actions["0|shake_0"]!const sitting =  actions["0|sitting_0"]!const standing =  actions["0|standing_0"]!shake.play();window.setTimeout(() => {rollover.play();rollover.crossFadeFrom(shake, 1, false)}, 10000)}, []);

useController

const { animations: gAnimations, scene
} = useGLTF('./dog.glb', true) as GLTFEnhance;const { actions, names } = useAnimations(gAnimations, scene);
const { animationName } = useControls({ animationName: { options: names } })useEffect(() => {const action = actions[animationName]!action.fadeIn(0.5).play()return () => { action.fadeOut(0.5) }
}, [animationName]);

6. Text3D

Documentation:https://github.com/pmndrs/drei#text3d

Example:

const [ matcapTexture ] = useMatcapTexture('3E2335_D36A1B_8E4A2E_2842A5', 256);<Text3Dfont={'./Regular.json'}size={ 0.75 }height={ 0.2 }curveSegments={ 12 }bevelEnabled={ true }bevelThickness={ 0.02 }bevelSize={ 0.02 }bevelOffset={ 0 }bevelSegments={ 5 }
>

The purpose of bevel-ralated properties is to make the font smoother.

bevel 的作用是让字体变得更加圆滑。

font属性需要填写一个被称作 typeface.json的字体文件,可在这个网站 https://gero3.github.io/facetype.js/ 将原始的ttf文件经过转化后得到。

The font props requires filling in a font file called typeface.json,which can be obtained by converting the orignal ttf file on https://gero3.github.io/facetype.js website.

7. useMatcapTexture

https://github.com/pmndrs/drei#usematcaptexture

The built in Texture can use in testing, not in the production environment.

内置的Texture,可用于测试,别使用在生产环境。

/*** The name of seconds parameters is format, we can choose between 64, 128, 256, 512, 1024* In our case, 256 is more than enough and you should try to use the smallest possible size   for performance reasons.*/
const [ matcapTexture ] = useMatcapTexture('3E2335_D36A1B_8E4A2E_2842A5', 256);

8. Multiple model processing

You shoud write the geometry, materal in mesh property when repeatedly rendering a model of the same geometry with the same materal. It performance better this way.

{[...Array(100)].map((_, index) =><meshkey={new Date().toString() + index}position={[(Math.random() - 0.5) * 10,(Math.random() - 0.5) * 10,(Math.random() - 0.5) * 10,]}scale={0.2 + Math.random() * 0.2}rotation={[Math.random() + Math.PI,Math.random() + Math.PI,Math.random() + Math.PI,]}geometry={torusGeometry}material={material}><torusGeometry args={[1, 0.6, 16, 32]} /><meshMatcapMaterial matcap={matcapTexture}/></mesh>)
}

↓↓↓

const Text3DHello: FC = memo(() => {const [matcapTexture] = useMatcapTexture('3E2335_D36A1B_8E4A2E_2842A5', 256);const [torusGeometry, setTorusGeometry] = useState<TorusGeometry>();const [material, setMaterial] = useState<MeshMatcapMaterial>();return <><torusGeometry ref={(torusGeometry) => setTorusGeometry(torusGeometry!)} args={[1, 0.6, 16, 32]} /><meshMatcapMaterial ref={(material) => setMaterial(material!) } matcap={matcapTexture}/><Center><Text3Dfont={'./Regular.json'}size={0.75}height={0.2}curveSegments={12}bevelEnabled={true}bevelThickness={0.02}bevelSize={0.02}bevelOffset={0}bevelSegments={5}>你好,React Three Fiber !<meshMatcapMaterial matcap={matcapTexture}/></Text3D></Center>{[...Array(100)].map((_, index) =><meshkey={new Date().toString() + index}position={[(Math.random() - 0.5) * 10,(Math.random() - 0.5) * 10,(Math.random() - 0.5) * 10,]}scale={0.2 + Math.random() * 0.2}rotation={[Math.random() + Math.PI,Math.random() + Math.PI,Math.random() + Math.PI,]}geometry={torusGeometry}material={material}/>)}</>
});

The better approach is to use OOP.

import {FC, memo, useEffect} from "react";
import {Center, Text3D, useMatcapTexture} from "@react-three/drei";
import {MeshMatcapMaterial, TorusGeometry} from "three";const torusGeometry = new TorusGeometry(1, 0.6, 16, 32);
const material = new MeshMatcapMaterial();const Text3DHello: FC = memo(() => {const [matcapTexture] = useMatcapTexture('3E2335_D36A1B_8E4A2E_2842A5', 256);useEffect(() => {matcapTexture.needsUpdate = true;material.matcap = matcapTexture;material.needsUpdate = true;}, [matcapTexture]);return <><Center><Text3Dfont={'./Regular.json'}size={0.75}height={0.2}curveSegments={12}bevelEnabled={true}bevelThickness={0.02}bevelSize={0.02}bevelOffset={0}bevelSegments={5}>你好,React Three Fiber !<meshMatcapMaterial matcap={matcapTexture}/></Text3D></Center>{[...Array(100)].map((_, index) =><meshkey={new Date().toString() + index}position={[(Math.random() - 0.5) * 10,(Math.random() - 0.5) * 10,(Math.random() - 0.5) * 10,]}scale={0.2 + Math.random() * 0.2}rotation={[Math.random() + Math.PI,Math.random() + Math.PI,Math.random() + Math.PI,]}geometry={torusGeometry}material={material}/>)}</>
});export default Text3DHello;

Use useFrame and useRef to add animation.

const donuts = useRef<Mesh[]>([]);useFrame((_, delta) => {for (const donut of donuts.current) donut.rotation.y += delta * 0.5
})// ...
<mesh ref={(mesh) => { donuts.current[index] = mesh! }}
// ...

or use group tag**(not recommanded)**

const donutsGroup = useRef<Group>(null!);useFrame((_, delta) => {for (const donut of donutsGroup.current.children) donut.rotation.y += delta * 0.1
}<group ref={ donutsGroup }>{ [...Array(100)].map((_, index) => <mesh // ... }

五、Mouse Event

1. EventHandler

const eventHandler = (event: ThreeEvent<MouseEvent>) => {console.log('event.uv', event.distance) // distance between camera and hit point.console.log('event.uv', event.uv)console.log('event.point', event.point) // Hit point coordinates (坐标).console.log('event.object', event.object)console.log('event.eventObject', event.eventObject) // Usually, eventObject is the same as objectconsole.log('event.x', event.x) // 2D Screen coordinates of the pointerconsole.log('event.y', event.y)console.log('event.shiftKey', event.shiftKey)console.log('event.ctrlKey', event.ctrlKey)console.log('event.metaKey', event.metaKey) // Click while holding down command / win key.
}

2. Event Kind

  • onClick

    • CLICK or CLICK with CTRL、SHIFT、COMMAND(WIN)、ALT
    • shiftKey,ctrlKey,metaKey,altKey
  • onContextMenu

    • RIGHT CLICK or CTRL + LEFT CLICK.
    • On a mobile, by pressing down for some time.
  • onDoubleClick

    • It works bisically the same as onClick.
    • The delay between the first and second click/tap is defined by the OS
  • onPointerUp

  • onPointerDown

  • onPointerOver and onPointerEnter

    • When the cursor or finger just went above the object
  • onPointerMove

  • onPointerMissed

    • When the user clicks outside of the object. ( Cannot get the event.object parameter ).

六、Post Processing

1. Install

We need tow dependencies,@react-three/postprocessing,postprocesssing, But for now, the only we neeed to install is @react-three/postprocessing since the dependency will also install postprocesssing.

"@react-three/drei": "^9.85.1",
"@react-three/fiber": "^8.14.2",
"@react-three/postprocessing": "2.6",
"postprocessing": "~6.31.2",
"r3f-perf": "^7.1.2",
"three": "~0.151.0",
"three-stdlib": "^2.27.0"

2. multisampling 多重采样

The default value is 8.

<EffectComposer multisampling={16} />

3. vignette 晕映

The default effect is add a black mask around the sceen.

<Vignette offset={0.3} darkness={0.9} />

You can specify the blending(混合、交融) method.

import { BlendFunction } from "postprocessing";
<Vignetteoffset={0.3}darkness={0.9}blendFunction={ BlendFunction.ALPHA }
/>

4. Glitch 失灵

Create snowflake(雪花) glitch effect like an old-fashioned TV.

<Glitch delay={ new Vector2(1, 1) } mode={ GlitchMode.SPORADIC } />

Delay attribute reviews a value of type Vector2.It represents the delay time for the horizontal and vertical axes.

The same effect to other attributes.

delay?: import("three").Vector2;
duration?: import("three").Vector2;
strength?: import("three").Vector2;

Effect Mode

mode: typeof GlitchMode[keyof typeof GlitchMode];export enum GlitchMode {DISABLED,SPORADIC,CONSTANT_MILD,CONSTANT_WILD,
}

5. Noise 噪点

<Noise blendFunction={ BlendFunction.SOFT_LIGHT } premultiply  // effect overlay
/>

BlendFunction

BlendFunction.OVERLAY // 叠加
BlendFunction.SCREEN  // It doesn't work well in bright scenes
BlendFunction.SOFT_LIGHT
BlendFunction.AVERAGE

6. Bloom

Bloom can be used to build an object glow(发光,同luminescence)effect

1、Set material attriblue.

Set larger value for color attriblue.

<meshStandardMaterial color={ [ 1.5 * 30, 1 * 30, 4 * 30 ] } toneMapped={ false } 
/>

Or set standard color, and set emissive attriblue and emissiveIntensity attibute.

<meshStandardMaterial color={ 'white' } emissive={ 'yellow' } emissiveIntensity={ 10 } toneMapped={ false } 
/>

2、Set Bloom effect component attriblue.

<BloommipmapBlur={ true } // always trueintensity={ 1 }luminanceSmoothing={ 2 } // 滤波luminanceThreshold={ 10 } // 阈值
/>

7. DepthOfField 景深

<DepthOfFieldfocusDistance={ 0.025 }focalLength={ 0.025 }bokehScale={ 6 }
/>

七、Physics

1. Installation

pnpm install @react-three/rapier

2. RigidBody:刚体

  • colliders:对撞机,设置刚体碰撞形状,ball 球,cuboid 矩形,hull Mesh的船体形状,trimesh Mesh网线形状

    export declare type RigidBodyAutoCollider = "ball" | "cuboid" | "hull" | "trimesh" | false;
    

Scene Example:

<Physics debug={true}><RigidBody colliders={'ball'} type={"dynamic"}><mesh castShadow={true} position={[0, 10, 0]}><sphereGeometry /><meshStandardMaterial color={'orange'} /></mesh></RigidBody><RigidBody colliders={'trimesh'}><mesh castShadow={true} position={[0, 1, 0]} rotation={[Math.PI * 0.5, 0, 0]}><torusGeometry args={[1, 0.5, 16, 32]} /><meshStandardMaterial color={'mediumpurple'} /></mesh></RigidBody><RigidBody type={"fixed"}><mesh receiveShadow={true} position={[0, 0, 0]} scale={1}><boxGeometry args={[10, 0.5, 10]}/><meshStandardMaterial color={"greenyellow"}/></mesh></RigidBody></Physics>

You can use CuboidCollider Component to add rigid body shape manually.

<RigidBody colliders={false} position={[0, 1, 0]} rotation={[Math.PI / 2, 0, 0]}><CuboidCollider args={[1.5, 1.5, 0.5]} /><CuboidCollider args={[1, 1, 1]} /><mesh castShadow={true}><torusGeometry args={[1, 0.5, 16, 32]} /><meshStandardMaterial color={'mediumpurple'} /></mesh>
</RigidBody>

BallCollider, the ball shape of rigid bidy.

<RigidBody colliders={false} position={[0, 1, 0]} rotation={[Math.PI / 2, 0, 0]}><BallCollider args={[1.5]} /><mesh castShadow={true}>n<torusGeometry args={[1, 0.5, 16, 32]} /><meshStandardMaterial color={'mediumpurple'} /></mesh>
</RigidBody>

3. Controll rigidbody movement

const cubeRigid = useRef<RapierRigidBody>(null!);const { camera } = useThree();const cubeJump = (event: ThreeEvent<MouseEvent>) => {cubeRigid.current.applyImpulse({ x: 0, y: 2, z: 0 }, false)cubeRigid.current.applyTorqueImpulse({ x: 0, y: 1, z: 0 }, false)const { eventObject } = event;// console.log(eventObject.position)const [epx,epy,epz] = eventObject.positioncamera.position.set(epx, epy - 4, epz + 4);camera.rotation.set(0, 0, 0);
}<Physics debug={true}><RigidBodycolliders={'cuboid'}type={"dynamic"}ref={cubeRigid}><meshcastShadow={true}position={[0, 10, 0]}onClick={cubeJump}><boxGeometry/><meshStandardMaterial color={'orange'} /></mesh></RigidBody><RigidBody type={"fixed"}><mesh receiveShadow={true} position={[0, 0, 0]} scale={1}><boxGeometry args={[10, 0.5, 10]}/><meshStandardMaterial color={"greenyellow"}/></mesh></RigidBody></Physics>

4. grvity 重力

You can set the gravity size and direction.

<Physicsdebug={true}gravity={[0, -1.6, 0]}
>

5. gravityScale,restitution,friction

  • gravityScale 重力倍率
  • restitution 恢复原状
  • friction 摩擦力(摩擦力是两个对象作用)
<RigidBodycolliders={'cuboid'}type={"dynamic"}ref={cubeRigid}gravityScale={ 1 }restitution={ 1 }
>

6. RigidBody mass 刚体重力

const cubeRigid = useRef<RapierRigidBody>(null!);
const cubeMesh = useRef<Mesh>(null!);
const cubeJump = (_: ThreeEvent<MouseEvent>) => {const mass = cubeRigid.current.mass();cubeRigid.current.applyImpulse({ x: 0, y: 5 * mass, z: 0 }, false)cubeRigid.current.applyTorqueImpulse({ x: 0, y: 1 * mass, z: 0 }, false)
}
return <Physicsdebug={true}gravity={[0, -8, 0]}
><RigidBodycolliders={false}type={"dynamic"}ref={cubeRigid}gravityScale={ 1 }restitution={ 1 }friction={1}><CuboidColliderargs={[0.5, 0.5, 0.5]}position={[0, 10, 0]}mass={10}/><meshref={cubeMesh}castShadow={true}position={[0, 10, 0]}onClick={cubeJump}><boxGeometry/><meshStandardMaterial color={'orange'} /></mesh></RigidBody>
</Physics>

这篇关于R3F(React Three Fiber)基础篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/744275

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo