이미지 텍스처를 사용하는 오브젝트에 빨간색을 오버레이하려면, 셰이더 머티리얼을 사용하거나 기존 텍스처에 빨간색 레이어를 추가하는 방법을 사용할 수 있습니다. 여기서는 셰이더 머티리얼을 사용하는 방법을 설명하겠습니다. 이 방법은 더 유연하고 성능이 좋습니다.

Three.js를 사용하여 다음과 같이 구현할 수 있습니다:

  1. 먼저, 커스텀 셰이더 머티리얼을 생성합니다.
  2. 이 머티리얼에서 오리지널 텍스처와 빨간색 오버레이를 블렌딩합니다.
  3. hit 상태에 따라 오버레이의 강도를 조절합니다.

여기 수정된 OpponentHead 컴포넌트입니다:

jsx
Copy
import React, { forwardRef, useRef, useEffect, useMemo } from 'react'
import { useFrame } from '@react-three/fiber'
import { useGLTF } from '@react-three/drei'
import * as THREE from 'three'

const OpponentHead = forwardRef(({ position, rotation, scale, name, hit }, ref) => {
  const localRef = useRef()
  const { scene, materials } = useGLTF('/models/opponent-head.glb')

  const uniforms = useMemo(() => ({
    texture: { value: null },
    hitIntensity: { value: 0 }
  }), [])

  const vertexShader = `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `

  const fragmentShader = `
    uniform sampler2D texture;
    uniform float hitIntensity;
    varying vec2 vUv;
    void main() {
      vec4 texColor = texture2D(texture, vUv);
      vec3 red = vec3(1.0, 0.0, 0.0);
      gl_FragColor = vec4(mix(texColor.rgb, red, hitIntensity), texColor.a);
    }
  `

  useEffect(() => {
    scene.traverse((child) => {
      if (child.isMesh) {
        const originalTexture = child.material.map

        const shaderMaterial = new THREE.ShaderMaterial({
          uniforms: uniforms,
          vertexShader: vertexShader,
          fragmentShader: fragmentShader,
          transparent: true,
        })

        uniforms.texture.value = originalTexture
        child.material = shaderMaterial
      }
    })
  }, [scene, uniforms, vertexShader, fragmentShader])

  useEffect(() => {
    uniforms.hitIntensity.value = hit ? 0.5 : 0// Adjust 0.5 to control the intensity of red
  }, [hit, uniforms])

  useFrame(() => {
    if (localRef.current && position) {
      localRef.current.position.set((position.x - 0.5) * 5, -(position.y - 0.5) * 5, -(position.z+0.01) * 15)
      if (rotation) {
        localRef.current.rotation.set(rotation[0], rotation[1], rotation[2]);
      }
    }
  })

  return <primitive ref={localRef} object={scene} scale={scale} name={name} />
})

OpponentHead.displayName = "OpponentHead";

export default OpponentHead;

이 수정된 버전에서는:

  1. 커스텀 셰이더를 정의하여 오리지널 텍스처와 빨간색을 블렌딩합니다.
  2. uniforms를 사용하여 텍스처와 hit 강도를 셰이더에 전달합니다.
  3. hit prop에 따라 hitIntensity uniform을 업데이트합니다.
  4. 모델의 각 메시에 대해 원본 머티리얼을 커스텀 셰이더 머티리얼로 교체합니다.

이 방법을 사용하면 오리지널 텍스처를 유지하면서 히트 상태에 따라 빨간색 오버레이를 부드럽게 적용할 수 있습니다. hitIntensity 값을 조정하여 빨간색의 강도를 제어할 수 있습니다.

이 접근 방식은 성능이 좋고 유연하지만, 셰이더 프로그래밍에 대한 이해가 필요합니다. 필요에 따라 셰이더 코드를 수정하여 다양한 효과를 만들 수 있습니다.