之前用包围盒和重心坐标法做过光栅化实现,但是那个方法存在问题,这次要实现一个更高效的光栅化方法.
之前使用的包围盒方法确定光栅化范围,但是包围盒确定的范围是矩形,要光栅化的是三角形,那么每次都会有不需要的像素参加运算,一个面当然没啥问题,但是如果是100个面问题就大了.
if(scrAY==scrBY&&scrAY==scrCY) //屏幕坐标所有y都相等,直线不进行光栅化 return; int minY=max(0,min(scrAY,min(scrBY,scrCY))); //顶上的y0 int maxY=min(fb->height-1,max(scrAY,max(scrBY,scrCY))); //底部的y1 for(int scrY=minY;scrY<=maxY;scrY++) { float x1,x2; if(scrAY==scrBY) { //平顶平底情况 float paramAC=((float)scrY-scrAY)/(scrCY-scrAY); float paramBC=((float)scrY-scrBY)/(scrCY-scrBY); x1=(scrCX-scrAX)*paramAC+scrAX; x2=(scrCX-scrBX)*paramBC+scrBX; } else if(scrAY==scrCY) { //平顶平底情况 float paramAB=((float)scrY-scrAY)/(scrBY-scrAY); float paramBC=((float)scrY-scrBY)/(scrCY-scrBY); x1=(scrBX-scrAX)*paramAB+scrAX; x2=(scrCX-scrBX)*paramBC+scrBX; } else if(scrBY==scrCY) { //平顶平底情况 float paramAB=((float)scrY-scrAY)/(scrBY-scrAY); float paramAC=((float)scrY-scrAY)/(scrCY-scrAY); x1=(scrBX-scrAX)*paramAB+scrAX; x2=(scrCX-scrAX)*paramAC+scrAX; } else { //正常情况 float paramAB=((float)scrY-scrAY)/(scrBY-scrAY); float paramAC=((float)scrY-scrAY)/(scrCY-scrAY); float paramBC=((float)scrY-scrBY)/(scrCY-scrBY); bool ab=(paramAB<=1.0&¶mAB>=0.0)?true:false; bool ac=(paramAC<=1.0&¶mAC>=0.0)?true:false; bool bc=(paramBC<=1.0&¶mBC>=0.0)?true:false; float xAB=(scrBX-scrAX)*paramAB+scrAX; float xAC=(scrCX-scrAX)*paramAC+scrAX; float xBC=(scrCX-scrBX)*paramBC+scrBX; if(!ab) { x1=xAC; x2=xBC; } else if(!ac) { x1=xAB; x2=xBC; } else if(!bc) { x1=xAB; x2=xAC; } else { x1=xAC; x2=xBC; if(x1==x2) //排除两线交点的情况 x2=xAB; } } int minX=max(0,min(x1,x2)-0.5); //扫描线左边的x值 int maxX=min(fb->width-1,max(x1,x2)+0.5); //扫描线右边的x值
for(int scrX=minX;scrX<=maxX;scrX++) { invViewPortTransform(scrX,scrY,fb->width,fb->height,ndcX,ndcY); VECTOR4D ndcPixel(ndcX,ndcY,1,0); VECTOR4D proportion4D=face->clipMatrixInv*ndcPixel; VECTOR3D proportionFragment(proportion4D.x,proportion4D.y,proportion4D.z); float pa=proportionFragment.x; float pb=proportionFragment.y; float pc=proportionFragment.z; if(pa<0||pb<0||pc<0) continue; float sum=pa+pb+pc; pa/=sum; pb/=sum; pc/=sum; Fragment frag; interpolate3f(pa,pb,pc,face->clipA.w,face->clipB.w,face->clipC.w,clipW); interpolate3f(pa,pb,pc,face->clipA.z,face->clipB.z,face->clipC.z,frag.ndcZ); frag.ndcZ/=clipW; if(frag.ndcZ<-1||frag.ndcZ>1) continue; if(db!=NULL) { float storeZ=readDepth(db,scrX,scrY); if(storeZ<frag.ndcZ) continue; writeDepth(db,scrX,scrY,frag.ndcZ); } interpolate3f(pa,pb,pc,face->clipA.x,face->clipB.x,face->clipC.x,frag.ndcX); frag.ndcX/=clipW; interpolate3f(pa,pb,pc,face->clipA.y,face->clipB.y,face->clipC.y,frag.ndcY); frag.ndcY/=clipW; interpolate3f(pa,pb,pc,face->clipA.wx,face->clipB.wx,face->clipC.wx,frag.wx); interpolate3f(pa,pb,pc,face->clipA.wy,face->clipB.wy,face->clipC.wy,frag.wy); interpolate3f(pa,pb,pc,face->clipA.wz,face->clipB.wz,face->clipC.wz,frag.wz); interpolate3f(pa,pb,pc,face->clipA.ww,face->clipB.ww,face->clipC.ww,frag.ww); interpolate3f(pa,pb,pc,face->clipA.nx,face->clipB.nx,face->clipC.nx,frag.nx); interpolate3f(pa,pb,pc,face->clipA.ny,face->clipB.ny,face->clipC.ny,frag.ny); interpolate3f(pa,pb,pc,face->clipA.nz,face->clipB.nz,face->clipC.nz,frag.nz); interpolate3f(pa,pb,pc,face->clipA.s,face->clipB.s,face->clipC.s,frag.s); interpolate3f(pa,pb,pc,face->clipA.t,face->clipB.t,face->clipC.t,frag.t); FragmentOut outFrag; fs(frag,outFrag); drawPixel(fb,scrX,scrY,outFrag.r,outFrag.g,outFrag.b); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zxx43/article/details/47680629