70

Three.js で、2 つの球体を表示する小さなプログラムを作成しようとしています。sphere1 の半径は常に 1.0 ですが、sphere2 の半径は 0.5 から 1.5 の間で振動するはずです。各球体は透明 (不透明度: 0.5) であるため、大きな球体に含まれる小さな球体を見ることができます。もちろん、sphere2 の半径が変わると、「小さい」と「大きい」の役割も変わります。

ここでの問題は、Three.js が、プログラムで定義した最初の球体を透明にしますが、2 番目の球体を透明にしないことです。最初に sphere1 を定義すると透明になりますが、sphere2 は完全に不透明になります。最初に sphere2 を定義すると、これが透明になります。それらをシーンに追加する順序は重要ではありません。

何が起こっているかを示す最小限のプログラムを以下に含めます (アニメーションなし)。現在の状態では、sphere1 のみが表示され、透明ではありません。sphere2 の前に sphere1 を定義すると、sphere1 は透明になりますが、sphere2 は透明ではなくなります。sphere2 の半径を 1.2 に変更すると、sphere1 が非表示になります。

両方の球体を透明にする方法はありますか?

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

camera.position.set(0, 0, 3);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

var ambient = new THREE.AmbientLight( 0x555555 );
scene.add(ambient);

var light = new THREE.DirectionalLight( 0xffffff );
light.position = camera.position;
scene.add(light);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Definition 2
var geometry2 = new THREE.SphereGeometry(0.8,32,24);
var material2 = new THREE.MeshLambertMaterial({color: 0x0000ff, transparent: true, opacity: 0.5});
var sphere2 = new THREE.Mesh(geometry2, material2);

// Definition 1
var geometry1 = new THREE.SphereGeometry(1.0,32,24);
var material1 = new THREE.MeshLambertMaterial({color: 0x00ff00, transparent: true, opacity: 0.5});
var sphere1 = new THREE.Mesh(geometry1, material1);

scene.add(sphere1);
scene.add(sphere2);

renderer.render(scene, camera);
4

3 に答える 3

173

両方の球体が透明であり、そのままです。起こっていることは、小さい方の球がまったくレンダリングされていないということです。

WebGL の透過性は扱いにくいものです。問題をグーグルで検索して、詳細を確認できます。

しかし、特に three.jsが透明性を処理する方法に関連する問題に遭遇しました。

three.jsのWebGLRendererは、カメラからの距離に基づいてオブジェクトを並べ替え、透明なオブジェクトを最も遠いものから最も近いものの順にレンダリングします。(これは重要なポイントです。オブジェクトをその位置に基づいて並べ替え、並べ替えられた順序でオブジェクトをレンダリングします。)

したがって、2 つの透明なオブジェクトを正しくレンダリングするには、後ろにあるオブジェクト (この場合は小さい方の球体) を最初にレンダリングする必要があります。そうしないと、深度バッファのためにまったくレンダリングされません。

しかし、あなたの場合、同じ場所にある 2 つの球体があるため、カメラから等距離にあります。それが問題です -- どちらを最初にレンダリングするか。それはトスアップです。

したがって、シーンを正しくレンダリングするには、小さい球を大きい球よりもカメラから離して配置する必要があります。

1 つの解決策は、小さい方の球体を少し後ろに移動することです。

別の解決策は、 を設定することrenderer.sortObjects = falseです。その後、オブジェクトはシーンに追加された順序でレンダリングされます。その場合は、小さい方の球体を最初にシーンに追加してください。

material1.depthWrite = false3 番目の解決策は、とを設定することmaterial2.depthWrite = falseです。

編集:

material.transparent = false(不透明なオブジェクト) を持つレンダリング可能なオブジェクトは、(透明なオブジェクト) を持つオブジェクトの前にレンダリングされますmaterial.transparent = true

したがって、4 つ目の解決策は、小さい方の球体を不透明にして、最初にレンダリングされるようにすることです。

r.71 の新機能:

現在、Object3D.renderOrder物件があります。オブジェクトの各クラス (不透明または透明) 内で、オブジェクトは で指定された順序でレンダリングされobject.renderOrderます。のデフォルト値はrenderOrderです0renderOrder子オブジェクトによって継承されないことに注意してください。レンダリング可能なオブジェクトごとに設定する必要があります。

同じ (タイ) を持つオブジェクトは、renderOrder上記のように深さでソートされます。

したがって、5 番目の解決策はrenderOrder = 1、より大きな球体に設定することです。これはおそらくあなたの場合の最良の解決策です。

three.js r.71

于 2013-04-14T03:30:45.137 に答える