C++ 带深度优化的DrawScanline
我有一些绘制扫描线的程序 深度-它以x作为x起点,以xk作为x终点, y和zs为xs处的z深度,zk为zk处的z深度 (z值从xs线性变化为xk)浮动深度 ram中的缓冲器用于深度测试 给你C++ 带深度优化的DrawScanline,c++,c,performance,optimization,drawing,C++,C,Performance,Optimization,Drawing,我有一些绘制扫描线的程序 深度-它以x作为x起点,以xk作为x终点, y和zs为xs处的z深度,zk为zk处的z深度 (z值从xs线性变化为xk)浮动深度 ram中的缓冲器用于深度测试 给你 inline void drawScanlineWithDepth(int y, int xs, int xk, float zs, float zk, unsigned color) { if(y<0) return; //clip if(y
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;
}
}
inline void drawScanlineWithDepth(int y、int xs、int xk、float zs、float zk、unsigned color)
{
如果(y=客户_y)返回//
if(xs>xk)//交换以确保xs位于左侧,xk位于右侧
{
int temp=xs;xs=xk;xk=temp;
浮点tempp=zs;zs=zk;zk=tempp;
}
if(xs=CLIENT_X)返回;
float sub_zk=(xk-(客户_X-1))*float(zk zs)/float(xk xs);
zk-=sub_zk;
xk=客户_X-1;
}
int len=xk xs;
int yc=客户_Y-Y-1//反转y坐标,因为blitter会反转y坐标
int adr=yc*客户机X+xs;
对于优化来说,一个非常重要的事情是考虑最重要的工作量是什么?它是不是画了很多短的(ISH)跨度,还是它绘制的大多是很长的跨度?每种情况下优化的主要目标都是不同的。
此外,您使用的处理器也很重要;分支预测是否会遗漏(即,作为一个整体的分支)会降低您的速度
短跨度:
一点是,最好将一些测试(y剪裁等)移到这个函数之外,以确保它根本不会被那些y值调用
交换侧面也是一样;您也可以展开这些箱子
大跨度:
答案取决于您的编译器和CPU;使用一些多媒体扩展将是一个好主意。此外,您可以在for()中展开循环,在一次迭代中执行两个像素,以赢得一点(除非你能让你的编译器帮你做这件事;你看过汇编输出并调整了优化器设置吗?它用于软件光栅化器,所以两种情况都会使用-一瞬间10万个短帧,然后当接近单个三角形时/s一整屏长三角形