Сортировка по глубине Three.js CanvasRenderer

У меня есть несколько объектов CubeGeometry, отображаемых на CanvasRenderer. У меня возникают некоторые проблемы с обрезкой из-за сортировки по глубине, как показано на следующем изображении.

Теперь я видел здесь ответы о том, что это связано с ограничениями в CanvasRenderer, и я попытался применить несколько вещей, чтобы получить лучший результат, но проблемы с обрезкой все еще остаются. Я установил перерисовку на 1, и я увеличил сегменты настолько, насколько мог, не слишком влияя на производительность.

Изображение выглядит правильно в WebGLRenderer, но оно еще не получило широкой поддержки, поэтому, прежде чем я откажусь от CanvasRenderer, я хотел бы исчерпать все варианты. У кого-нибудь есть другие идеи, чтобы попробовать?

код для справки:

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

}

person Micah    schedule 30.10.2013    source источник
comment
Вы разбиваете свою геометрию одинаково во всех трех измерениях (8x8x8). Попробуйте тесселяцию только при необходимости (например, 2x32x1).   -  person WestLangley    schedule 31.10.2013


Ответы (1)


Буфер глубины (или Z-буфер) используется для решения проблемы со скрытой поверхностью. Если входящий фрагмент имеет большее значение глубины, чем значение в буфере, он отбрасывается. Если его значение меньше, оно заменяет текущее значение и записывается цвет фрагмента.

Изображение выглядит как классический случай Z-файтинг. Ваша ближняя/дальняя плоскость так далеко друг от друга по сравнению с расстоянием Z между поверхностями, что их значения Z сталкиваются.

Быстрый ответ, измените линию проекции на что-то вроде этого...

camera = new THREE.PerspectiveCamera(60, WIDTH / HEIGHT, 0.01, 100);

Если вам действительно нужны такие большие различия в ближней/дальней плоскости, это становится немного сложнее.

Быстрый гугл выдал вот это:

person jozxyqk    schedule 31.10.2013