2017-04-19 1 views
0

私はTHREE.InstancedBufferGeometryで遊んでいます。私はついに事例を得て、今シェーダで遊んでいます。私が最初に試みたのは、透明性を設定することでした。私のサンプルコードは以下の通りです。インスタント図形内の透明度

初期状態、および他のカメラアングルのホストから(たとえば、マウスを左にドラッグする)、透明度は何も影響していないようです。しかし、他のカメラアングル(例えば、マウスをリロードして右にドラッグする)では、シェイプが明らかに重なってしまいます。これは私が予想していたものです。

インスタンスのシェイプで深度ソートが異なるか、何か間違っている、または何か不足していますか?私は何とかカメラがシーンの適切な深さを知るように形状を更新する必要がありますか?

var cubeGeo = new THREE.InstancedBufferGeometry().copy(new THREE.BoxBufferGeometry(10, 10, 10)); 
 
//cubeGeo.maxInstancedCount = 8; 
 

 
cubeGeo.addAttribute("cubePos", new THREE.InstancedBufferAttribute(new Float32Array([ 
 
    25, 25, 25, 
 
    25, 25, -25, -25, 25, 25, -25, 25, -25, 
 
    25, -25, 25, 
 
    25, -25, -25, -25, -25, 25, -25, -25, -25 
 
]), 3, 1)); 
 

 
var vertexShader = [ 
 
    "precision highp float;", 
 
    "", 
 
    "uniform mat4 modelViewMatrix;", 
 
    "uniform mat4 projectionMatrix;", 
 
    "", 
 
    "attribute vec3 position;", 
 
    "attribute vec3 cubePos;", 
 
    "", 
 
    "void main() {", 
 
    "", 
 
    " \t gl_Position = projectionMatrix * modelViewMatrix * vec4(cubePos + position, 1.0);", 
 
    "", 
 
    "}" 
 
].join("\n"); 
 
var fragmentShader = [ 
 
    "precision highp float;", 
 
    "", 
 
    "void main() {", 
 
    "", 
 
    " \t gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);", 
 
    "", 
 
    "}" 
 
].join("\n"); 
 

 
var mat = new THREE.RawShaderMaterial({ 
 
    uniforms: {}, 
 
    vertexShader: vertexShader, 
 
    fragmentShader: fragmentShader, 
 
    transparent: true 
 
}); 
 

 
var mesh = new THREE.Mesh(cubeGeo, mat); 
 

 
scene.add(mesh);
html * { 
 
    padding: 0; 
 
    margin: 0; 
 
    width: 100%; 
 
    overflow: hidden; 
 
} 
 

 
#host { 
 
    width: 100%; 
 
    height: 100%; 
 
}
<script src="http://threejs.org/build/three.js"></script> 
 
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script> 
 
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script> 
 
<div id="host"></div> 
 

 
<script> 
 
    var WIDTH = window.innerWidth, 
 
    HEIGHT = window.innerHeight, 
 
    FOV = 35, 
 
    NEAR = 1, 
 
    FAR = 1000; 
 

 
    var renderer = new THREE.WebGLRenderer({ 
 
    antialias: true 
 
    }); 
 
    renderer.setSize(WIDTH, HEIGHT); 
 
    document.getElementById('host').appendChild(renderer.domElement); 
 

 
    var stats = new Stats(); 
 
    stats.domElement.style.position = 'absolute'; 
 
    stats.domElement.style.top = '0'; 
 
    document.body.appendChild(stats.domElement); 
 

 

 
    var camera = new THREE.PerspectiveCamera(FOV, WIDTH/HEIGHT, NEAR, FAR); 
 
    camera.position.z = 250; 
 

 
    var trackballControl = new THREE.TrackballControls(camera, renderer.domElement); 
 
    trackballControl.rotateSpeed = 2.0; // need to speed it up a little 
 

 
    var scene = new THREE.Scene(); 
 

 
    var light = new THREE.PointLight(0xffffff, 1, Infinity); 
 
    camera.add(light); 
 

 
    scene.add(light); 
 

 
    function render() { 
 
    if (typeof updateVertices !== "undefined") { 
 
     updateVertices(); 
 
    } 
 
    renderer.render(scene, camera); 
 
    stats.update(); 
 
    } 
 

 
    function animate() { 
 
    requestAnimationFrame(animate); 
 
    trackballControl.update(); 
 
    render(); 
 
    } 
 

 
    animate(); 
 
</script>

答えて

0

あなたは半透明であり、メッシュとInstancedBufferGeometryを使用しています。

インスタンスは、バッファに表示される順序でレンダリングされます。各インスタンスの面は、ジオメトリによって指定された順序でレンダリングされます。

したがって、半透明でインスタンス化すると、視野角によってアーチファクトが発生する可能性があります。

ユースケースによっては、material.depthWrite = falseを設定してみることもできますが、それは他のアーティファクトにつながる可能性があります。

メッシュテクスチャが部分的ではなく完全な透明領域を持つ場合は、material.alphaTestを使用してアーティファクトなしで不要なフラグメントを破棄することができます。

three.js r.84

+0

私は、正しくこの作品は正しい、深度ソート方法で、私の 'cubePos'バッファを再配置することであろうようにするだけ*本物*方法を理解していますか?このようなフレーム単位のタスクを含めると、インスタンスを使用することで得られるパフォーマンス上のメリットが犠牲になる可能性があります(ただし、メモリーにはメリットがあります)。 :( – TheJim01

+0

ジオメトリの顔に頼らないでください:実装されているバックフェース - 前面 - 顔のトリック[ここ](https://threejs.org/examples/webgl_geometry_convex.html)を使用してください。 – WestLangley

+0

'cubePos' *は私のインスタンスであり、実際にはそのように動作するようになっています。非効率的です(このコードで回答を投稿します)。私はバックフェイスフロントフェイストリックを試してみますが、シーンにメッシュを追加することでそれほど魅力的ではありません。 – TheJim01

0

はコメントでWestLangleyとの議論の後、私は自分のインスタンスのソーターを追加しました。カメラからの距離に基づいてインスタンスの位置をソートします。

(余談:私は他のどのTHREE.InstancedBufferAttributesを持っていた場合、私はそれらを同時に注文し直す必要があります。)

これまでの最大の欠点は、シーンがにつれて、それはより多くの高価になるということですインスタンス化された形状と非インスタンス化された形状の両方でより大きい。

// Instances Sorter, called each frame 
 
function sortObjectInstances(obj) { 
 
    if (obj.geometry) { 
 
    if (obj.geometry instanceof THREE.InstancedBufferGeometry) { 
 
     var array = obj.geometry.attributes.cubePos.array, 
 
     vecArray = []; 
 
     for (var i = 0, l = array.length/3; i < l; ++i) { 
 
     vecArray.push(new THREE.Vector3(array[(i * 3)], array[(i * 3) + 1], array[(i * 3) + 2])); 
 
     } 
 
     vecArray.sort(function(a, b) { 
 
     if (a.distanceTo(camera.position) > b.distanceTo(camera.position)) { 
 
      return -1; 
 
     } 
 
     if (a.distanceTo(camera.position) < b.distanceTo(camera.position)) { 
 
      return 1; 
 
     } 
 
     return 0; 
 
     }); 
 
     for (var i = 0, l = vecArray.length; i < l; ++i) { 
 
     array[(i * 3)] = vecArray[i].x; 
 
     array[(i * 3) + 1] = vecArray[i].y; 
 
     array[(i * 3) + 2] = vecArray[i].z; 
 
     } 
 
     obj.geometry.attributes.cubePos.needsUpdate = true; 
 
    } 
 
    } else { 
 
    for (var i = 0, l = obj.children.length; i < l; ++i) { 
 
     sortObjectInstances(obj.children[i]); 
 
    } 
 
    } 
 
} 
 

 
var cubeGeo = new THREE.InstancedBufferGeometry().copy(new THREE.BoxBufferGeometry(10, 10, 10)); 
 
//cubeGeo.maxInstancedCount = 8; 
 

 
cubeGeo.addAttribute("cubePos", new THREE.InstancedBufferAttribute(new Float32Array([ 
 
    25, 25, 25, 
 
    25, 25, -25, -25, 25, 25, -25, 25, -25, 
 
    25, -25, 25, 
 
    25, -25, -25, -25, -25, 25, -25, -25, -25 
 
]), 3, 1)); 
 

 
var vertexShader = [ 
 
    "precision highp float;", 
 
    "", 
 
    "uniform mat4 modelViewMatrix;", 
 
    "uniform mat4 projectionMatrix;", 
 
    "", 
 
    "attribute vec3 position;", 
 
    "attribute vec3 cubePos;", 
 
    "", 
 
    "void main() {", 
 
    "", 
 
    " \t gl_Position = projectionMatrix * modelViewMatrix * vec4(cubePos + position, 1.0);", 
 
    "", 
 
    "}" 
 
].join("\n"); 
 
var fragmentShader = [ 
 
    "precision highp float;", 
 
    "", 
 
    "void main() {", 
 
    "", 
 
    " \t gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);", 
 
    "", 
 
    "}" 
 
].join("\n"); 
 

 
var mat = new THREE.RawShaderMaterial({ 
 
    uniforms: {}, 
 
    vertexShader: vertexShader, 
 
    fragmentShader: fragmentShader, 
 
    transparent: true 
 
}); 
 

 
var mesh = new THREE.Mesh(cubeGeo, mat); 
 

 
scene.add(mesh);
html * { 
 
    padding: 0; 
 
    margin: 0; 
 
    width: 100%; 
 
    overflow: hidden; 
 
} 
 

 
#host { 
 
    width: 100%; 
 
    height: 100%; 
 
}
<script src="http://threejs.org/build/three.js"></script> 
 
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script> 
 
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script> 
 
<div id="host"></div> 
 

 
<script> 
 
    var WIDTH = window.innerWidth, 
 
    HEIGHT = window.innerHeight, 
 
    FOV = 35, 
 
    NEAR = 1, 
 
    FAR = 1000; 
 

 
    var renderer = new THREE.WebGLRenderer({ 
 
    antialias: true 
 
    }); 
 
    renderer.setSize(WIDTH, HEIGHT); 
 
    document.getElementById('host').appendChild(renderer.domElement); 
 

 
    var stats = new Stats(); 
 
    stats.domElement.style.position = 'absolute'; 
 
    stats.domElement.style.top = '0'; 
 
    document.body.appendChild(stats.domElement); 
 

 

 
    var camera = new THREE.PerspectiveCamera(FOV, WIDTH/HEIGHT, NEAR, FAR); 
 
    camera.position.z = 250; 
 

 
    var trackballControl = new THREE.TrackballControls(camera, renderer.domElement); 
 
    trackballControl.rotateSpeed = 2.0; // need to speed it up a little 
 

 
    var scene = new THREE.Scene(); 
 

 
    var light = new THREE.PointLight(0xffffff, 1, Infinity); 
 
    camera.add(light); 
 

 
    scene.add(light); 
 

 
    function render() { 
 
    if (typeof sortObjectInstances !== "undefined") { 
 
     sortObjectInstances(scene); // Sort the instances 
 
    } 
 
    renderer.render(scene, camera); 
 
    stats.update(); 
 
    } 
 

 
    function animate() { 
 
    requestAnimationFrame(animate); 
 
    trackballControl.update(); 
 
    render(); 
 
    } 
 

 
    animate(); 
 
</script>

+0

効率を少し変えるのは、 'THREE.Vector3'オブジェクトの配列を格納することです毎回それを生成するのではなく、メッシュ上に自己を配置します。 – TheJim01