Самый быстрый способ реализовать z-буферизацию для программного средства визуализации?

StackOverflow https://stackoverflow.com//questions/12677218

Вопрос

Я внедряю программный рендерер javascript (для академических целей).Он обрабатывает представление 3d-объекта в виде треугольников и обрабатывает перспективную проекцию из 3d-пространства в 2d-пространство.

До сих пор я пользовался lineTo и fillRect для представления вершин и линий на экране.Я даже использовал lineTo чтобы выполнить заполнение треугольника линии сканирования.(вы можете ознакомиться с проектом здесь)

До сих пор FPS был довольно хорошим.Но последняя часть задания заключается в реализации z-буферизации:P.Насколько мне известно, единственный способ сделать это - прекратить заполнять мои треугольники с помощью lineTo и заполните их либо массивом строк размером 1 пиксель, либо массивом квадратов размером 1 пиксель.(потому что, прежде чем я нарисую каждый "пиксель", я должен проверить буфер глубины и посмотреть, действительно ли я должен его нарисовать или нет.)

Проблема в том, что заполнение треугольников крошечными прямоугольниками или линиями происходит медленно.Сокращает скорость до 2 кадров в секунду.Итак, мой вопрос в том, есть ли какой-нибудь способ нарисовать один пиксель вместо крошечной линии (что может быть быстрее)?

В качестве альтернативы, что еще я могу сделать, чтобы ускорить процесс?Моя цель - заставить его вращаться достаточно быстро, чтобы продемонстрировать принцип.(6-10 кадров в секунду было бы достаточно)

Ваше здоровье.

[РЕДАКТИРОВАТЬ] Пока я жду ответа, я попробую изменить свои функции заполнения треугольника, чтобы рисовать "пиксели" размером 4 пикселя вместо 1 пикселя.Но это будет выглядеть неровно...

Это было полезно?

Решение

Зацени это: http://jsfiddle.net/ZXjAM/2/

// points 0,1,2,3 front face
var fAvgZ = (cube.processPoints[0].colorZ + 
    cube.processPoints[1].colorZ + 
    cube.processPoints[2].colorZ + 
    cube.processPoints[3].colorZ) / 4 / 20;

// points 0,2,4,6 top
var tAvgZ = (cube.processPoints[0].colorZ + 
    cube.processPoints[2].colorZ + 
    cube.processPoints[4].colorZ + 
    cube.processPoints[6].colorZ) / 4 / 20;

// points 4,5,6,7 rear
var reAvgZ = (cube.processPoints[4].colorZ + 
    cube.processPoints[5].colorZ + 
    cube.processPoints[6].colorZ + 
    cube.processPoints[7].colorZ) / 4 / 20;

// points 1,3,5,7 bottom
var bAvgZ = (cube.processPoints[1].colorZ + 
    cube.processPoints[3].colorZ + 
    cube.processPoints[5].colorZ + 
    cube.processPoints[7].colorZ) / 4 / 20;

// points 2,3,6,7 right side
var rAvgZ = (cube.processPoints[2].colorZ + 
    cube.processPoints[3].colorZ + 
    cube.processPoints[6].colorZ + 
    cube.processPoints[7].colorZ) / 4 / 20;

// points 0,1,4,5 left side
var lAvgZ = (cube.processPoints[0].colorZ + 
    cube.processPoints[1].colorZ + 
    cube.processPoints[4].colorZ + 
    cube.processPoints[5].colorZ) / 4 / 20;

var layers = [{key:0, val:fAvgZ},
          {key:1, val:fAvgZ},
          {key:2, val:tAvgZ},
          {key:3, val:tAvgZ},
          {key:4, val:reAvgZ},
          {key:5, val:reAvgZ},
          {key:6, val:bAvgZ},
          {key:7, val:bAvgZ},
          {key:8, val:rAvgZ},
          {key:9, val:rAvgZ},
          {key:10, val:lAvgZ},
          {key:11, val:lAvgZ}];

var outLay = layers.sort(function(a,b){
    return (a.val - b.val);
});

for(var i = 0; i < outLay.length; i++)
{
    var k = outLay[i].key;
    ...
}

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

Я нахожу средний z-индекс и использую его для определения порядка наслоения.Очевидно, что это никогда не сработает для всего, но для простых многогранников этого должно быть достаточно.

Это может быть упрощено до:

var layers = [];
for (var i = 0; i < cube.sides.length; i++){
    var side = cube.sides[i];
    var avg = (cube.processPoints[side.a].colorZ + 
               cube.processPoints[side.b].colorZ + 
               cube.processPoints[side.c].colorZ) / 3 / 20;                   
    layers.push({key:i, val:avg});
}

var outLay = layers.sort(function(a,b){
    return (a.val - b.val);
});

Похоже, действительно есть некоторые второстепенные случаи, когда возникает проблема с быстрым оформлением заказа.

Это кажется более точным: http://jsfiddle.net/ZXjAM/4/

var layers = [];
for (var i = 0; i < 12; ++i){
    var side1 = cube.sides[i];
    var side2 = cube.sides[++i];
    var avg = (cube.processPoints[side1.a].colorZ + 
               cube.processPoints[side1.b].colorZ + 
               cube.processPoints[side1.c].colorZ + 
               cube.processPoints[side2.a].colorZ + 
               cube.processPoints[side2.b].colorZ + 
               cube.processPoints[side2.c].colorZ) / 6;                   
    layers.push({key:i-1, val:avg});
    layers.push({key:i, val:avg});
}

var outLay = layers.sort(function(a,b){
    return (a.val - b.val);
});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top