[Three.js旅程講義ノート]23

19856 ワード

🙌🏻 この文章はThree.js Journeyの講義です.

23 Realistic Render


前の授業でハンバーガーを3つ食べました.jsにインポートすると、色出力が少しおかしいことがわかります.時々私たちは真実のレンダリングを望んでいます.特に、実際に使用している製品をウェブサイトに表示したい場合や、3 D芸術家として、最高の結果で仕事を表示したい場合は、このようにします.このレッスンでは、レンダリング品質を改善する方法について説明します.
前回のレッスンで作成したハンバーグを使用できますが、様々なテクスチャに適したモデルリポジトリのFlight Helmetで実習します.まず、starter packに球があります.照明を設定します.まずtestSphereのマテリアルをMeshStandardMaterialに変更し、照明を確認します.
new THREE.MeshStandardMaterial()

DirectionLightは1つしか使用しません.照明をより多く制御し、シャドウを生成するには、DirectionLightが重要です.
const directionalLight = new THREE.DirectionalLight('#ffffff', 1)
directionalLight.position.set(0.25, 3, - 2.25)
scene.add(directionalLight)

Three.js光強度のDefault valueは現実をうまく反映していない.これは重要ではないと思いますが、現実と標準の値を反映できれば、より良い選択になります.より現実的な値を適用するには、webGLReaderの物理CorrectLightsプロパティをtrueに変更する必要があります.
renderer.physicallyCorrectLights = true

Model


ライトが設定されているので今からモデルのロードを始めましょうまず、GLTFLADERをインスタンス化します.モデルは圧縮されていないのでDRACoLoaderは不要です.
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

const gltfLoader = new GLTFLoader();

gltfLoader.load("/models/FlightHelmet/glTF/FlightHelmet.gltf", (gltf) => {
  gltf.scene.scale.set(10, 10, 10);
  gltf.scene.position.set(0, -4, 0);
  gltf.scene.rotation.y = Math.PI * 0.5;
  scene.add(gltf.scene);
  gui
    .add(gltf.scene.rotation, "y")
    .min(-Math.PI)
    .max(Math.PI)
    .step(0.001)
    .name("rotation");
});

Environment map


弱いDirectionLightが1つしかないので、モデルを正確にチェックすることはできません.照明は環境マップで処理されます.私たちは材料の授業で環境地図を知った.環境地図は周囲を囲む写真のようだ.360度の写真かもしれないし、立方体の形をした6枚の写真かもしれない.環境図を使用して背景とモデルをマッピングします.

Load the environment map

/**
 * Environment map
 */
const environmentMap = cubeTextureLoader.load([
    '/textures/environmentMaps/0/px.jpg',
    '/textures/environmentMaps/0/nx.jpg',
    '/textures/environmentMaps/0/py.jpg',
    '/textures/environmentMaps/0/ny.jpg',
    '/textures/environmentMaps/0/pz.jpg',
    '/textures/environmentMaps/0/nz.jpg'
])

Apply the environment map to the background


環境マップをシーンの背景に追加するには、まず巨大な立方体を作成し、中からも立方体の一面が見えるように設定する必要があります.それからテクスチャを適用すればいいです.
scene.background = environmentMap

Apply the environment map to the model


リアルレンダリングのコアは、環境を介してモデルをマッピングすることです.EnvMapプロパティを使用して環境マッピングをMeshStandardMaterialに適用する方法を学習しました.問題は,我々のモデルが多くのメッシュから構成されていることである.継承クラス(メソッドやグループ、メッシュなど)を使用することができます.コールバックで処理するのではなく、updateAllMaterials関数を作成します.
const updateAllMaterials = () => {
  scene.traverse((child) => {
    console.log(child);
  });
};

子供はコンソールウィンドウで確認できます.実は私たちがやりたいのは子供たちをコンソールに撮るのではなく、環境地図を応用することです.環境地図を照明、カメラ、グループに適用するのは意味がありません.私たちはMeshに環境地図を適用したいだけです.
const updateAllMaterials = () => {
  scene.traverse((child) => {
    if (
      child instanceof THREE.Mesh &&
      child.material instanceof THREE.MeshStandardMaterial
    ) {
      child.material.envMap = environmentMap;
      child.material.envMapIntensity = 5;
    }
  });
};

Apply the environment map as default


environment mapを適用するより簡単な方法があります.シーンの環境プロパティを使用できます.もちろん、この方法では、シーン内で各マテリアル環境マップの強度を直接変更することはできません.
scene.environment = environmentMap

Renderer


色を操作する必要があります.これはWebGLReduserで作業できます.

Output encoding

outputEncodingプロパティ制御出力レンダリングエンコード.
renderer.outputEncoding = THREE.sRGBEncoding

もう一つの可能な価格はTHREE.GammaEncodingです.ガンマ符号化は、人間の目の感度に応じて、明暗値の記憶方式を最適化することによって色を記憶する方式である.sRGBE符号化を使用することは、一般値2.2のデフォルトガンマ係数を使用してガンマEncodeを行うことに相当する.より多くのものを制御できるので、ガンマ符号化はもっとよく聞こえますが、物理的には理想的ではありません.輝度を管理するには、いくつかのより良い方法があります.

Textures encoding


気づいたかもしれませんが、今は環境地図の色が少しおかしいです.これで満足できますが、まず正しい色を保つ方法を知っておく必要があります.問題は、レンダラー出力符号化がTHREEであることです.sRGBEncodingまた、デフォルトではEnvironment map textureはTHREEです.LinearEncodingです私たちが見えるすべてのテクスチャはTHREEですsRGBEは符号化されています.そうしないと、すべてのもののテクスチャがTHREEになります.LinearEncodeを使用してエンコードされます.
environmentMap.encoding = THREE.sRGBEncoding

Tone mapping


ToneマッピングはHDR値をLDR値に変換します.Tone mapping効果でよりリアルな結果が得られます.Toneマッピングを変更するには、WebGLReaderでToneマッピング属性を更新するだけです.可能な価格はいろいろあります.
  • THREE.NoToneMapping (default)
  • THREE.LinearToneMapping
  • THREE.ReinhardToneMapping
  • THREE.CineonToneMapping
  • THREE.ACESFilmicToneMapping
  • renderer.toneMapping = THREE.ACESFilmicToneMapping

    Toneマッピングの露出を変更することもできます.
    renderer.toneMappingExposure = 3

    Antialiasing


    ジオメトリのエッジを拡大すると、階段のような画像を別名と呼びます.今ではモデルの詳細が多いので大丈夫ですが、ピクセルスケールが1の画面でエッジを表示するとaliasingが表示されます.ピクセルレンダリングが発生すると、そのピクセルのどのオブジェクトがレンダリングされるかがテストされます.通常、エッジが画面のピクセルの垂直線と水平線に完全に整列していないという問題が発生します.簡単な解決策は、レンダリングの解像度を向上させることです.もちろん、これは簡単な方法ですが、パフォーマンスの問題を引き起こす可能性があります.もう1つの解決策はマルチサンプリングです.レンダリングの解像度は向上しますが、グラフィックのエッジでのみレンダリングできます.次に、画素値を平均し、最終画素値を得る.Three.jsにも多重サンプリングを適用できます!
    const renderer = new THREE.WebGLRenderer({
        canvas: canvas,
        antialias: true
    })
    反転を使用すると、リソースが消費されます.理想的には、ピクセルスケールが2未満の画面でのみアクティブにします.

    Shadows

    renderer.shadowMap.enabled = true
    renderer.shadowMap.type = THREE.PCFSoftShadowMap
    
    directionalLight.castShadow = true
    directionalLight.shadow.camera.far = 15
    directionalLight.shadow.mapSize.set(1024, 1024)
    
                child.castShadow = true
                child.receiveShadow = true
    

    Final tweaks


    Hamburger


    今やっと前回のレッスンで作ったハンバーガーを応用する時間になりました.
    gltfLoader.load(
        '/models/hamburger.glb',
        (gltf) =>
        {
            gltf.scene.scale.set(0.3, 0.3, 0.3)
            gltf.scene.position.set(0, - 1, 0)
            scene.add(gltf.scene)
    
            updateAllMaterials()
        }
    )

    拡大すると表面が熱くなる問題が発生します!これは陰影ニキビと呼ばれています.
    directionalLight.shadow.normalBias = 0.05