Three.js CanvasRenderer depth sorting

一笑奈何 提交于 2019-12-11 11:19:42

问题


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.

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.

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?

code for reference:

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

}

回答1:


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.

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


来源:https://stackoverflow.com/questions/19695934/three-js-canvasrenderer-depth-sorting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!