😄

@react-threeで簡単なオブジェクトを作ってみるメモ

に公開

@react-threeで簡単なオブジェクトを作ってみるメモ

サンプルの物をちょっといじっただけですが(;^ω^)

各コンポーネントについて

Three.js関連のもののみ調べました

Canvas

  • シーン、レンダラーをカプセル化したコンポーネント
  • 子コンポーネントにカメラやライト、メッシュを配置することができる
  • 親要素の幅、高さに従う

プロパティ一覧

<Canvas>
	{children}
</Canvas>

OrbitControls

  • カメラを操作することができる
  • minDistance: ドリー・イン(カメラが被写体に近づく意味=視点が前進)できる距離
  • maxDistance: ドリー・アウト(カメラが被写体から離れる)できる距離

プロパティ一覧

<OrbitControls minDistance={12} maxDistance={200} />

mesh

  • 3Dオブジェクトを表示するコンポーネント
  • three.jsのTHREE.Mesh()に相当し、JSX要素として呼び出すことができる

なぜグローバルに扱えるのかは今後調べる

プロパティ一覧

<mesh>
	{children}
</mesh>

sphareGeometry

  • 球面のジオメトリを定義する
  • argsは左から順に
    • 半径: 球体の大きさを定義する。
    • 幅セグメント : 水平方向の分割数を定義しているらしい。値が大きいほど滑らかになるが、処理負荷も増える
    • 高さセグメント: 垂直方向の分割数。上に同じく。
<sphereGeometry 
	args={[3, 64, 64]}
	/>

capsuleGeometry

  • カプセル型のジオメトリを定義する
  • argsは左から順に
    • 半径: カプセルの半径を定義する。
    • 高さ: 円筒部分の高さを定義する。
    • キャップセグメント : カプセルの両端の半球部分の分割数を定義しているらしい。値が大きいほど滑らかになるが(ポリゴン数も増加)、処理負荷も増える
    • 放射状セグメント: カプセルの周囲方向の分割数を定義。上に同じく。
<capsuleGeometry 
  args={[1, 5, 64, 64]}
	/>

meshStandardMaterial

  • 物理ベースのレンダリング原理(PBR?)に基づいたマテリアル
  • 光学的性質をシミュレートする
  • color: 色を指定。デフォルトは"white"。16進数のカラーコードを指定することで色を変えられる。
  • リアルな反射や屈折を表現することができる
  • roughness: 粗さ。0.0 ~1.0の間で指定する
  • metalness: 金属度

プロパティ一覧

<meshStandardMaterial 
	color={"hotpink"}
	metalness={0.7}
	roughness={0.5}
	/>

ambientLight

  • 環境光を定義する
  • itensity: 光の強さ
<ambientLight intensity={Math.PI / 2} />

spotLight

  • position: スポットライトの3D空間における位置

  • 値が小さいほど狭く集中した光、大きいほど拡散した光になる。→ステージのスポットライトと同じようなものなのだろうか?

  • angle: ライトのビーム角度(ラジアン)

  • penumbra: スポットライトの端(エッジ)のぼかし具合

    • 0: はっきりとした硬い光の境界線
    • 1: 完全にソフトな光の減衰
  • decay: 距離による光の減衰率

  • itensity: 省略

<spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />

pointLight

  • 空間の一点から全方向に均等に光を投射する光源

  • 電球や電灯に近い光

  • 距離減衰がある

  • position: 省略

  • decay: 省略

  • itensity: 省略

<pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />

各光源の違い

  • SpotLight(スポットライト): 特定の方向に円錐状の光を放射。舞台照明のスポットライトのような効果
  • DirectionalLight(平行光源): 太陽光のように平行に進む光線を発生。方向は持つが特定の位置は持たない
  • AmbientLight(環境光): 特定の方向や位置を持たず、シーン全体を均等に照らす
  • HemisphereLight(半球光): 空と地面からの光を模倣し、上下で異なる色の光を放射

今回のコード

"use client"

import * as THREE from "three"
import { Canvas, ThreeElements } from "@react-three/fiber";
import { useRef } from "react";
import { OrbitControls } from "@react-three/drei";

const Ball = (props: ThreeElements["mesh"]) => {
  const meshRef = useRef<THREE.Mesh>(null)

  return (
    <mesh
      {...props}
      ref={meshRef}
      >
      <sphereGeometry 
        args={[3, 64, 64]}
        />
      <meshStandardMaterial 
        color={"hotpink"}
        metalness={0.7}
        roughness={0.5}
        />
    </mesh>
  )
}

const Medicine = (props: ThreeElements["mesh"]) => {
  const meshRef = useRef<THREE.Mesh>(null)

  return (
    <mesh 
      {...props}
      ref={meshRef}
      >
      <capsuleGeometry 
        args={[1, 5, 64, 64]}
        />
      <meshStandardMaterial 
        color={"hotpink"}
        metalness={0.7}
        roughness={0.5}
        />
    </mesh>
  )
}

export default function Home() {
  return (
	<Canvas>
	  <ambientLight intensity={Math.PI / 2} />
	  <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />
	  <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
	
	  <Ball position={[1, 0, 0]} />
	  <Medicine position={[6, 0, 0]} />
	  <OrbitControls minDistance={12} maxDistance={200} />
	</Canvas>
  );
}

実際の画面

metalness, roughnessあり
metal.png

なし
not-metal.png

最後に

間違っていることがあれば、コメントに書いていただけると幸いです。
よろしくお願いいたします。

GitHubで編集を提案

Discussion