之前用包围盒和重心坐标法做过光栅化实现,但是那个方法存在问题,这次要实现一个更高效的光栅化方法.
之前使用的包围盒方法确定光栅化范围,但是包围盒确定的范围是矩形,要光栅化的是三角形,那么每次都会有不需要的像素参加运算,一个面当然没啥问题,但是如果是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