>웹 프론트엔드 >JS 튜토리얼 >Three.js와 사용자 정의 프래그먼트 셰이더를 사용하여 3D 지구 모델 주변의 현실적인 분위기를 어떻게 시뮬레이션할 수 있습니까?

Three.js와 사용자 정의 프래그먼트 셰이더를 사용하여 3D 지구 모델 주변의 현실적인 분위기를 어떻게 시뮬레이션할 수 있습니까?

DDD
DDD원래의
2024-11-12 11:09:02468검색

How can I simulate a realistic atmosphere around a 3D Earth model using Three.js and a custom fragment shader?

Three.js는 브라우저에서 3D 그래픽을 생성하는 데 널리 사용되는 JavaScript 라이브러리입니다. 대화형 시각화 및 게임을 만드는 데 자주 사용됩니다. 3D 그래픽의 과제 중 하나는 구름이나 연기와 같이 불투명하지 않은 개체를 렌더링하는 것입니다. 이러한 물체는 빛을 통과시켜 더욱 부드럽고 사실적인 모습을 연출할 수 있습니다.

이 경우 목표는 지구 표현에 '대기' 효과를 추가하는 것입니다. 대기는 지구를 둘러싸고 빛을 산란시키는 반투명 레이어가 되어 더욱 사실적인 모습을 제공합니다.

이 효과를 얻기 위해 각 픽셀의 색상을 계산하는 프래그먼트 셰이더를 만듭니다. 대기에서의 위치와 광원의 방향에 따라 대기에서. 프래그먼트 셰이더는 "대기 산란"이라는 기술을 사용하여 빛이 대기의 입자에 의해 산란되는 방식을 시뮬레이션합니다.

프래그먼트 셰이더 코드는 다음과 같습니다.

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

uniform vec3 lightDirection;
uniform sampler2D earthTexture;

varying vec2 vUv;
varying vec3 vNormal;

void main() {
  // Compute the surface normal at this position
  vec3 normal = normalize(vNormal);
  // Compute the direction from this point to the light source
  vec3 lightDir = normalize(lightDirection);
  // Compute the amount of light that is scattered in this direction
  float scattering = dot(normal, lightDir);
  // Compute the color of the atmosphere at this position
  vec3 color = texture2D(earthTexture, vUv).rgb * scattering;
  // Output the color
  gl_FragColor = vec4(color, 1.0);
}

이 프래그먼트 셰이더는 여러 입력을 받습니다:

  • lightDirection: 빛의 방향 source.
  • earthTexture: 지구를 나타내는 데 사용되는 텍스처.
  • vUv: 현재 픽셀의 텍스처 좌표.
  • vNormal: 현재 픽셀의 법선 벡터.

프래그먼트 셰이더는 먼저 현재 픽셀의 표면 법선을 계산합니다. 그런 다음 현재 픽셀에서 광원까지의 방향을 계산합니다. 이 두 값은 픽셀 방향으로 산란되는 빛의 양을 계산하는 데 사용됩니다.

그런 다음 프래그먼트 셰이더는 지구 텍스처의 색상에 다음을 곱하여 현재 픽셀의 대기 색상을 계산합니다. 산란의 양. 결과 색상은 프래그먼트 색상으로 출력됩니다.

이 프래그먼트 셰이더를 사용하려면 이를 사용하는 머티리얼을 생성해야 합니다. 다음은 대기 산란 조각 셰이더를 사용하는 재료의 예입니다.

const material = new THREE.ShaderMaterial({
  fragmentShader: `
    #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
    #else
    precision mediump float;
    #endif
    
    uniform vec3 lightDirection;
    uniform sampler2D earthTexture;
    
    varying vec2 vUv;
    varying vec3 vNormal;
    
    void main() {
      vec3 normal = normalize(vNormal);
      vec3 lightDir = normalize(lightDirection);
      float scattering = dot(normal, lightDir);
      vec3 color = texture2D(earthTexture, vUv).rgb * scattering;
      gl_FragColor = vec4(color, 1.0);
    }
  `,
  uniforms: {
    lightDirection: { value: new THREE.Vector3(0, 1, 0) },
    earthTexture: { value: new THREE.TextureLoader().load('earth.jpg') }
  }
});

이 재료는 두 가지 유니폼을 사용합니다.

  • lightDirection: 광원 방향.
  • earthTexture: 지구를 표현하는 데 사용되는 텍스처입니다.

재료는 각 방향으로 산란되는 빛의 양을 계산하기 위한 lightDirection 균일성. EarthTexture 유니폼을 사용하여 지구의 표면을 표현합니다.

이 머티리얼을 사용하려면 메시를 생성하여 머티리얼에 할당해야 합니다. 다음은 메쉬를 생성하고 이를 재질에 할당하는 방법에 대한 예입니다.

const geometry = new THREE.SphereGeometry(10, 32, 32);
const material = new THREE.ShaderMaterial({
  fragmentShader: `
    #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
    #else
    precision mediump float;
    #endif
    
    uniform vec3 lightDirection;
    uniform sampler2D earthTexture;
    
    varying vec2 vUv;
    varying vec3 vNormal;
    
    void main() {
      vec3 normal = normalize(vNormal);
      vec3 lightDir = normalize(lightDirection);
      float scattering = dot(normal, lightDir);
      vec3 color = texture2D(earthTexture, vUv).rgb * scattering;
      gl_FragColor = vec4(color, 1.0);
    }
  `,
  uniforms: {
    lightDirection: { value: new THREE.Vector3(0, 1, 0) },
    earthTexture: { value: new THREE.TextureLoader().load('earth.jpg') }
  }
});
const mesh = new THREE.Mesh(geometry, material);

이 코드는 반경 10, 세그먼트 32개, 링 32개의 구 형상을 생성합니다. 그런 다음 대기 산란 조각 셰이더를 사용하는 재료를 만듭니다. 마지막으로 메시를 생성하여 머티리얼에 할당합니다.

메시가 생성되면 장면에 추가할 수 있습니다. 다음은 장면에 메시를 추가하는 방법에 대한 예입니다.

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

uniform vec3 lightDirection;
uniform sampler2D earthTexture;

varying vec2 vUv;
varying vec3 vNormal;

void main() {
  // Compute the surface normal at this position
  vec3 normal = normalize(vNormal);
  // Compute the direction from this point to the light source
  vec3 lightDir = normalize(lightDirection);
  // Compute the amount of light that is scattered in this direction
  float scattering = dot(normal, lightDir);
  // Compute the color of the atmosphere at this position
  vec3 color = texture2D(earthTexture, vUv).rgb * scattering;
  // Output the color
  gl_FragColor = vec4(color, 1.0);
}

이 코드는 장면에 메시를 추가합니다. 이제 메시는 대기 산란 조각 셰이더를 사용하여 렌더링됩니다. 그 결과 지구를 둘러싸는 반투명 대기가 탄생하게 됩니다.

위 내용은 Three.js와 사용자 정의 프래그먼트 셰이더를 사용하여 3D 지구 모델 주변의 현실적인 분위기를 어떻게 시뮬레이션할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.