У меня есть какая-то процедура рисовать сканлайн
с глубиной — принимает xs как начало x, xk как конец x,
y и zs как z-глубина в xs и zk как z-глубина в zk
(z значение меняет линейную форму от xs до xk) Глубина плавания
буфер в оперативной памяти используется для проверки глубины
Вот
inline void drawScanlineWithDepth(int y, int xs, int xk, float zs, float zk, unsigned color)
{
if(y<0) return; //clip
if(y>=CLIENT_Y) return; //
if(xs>xk) // swap to assure xs is on left xk at right
{
int temp = xs; xs=xk; xk=temp;
float tempp = zs; zs=zk; zk=tempp;
}if(xs<0) //cut left end to 0
{
if(xk<0) return;
float dod_zs = (-xs)*float(zk-zs)/float(xk-xs);
zs += dod_zs;
xs=0;
}if(xk>=CLIENT_X) //cut right end to CLIENT_X-1
{
if(xs>=CLIENT_X) return;
float sub_zk = (xk-(CLIENT_X-1))*float(zk-zs)/float(xk-xs);
zk -= sub_zk;
xk = CLIENT_X-1;
}int len = xk-xs;
int yc = CLIENT_Y-y-1; //reverse y coordinate becouse blitter reverses it
int adr_ = yc*CLIENT_X + xs;
int adr_depth = ( yc<<12 ) + xs; // depth[] is a static table with 4096 width
float* db = ((float*) depth) + adr_depth;
unsigned* adr = ((unsigned*)pBits) + adr_;
if(len<=3) //unwind short scanlines
{if(len==0)
{
if(zs< *db) *db = zs, *adr = color;
return;
}
else if(len==1)
{
if(zs< *db) *db = zs, *adr = color; db++; adr++;
if(zk< *db) *db = zk, *adr = color;
return;
}
else if(len==2)
{
float zs_1 = zs + len*0.5;
if(zs <*db) *db = zs, *adr = color; db++; adr++;
if(zs_1<*db) *db = zs_1, *adr = color; db++; adr++;
if(zk <*db) *db = zk, *adr = color;
return;
}
else if(len==3)
{
float zs_1 = zs + (len)*(1./3.);
float zs_2 = zs + (len)*(2./3.);
if(zs < *db) *db = zs , *adr = color; db++; adr++;
if(zs_1< *db) *db = zs_1 , *adr = color; db++; adr++;
if(zs_2< *db) *db = zs_2 , *adr = color; db++; adr++;
if(zk < *db) *db = zk , *adr = color;
return;
}
}
if(len==0) ERROR_("len == 0");
if(len<0) ERROR_("len < 0");float dz = float(zk-zs)/float(len);
float z = zs;
for(int i=0; i<=len; i++)
{
if(z < *db) //depthtest
{
*db = z; //set pixel
*adr = color;
}
adr++;
db++;
z+=dz;
}
}
«Разматывать» петлю для коротких линий сканирования, как указано выше, для длины 1,2,3,4
делает это быстрее, но с более неповоротливым я не вижу большого улучшения
Можно ли его оптимизировать больше?
Len
Одна действительно важная вещь для оптимизации — рассмотреть, какая самая важная рабочая нагрузка. Это рисует много коротких (ish) промежутков или это в основном действительно длинные промежутки? Основная цель оптимизации различна в каждом конкретном случае.
Кроме того, какой процессор вы используете, важно; замедление предсказания ветвления (то есть ветвление в целом) замедляет вас или нет.
Короткие пролеты:
Один момент заключается в том, что было бы неплохо переместить некоторые из тестов (y-отсечение и т. Д.) За пределы этой функции, чтобы она вообще не вызывалась с этими значениями Y.
То же самое для обмена сторонами; Вы также можете развернуть эти дела.
Длинные пролеты:
Ответ зависит от вашего компилятора и процессора; использование некоторых мультимедийных расширений а-ля SSE было бы отличной идеей. Кроме того, вы можете развернуть цикл внутри for (), чтобы сделать два пикселя внутри одной итерации, чтобы выиграть немного (если только вы не можете заставить свой компилятор сделать это за вас; вы посмотрели на вывод сборки и настроили параметры оптимизатора) ?)
Других решений пока нет …