การเพิ่มพื้นผิว (Adding Textures)

การเพิ่มพื้นผิว Three.js

ในความที่แล้ว เราพูดถึงเนื้อหาประเภทต่างๆ ในบทความนี้ เราจะไปที่ กำลังพูดถึงพื้นผิวก่อนที่เราจะเริ่มต้น สร้างพื้นผิวเพื่อใช้กับพื้นผิวหรือเป็นภาพสะท้อนหรือการหักเหของแสง

หมายเหตุ: หลังจากใช้งานพื้นผิวครั้งแรกแล้ว ขนาด รูปแบบ และประเภทของพื้นผิวจะไม่สามารถเปลี่ยนแปลงได้ ให้เรียก .dispose() บนเท็กซ์เจอร์ แล้วสร้างตัวอย่างใหม่

ข้อกำหนดเบื้องต้น


ข้อกำหนดสำหรับบทความนี้คือ คุณควรได้ทำตามบทความ ภาพรวมของวัสดุ (Overview of Materials)  มาก่อน


Textures


เราจะต้องนำเข้า useLoader


เราจะปรับกล้องกลับลงไปที่ตำแหน่งเดิมด้วย

camera={{ position: [3, 3, 3] }}

มาเพิ่มเท็กซ์เจอร์ให้กับคิวบ์นี้กันเถอะ ลบโค้ดบางส่วน เพื่อกำจัดคุณสมบัติทั้งหมดที่เรานำไปใช้ล่าสุด

ที่โฟลเดอร์ public นำเข้าไฟล์รูปภาพ wood.jpg

และเราจะใช้ตัวโหลด useLoader เพื่อสร้างพื้นผิว ตัวโหลดประเภทแรกที่เราจะดูคือตัวโหลดพื้นผิว TextureLoader

จากนั้นเส้นทางที่คุณต้องการใช้กับ react ก็คือ เส้นทางที่สัมพันธ์กัน มาจากโฟลเดอร์ public และเลือกไฟล์เป็น wood.jpg

const texture = useLoader
    (THREE.TextureLoader,
      '/wood.jpg'
    );

มาตั้งค่าคุณสมบัติ map property เป็นพื้นผิวที่เราเพิ่งสร้างขึ้น โดยการเพิ่ม map={texture} ที่ meshPhysicalMaterial

     <meshPhysicalMaterial
        map={texture}
      />

ดังนั้นสิ่งที่เราต้องการทำคือรอจนกว่าพื้นผิวจะโหลดแล้วจึงแสดงผลส่วนประกอบ ดังนั้นเพื่อเลี่ยงการใช้ async ออกไป หรือใช้ความจริง เราสามารถใช้ส่วนประกอบตอบสนองในตัวที่เรียกว่า Suspense

import { useRef, Suspense } from 'react';

โดย Suspense component จะมี props ชื่อ fallback สามารถส่ง element บางอย่างเข้าไปเพื่อจะให้แสดงระหว่างที่รอ

<Suspense fallback={null}>
  <Box position={[0, 1, 0]} />
</Suspense>

ดังนั้นเราจึงมีเนื้อไม้ที่ยอดเยี่ยมในลูกบาศก์ของเรา โปรดจำไว้ว่า คุณสมบัติของวัสดุทั้งหมดที่เราพูดถึงในบทความที่แล้ว คุณสามารถใช้ได้ ดังนั้นหากคุณต้องการทำให้สิ่งนี้เป็นประกายหรือโปร่งใส คุณสามารถทำได้ทั้งหมดนอกเหนือจากพื้นผิว

เราจะเปลี่ยนประเภทของเรขาคณิตที่เราใช้เพื่อแสดงให้คุณเห็นว่าพื้นผิวบนทรงกลมเป็นอย่างไร

ตัวอย่างเช่น ทำให้เรื่องนี้ราบรื่นขึ้นหน่อย

<sphereBufferGeometry />
<sphereBufferGeometry args={[1,100,100]}/>

คุณจะเห็นว่าพื้นผิวกำลังจับคู่อย่างสวยงาม

Background

ที่โฟลเดอร์ public นำเข้าไฟล์รูปภาพ sky.jpg

ตอนนี้เรามาดูกันว่าเราสามารถใช้พื้นผิวกับพื้นหลัง background ของเราได้หรือไม่ เราจะสร้างองค์ประกอบใหม่ที่เรียกว่า background

const Background = props => {
  const texture = useLoader(
    THREE.TextureLoader,
    '/sky.jpg'
  )
  return (
    <primitive
      attach='background'
      object={texture}
    />
  )
}

เพิ่ม Suspense 

<Suspense fallback={null}>
  <Background />
</Suspense>

ลบโค้ด หมอก (fog) ออก

<fog attach='fog' args={['white', 1, 10]} />

ที่โฟลเดอร์ public นำเข้าไฟล์รูปภาพ autoshop.jpg

ทดสอบเปลี่ยนภาพพื้นหลัง background

และเราจะใช้ Web Geo Kuprin หรือ Target เพื่อจัดรูปแบบอย่างถูกต้อง กระบวนการเดียวกันที่นี่

const Background = props => {
  const texture = useLoader(
    THREE.TextureLoader,
    '/autoshop.jpg'
  );

  const { gl } = useThree();

  const formatted = new THREE.WebGLCubeRenderTarget(
    texture.image.height
  ).fromEquirectangularTexture(gl, texture)

  return (
    <primitive
      attach='background'
      object={formatted}
    />
  )
}


ผลลัพธ์การทำงาน


โค้ด

import './App.css';
import {
  Canvas,
  useFrame,
  useThree,
  extend,
  useLoader
} from 'react-three-fiber';
import { useRef, Suspense } from 'react';
import {
  OrbitControls
} from 'three/examples/jsm/controls/OrbitControls';
import * as THREE from 'three'

extend({ OrbitControls });

const Orbit = () => {
  const { camera, gl } = useThree();
  return (
    <orbitControls args={[camera, gl.domElement]} />
  )
}

const Box = props => {
  const ref = useRef();
  const texture = useLoader(
    THREE.TextureLoader,
    '/wood.jpg'
  );
  useFrame(state => {
    ref.current.rotation.y += 0.01;
    ref.current.rotation.x += 0.01;
  });

  return (
    <mesh
      ref={ref}
      {...props}
      castShadow
    // receiveShadow
    >
      <sphereBufferGeometry args={[1, 100, 100]} />
      <meshPhysicalMaterial
        map={texture}
      />
    </mesh>
  )
}

const Background = props => {
  const texture = useLoader(
    THREE.TextureLoader,
    '/autoshop.jpg'
  );

  const { gl } = useThree();

  const formatted = new THREE.WebGLCubeRenderTarget(
    texture.image.height
  ).fromEquirectangularTexture(gl, texture)

  return (
    <primitive
      attach='background'
      object={formatted}
    />
  )
}

const Floor = props => {
  return (
    <mesh {...props} receiveShadow>
      <boxBufferGeometry args={[20, 1, 10]} />
      <meshPhysicalMaterial
      />
    </mesh>
  )
}

const Bulb = props => {
  return (
    <mesh {...props}>
      <pointLight castShadow />
      <sphereBufferGeometry args={[0.2, 20, 20]} />
      <meshPhongMaterial emissive='yellow' />
    </mesh>
  )
}

function App() {

  return (
    <div style={{ height: '100vh', width: '100vw' }}>
      <Canvas
        shadowMap
        style={{ background: 'black' }}
        camera={{ position: [3, 3, 3] }}
      >
        <ambientLight intensity={0.2} />
        <Bulb position={[0, 3, 0]} />
        <Orbit />
        <axesHelper args={[5]} />
        <Suspense fallback={null}>
          <Box position={[0, 1, 0]} />
        </Suspense>
        <Suspense fallback={null}>
          <Background />
        </Suspense>
        <Floor position={[0, -0.5, 0]} />
      </Canvas>
    </div>
  );
}

export default App;

ดูผ่านเว็บไซต์ได้ที่

Leave a Reply

Your email address will not be published. Required fields are marked *