Three.js とカスタム フラグメント シェーダーを使用して、3D Earth モデルの周囲の現実的な雰囲気をシミュレートするにはどうすればよいですか?

DDD
リリース: 2024-11-12 11:09:02
オリジナル
427 人が閲覧しました

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 グラフィックスに関する課題の 1 つは、雲や煙などの不透明でないオブジェクトをレンダリングすることです。これらのオブジェクトは光を通過させるため、より柔らかく、よりリアルな外観を作成できます。

この場合の目標は、地球の表現に「雰囲気」効果を追加することです。大気は地球を囲み光を散乱させる半透明のレイヤーとなり、よりリアルな外観を与えます。

この効果を実現するには、各ピクセルの色を計算するフラグメント シェーダーを作成します。大気中の位置と光源の方向に基づいて大気中での位置を特定します。フラグメント シェーダーは、「大気散乱」と呼ばれる手法を使用して、大気中の粒子によって光が散乱する様子をシミュレートします。

フラグメント シェーダー コードは次のとおりです:

#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: 現在のピクセルの法線ベクトル。

フラグメント シェーダーはまず、現在のピクセルでのサーフェス法線を計算します。次に、現在のピクセルから光源までの方向を計算します。これら 2 つの値は、ピクセルの方向に散乱する光の量を計算するために使用されます。

次に、フラグメント シェーダーは、地球テクスチャの色に次の値を乗算して、現在のピクセルにおける大気の色を計算します。飛散量。結果のカラーはフラグメント カラーとして出力されます。

このフラグメント シェーダーを使用するには、それを使用するマテリアルを作成する必要があります。以下は、大気散乱フラグメント シェーダを使用するマテリアルの例です:

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') }
  }
});
ログイン後にコピー

このマテリアルは 2 つのユニフォームを取ります:

  • lightDirection: 光源への方向。
  • earthTexture: を表現するために使用されるテクスチャEarth.

マテリアルは、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 Earth モデルの周囲の現実的な雰囲気をシミュレートするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート