Transparente Objekte in Threejs

Ich versuche ein kleines Programm in Three.js zu schreiben, das zwei ineinander verschachtelte Kugeln zeigt. Der Radius von sphere2 soll zwischen 0.5 und 1.5 schwingen, während der Radius von sphere1 immer 1.0 ist. Jede Kugel ist transparent (Opazität: 0,5), so dass es möglich ist, die kleinere Kugel zu sehen, die in der größeren enthalten ist. Natürlich ändern sich die Rollen von “kleiner” und “größer”, wenn der Radius der Kugel 2 variiert.

Das Problem ist nun, dass Three.js die erste Sphäre, die ich in meinem Programm definiere, transparent macht, aber nicht die zweite. Wenn ich die erste Sphäre1 definiere, wird sie transparent, aber dann ist Sphäre2 vollständig undurchsichtig. Wenn ich die erste Sphäre2 definiere, dann ist dies die transparente Sphäre. Die Reihenfolge, in der sie zur Szene hinzugefügt werden, spielt keine Rolle.

Ich füge unten ein minimales Programm ein, das zeigt, was vor sich geht (ohne die Animation). In seinem aktuellen Zustand ist nur sphere1 sichtbar und nicht transparent. Wenn ich sphere1 vor sphere2 definiere, wird sphere1 transparent, aber sphere2 ist nicht mehr transparent. Wenn Sie den Radius von sphere2 auf 1,2 ändern, wird sphere1 ausgeblendet.

Gibt es eine Möglichkeit, beide Kugeln transparent zu machen?

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); 

Solutions Collecting From Web of "Transparente Objekte in Threejs"

Ihre beiden Sphären sind transparent und bleiben es auch. Was passiert, ist, dass die kleinere Kugel überhaupt nicht wiedergegeben wird.

Transparenz in WebGL ist schwierig. Sie können das Problem googlen, um mehr darüber zu erfahren.

Aber Sie sind auf ein Problem gestoßen, das sich darauf bezieht, wie insbesondere Three.js mit Transparenz umgeht .

Der WebGLRenderer in three.js sortiert Objekte basierend auf ihrer Entfernung von der Kamera und rendert transparente Objekte in der Reihenfolge von am weitesten zum nächsten. (Dies ist ein wichtiger Punkt: Er sortiert Objekte basierend auf ihrer Position und rendert Objekte in der sortierten Reihenfolge.)

Damit also zwei transparente Objekte richtig gerendert werden, muss das Objekt, das sich hinten befindet – in diesem Fall die kleinere – zuerst gerendert werden. Andernfalls wird es aufgrund des Tiefenpuffers überhaupt nicht gerendert.

Aber in Ihrem Fall haben Sie zwei Kugeln, die sich an der gleichen Stelle befinden und daher von der Kamera gleich weit entfernt sind. Das ist das Problem – welches man zuerst rendern soll; es ist ein Toss-Up.

Sie müssen also die kleinere Kugel weiter von der Kamera entfernen als die größere Kugel, damit die Szene korrekt gerendert wird.

Eine Lösung besteht darin, die kleinere Kugel ein wenig zurück zu bewegen.

Eine andere Lösung besteht darin, renderer.sortObjects = false . Dann werden die Objekte in der Reihenfolge wiedergegeben, in der sie der Szene hinzugefügt wurden. Stellen Sie in diesem Fall sicher, dass Sie der Szene zuerst die kleinere Kugel hinzufügen.

Eine dritte Lösung besteht darin, material1.depthWrite = false und material2.depthWrite = false .

BEARBEITEN:

Renderbare Objekte mit material.transparent = false (undurchsichtige Objekte) werden vor Objekten gerendert, die material.transparent = true (transparente Objekte) haben.

Eine vierte Lösung besteht also darin, die kleinere Sphäre undurchsichtig zu machen, so dass sie zuerst gerendert wird.

Neues Feature für r.71:

Es gibt jetzt eine Object3D.renderOrder Eigenschaft. Innerhalb jeder Objektklasse (undurchsichtig oder transparent) werden Objekte in der durch object.renderOrder angegebenen Reihenfolge object.renderOrder . Der Standardwert von renderOrder ist 0 . Beachten Sie, dass renderOrder nicht von renderOrder Objekten geerbt wird. Sie müssen es für jedes renderbare Objekt festlegen.

Objekte mit demselben renderOrder (Bindungen) werden wie oben beschrieben nach der Tiefe sortiert.

Eine fünfte Lösung besteht darin, renderOrder = 1 für die größere Sphäre zu setzen. Dies ist wahrscheinlich die beste Lösung in Ihrem Fall.

three.js r.71

Ein paar Kommentare.

Zuerst. Wenn du eine Frage stellen willst, die Leute erwarten, Code zu überprüfen, lege sie in jsfiddle ab. Wenn Sie das tun, werden Sie mehr Leute dazu bringen, einen Blick zu casting. Nachdem dies gesagt wurde, hier ist eine leicht modifizierte Version Ihres Codes in jsfiddle, bitte verwenden Sie es als Leitfaden für zukünftige Fragen. Beispiel

 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); renderer.sortObjects = false; // 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: 0xff0000, transparent: true, opacity: 0.5}); var sphere1 = new THREE.Mesh(geometry1, material1); scene.add(sphere2); scene.add(sphere1); renderer.render(scene, camera); 

Was ich in Ihrem Code geändert habe, ist, sortObjects auf false zu setzen und dann die Reihenfolge zu ändern, in der die Sphären zur Szene hinzugefügt wurden. Dies wurde aufgrund der Informationen in den nächsten 2 Links getan

Transparente WebGL-Ebenen Transparentes Texturverhalten