Three.js CanvasRenderer深度排序 [英] Three.js CanvasRenderer depth sorting
问题描述
我在CanvasRenderer上渲染了一些CubeGeometry对象.由于深度排序,我遇到了一些裁剪问题,如下图所示.
I have a few CubeGeometry objects rendered on the CanvasRenderer. I am getting some clipping issues due to depth sorting as shown on the following image.
现在我在这里看到了响应,这是由于CanvasRenderer中的限制所致,我尝试应用一些方法以获得更好的结果,但是仍然存在裁剪问题.我将透支设置为1,并在不影响性能的情况下尽可能增加了细分.
Now I have seen the responses on here that this is due to limitations in CanvasRenderer and I have tried applying a few things to get a better result but there is still the clipping issues. I have overdraw set to 1 and I have increased segments as much as I can without impacting performance too much.
该图像在WebGLRenderer中看起来是正确的,但是尚未得到广泛支持,因此在我放弃CanvasRenderer之前,我想穷尽所有选项.还有其他想法可以尝试吗?
The image looks correct in the WebGLRenderer but it is not widely supported yet so before I give up on the CanvasRenderer I would like to exhaust all options. Anyone have any other ideas to try?
参考代码:
function SolidWood( length, width, thickness )
{
this.ID = -1;
this.name = "Unknown";
this.dimensions = {};
this.dimensions.length = length;
this.dimensions.width = width;
this.dimensions.thickness = thickness;
this.properties = {};
this.properties.color = 0x00ff00;
this.properties.wireframe = false;
this.properties.shading = THREE.SmoothShading;
this.properties.overdraw = 1.0;
this.geometry = null;
this.material = null;
this.mesh = null;
}
SolidWood.prototype.BuildGeometry = function(){
var segs = (Detector.webgl ? 1 : 8);
this.geometry = new THREE.CubeGeometry(this.dimensions.width, this.dimensions.length, this.dimensions.thickness
, segs, segs, segs);
};
SolidWood.prototype.BuildMaterial = function(){
this.properties.ambient = this.properties.color;
this.material = new THREE.MeshLambertMaterial( this.properties );
};
SolidWood.prototype.BuildMesh = function(){
this.mesh = new THREE.Mesh(this.geometry, this.material)
};
SolidWood.prototype.BuildAll = function(){
this.BuildGeometry();
this.BuildMaterial();
this.BuildMesh();
};
var camera, scene, renderer, controls, light;
var panel = {};
var HEIGHT, WIDTH;
var $container = $('#content-gallery-content');
var $speed = $('#speed');
init();
animate();
function init() {
WIDTH = 400;
HEIGHT = 300;
camera = new THREE.PerspectiveCamera( 60, WIDTH / HEIGHT, .001, 1000 );
camera.position.z = 30;
camera.position.y = 5;
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
light = new THREE.PointLight(0xffffff, 0.75, 0.0);
light.position.set(0, -30, 0);
scene.add(light);
scene.add(new THREE.AmbientLight(0xb0b0b0));
//build our panel
panel.crossmembersCount = 2;
panel.membersPerFoot = 4;
panel.memberWidth = 2.5;
panel.memberWidthHalf = panel.memberWidth/2;
panel.degrees90 = ((90*Math.PI)/180);
panel.gapWidth = (12-(panel.memberWidth * panel.membersPerFoot)) / panel.membersPerFoot;
panel.members = {};
panel.crossmembers = {};
for(i=0; i<panel.crossmembersCount; ++i)
{
panel.crossmembers[i] = new SolidWood(1.25, 11.875, 0.5);
panel.crossmembers[i].properties.color = 0x000000;
panel.crossmembers[i].BuildAll();
panel.crossmembers[i].mesh.rotation.x = panel.degrees90;
panel.crossmembers[i].mesh.position.z = ((i*12)+5.5)-11.5;
panel.crossmembers[i].mesh.position.x = 0.0625;
panel.crossmembers[i].mesh.position.y = 0.25;
scene.add( panel.crossmembers[i].mesh );
}
for(i=0; i< panel.membersPerFoot; ++i)
{
panel.members[i] = new SolidWood(23.0, panel.memberWidth, 0.6875);
panel.members[i].properties.color = 0xccaa00;
panel.members[i].BuildAll();
panel.members[i].mesh.rotation.x = panel.degrees90;
panel.members[i].mesh.position.z = 0;
panel.members[i].mesh.position.x = panel.memberWidthHalf-6.125+((panel.memberWidth+panel.gapWidth)*i);
panel.members[i].mesh.position.y = (0.6875/2)*-1;
scene.add( panel.members[i].mesh );
}
renderer = (Detector.webgl ? new THREE.WebGLRenderer() : new THREE.CanvasRenderer());
renderer.setSize( WIDTH, HEIGHT );
renderer.setClearColor(0xD0D0D0, 1.0);
$container.append( renderer.domElement );
controls = new THREE.OrbitControls(camera, $container.get(0));
}
function animate() {
// note: three.js includes requestAnimationFrame shim
requestAnimationFrame( animate );
light.position = camera.position;
//var length = $('#speed').val() * 100;
renderer.render( scene, camera );
}
推荐答案
深度缓冲区(或Z缓冲区)用于解决隐藏表面问题.如果传入的片段的深度值大于缓冲区中的深度值,则将其丢弃.如果其值较小,它将替换当前值,并写入片段颜色.
The depth buffer (or Z-buffer) is used to resolve the hidden surface problem. If an incoming fragment has a greater depth value than the value in the buffer, it's discarded. If its value is less, it replaces the current value and the fragment colour is written.
在我看来,图像看起来像是Z战的经典案例.与表面之间的Z距离相比,您的近/远平面相距如此远,以至于它们的Z值发生冲突.
The image looks to me like a classic case of Z-fighting. Your near/far plane is so far apart compared to the Z distance between the surfaces that their Z values collide.
快速解答,将投影线更改为这样的内容...
The quick answer, change the projection line to something like this...
camera = new THREE.PerspectiveCamera(60, WIDTH / HEIGHT, 0.01, 100);
如果您真的需要在近/远平面上有如此大的差异,那就会变得更加复杂.
If you really need such large differences in near/far plane, it gets a bit more complicated.
一个快速的谷歌出现了这些:
A quick google turned up these:
- Depth Buffer Precision
- Maximizing Depth Buffer Range and Precision
这篇关于Three.js CanvasRenderer深度排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!