我一直在玩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() {",
"",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( cubePos + position, 1.0 );",
"",
"}"
].join("\n");
var fragmentShader = [
"precision highp float;",
"",
"void main() {",
"",
" 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 :(得分:0)
您使用的InstancedBufferGeometry
网格是半透明的。
实例按照它们在缓冲区中出现的顺序呈现。每个实例的面都以几何体指定的顺序呈现。
因此,如果您使用具有半透明度的实例化,则可能会根据视角产生伪影。
根据您的使用情况,您可以尝试设置material.depthWrite = false
,但这可能会导致其他工件。
如果您的网格纹理具有完全透明(而不是部分)的区域,您应该能够使用material.alphaTest
丢弃不需要的片段而不会产生伪影。
three.js r.84
答案 1 :(得分: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() {",
"",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( cubePos + position, 1.0 );",
"",
"}"
].join("\n");
var fragmentShader = [
"precision highp float;",
"",
"void main() {",
"",
" 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);
&#13;
html * {
padding: 0;
margin: 0;
width: 100%;
overflow: hidden;
}
#host {
width: 100%;
height: 100%;
}
&#13;
<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>
&#13;