很多朋友对什么是光栅化,为什么要光栅化怎么实现光栅化方法不是很了解,六月小编刚好整理了这方面的知识,今天就来带大家一探究竟。光栅化
很多朋友对什么是光栅化,为什么要光栅化怎么实现光栅化方法不是很了解,六月小编刚好整理了这方面的知识,今天就来带大家一探究竟。
光栅化是在计算机上生成图像的重要步骤,但opengl、directx和其他图形界面都封装了光栅化方法。我自己做了一个栅格化器,接下来我就说说如何实现栅格化。为什么要栅格化?
图形管道的输入是图元的顶点,输出是像素。在这一步中,还有一个中间产物叫做fragment,每个fragment对应一个像素,但是fragment比像素有更多的属性用于计算,比如深度值和法向量。我们可以通过线段计算出最终将要生成的像素的颜色值,我们把由输入顶点计算线段的过程称为光栅化。为什么要栅格化?因为要生成段来计算最终颜色。
栅格化的输入输出有哪些?和普通函数一样,栅格化函数也需要输入和输出。从前面的定义来看,函数的输入是图形元素的顶点结构,输出是片段结构。为什么是结构?因为这些都可以用C语言中的struct来描述。
光栅化发生在哪个步骤?通常在图形界面中会暴露顶点处理程序和片段处理程序(着色器听起来像雾,所以用处理程序代替),但是gpu会进行光栅插值计算,这就是为什么片段处理程序的输入是顶点处理程序输出的插值。
由于光栅化是顶点处理后的一个步骤,所以输入的顶点结构是顶点处理后的,也就是mvp变换和与透视矩阵相乘后的顶点。注意:这一步没有经过透视分割,光栅化插值发生在裁剪空间,绝非标准化空间,所以顶点位置是四维齐次坐标,不是三维坐标!
光栅化方法怎么实现?我们首先可以确定的是光栅化的输入和输出是什么。而且你要知道手头可以用什么数据。首先对输入的顶点进行处理,转换成屏幕坐标,然后将裁剪空间的顶点坐标转换成标准化空间,就像这样:ndca . x=clipa . x/clipa . w;ndca . y=clipa . y/clipa . w;ndcb . x=clipb . x/clipb . w;ndcb . y=clipb . y/clipb . w;ndcc . x=clipc . x/clipc . w;ndcc . y=clipc . y/clipc . w;然后在顶点的标准坐标上进行视口变换:“
viewPortTransform(face-"ndcA.x,face-"ndcA.y,fb-"width,fb-"height,scrAX,scrAY);viewPortTransform(face-"ndcB.x,face-"ndcB.y,fb-"width,fb-"height,scrBX,scrBY);viewPortTransform(face-"ndcC.x,face-"ndcC.y,fb-"width,fb-"height,scrCX,scrCY);但是,如果2D库德纳说他的立场是代表比尔克林顿的话,那么他就有可能成为一个大人物。比如一个抽屉。
int minX=max(0,min(scrAX,min(scrBX,scrCX));int maxX=min(fb-) width-1,max(scrAX,max(scrBX,scrCX));int minY=max(0,min(scrAY,min(scrBY,scrCY)));int maxY=min(fb-"height-1,max(scrAY,max(scrBY,scrCY));如果你愿意的话,请不要犹豫。所有的双年展都是如此。在这种情况下,position {\\ F2 auf {\\ F2 Bildschirm fr potentielle fragment :} for(int scrX=minX;scrX=maxXscrx)
for(int scrY=minY;scrY"=maxY;scrY ) { .}}计算该线段对应的标准化空间坐标:invViewPortTransform(scrX,scrY,FB-"width,FB-"height,ndcX,ndcY);这里用的是逆视口变换,非常方便,缩放平移坐标即可。
然后我们得到可能碎片的标准化空间的x和y坐标。为什么可能是碎片?因为还不能确定这些片段是在要栅格化的三角形的外面还是里面,所以我们只计算三角形里面的片段。但是知道这些有什么用呢?这里有一个公式可以计算三个顶点对片段的影响比例,也称为权重:
这个公式的A b c分别代表一个三角形的三个顶点,ax ay aw是顶点a在裁剪空间的齐次坐标(是四维的)的x y w值,这里不用z值,因为z也要用这个权值来计算。你如何推导这个公式?给定要栅格化的三角形abc的三个顶点在裁剪空间中的齐次坐标,可以得到每一段的裁剪空间的齐次坐标如下:x=pa * axpb * bxpc * cxy=pa * aypb * bypc * cyz=pa * azpb * bzpc * cz。
W=pa*aw pb*bw pc*cw然后计算碎片在标准化坐标系中的坐标值如下:nx=x/wny=y/wnz=z/wnw=1。可以推导出x=w*nxy=w*nyw=w因为:X=pa * axpb * bxpc * cxy=pa * aypb。将cw转换成3x3矩阵是AXBX CX PAW * nx AY BY CY * Pb=W * nya ww BW CW PCW其中NX和NY是之前得到的片段在标准化坐标系中的x y值;而且因为pa pb pc是比值,w可以去掉;这样,pa pb pc的值只需取33矩阵的逆即可得到。
但需要注意的是,pa pb pc=1,所以计算完值后要进行如下处理,例如:float sum=pa pb pcpa/=sum;Pb/=sum;PC/=sum;然后丢弃比值小于0的片段:if (pa ||| Pb ||| PC || 0)继续;接下来,我们可以使用这三个权重来插值顶点属性。详细的栅格化函数如下:void rasterize(FrameBuffer* fb,DepthBuffer* db,FragmentShader fs,Face* face) {float ndcX=0,ndcY=0,clipW=0;int scrAX,scrAY,scrBX,scrBY,scrCX,scrCY
viewPortTransform(face-"ndcA.x,face-"ndcA.y,fb-"width,fb-"height,scrAX,scrAY);viewPortTransform(face-"ndcB.x,face-"ndcB.y,fb-"width,fb-"height,scrBX,scrBY);viewPortTransform(face-"ndcC.x,face-"ndcC.y,fb-"width,fb-"height,scrCX,scrCY);int minX=max(0,min(scrAX,min(scrBX,scrCX));int maxX=min(fb-) width-1,max(scrAX,max(scrBX,scrCX));
int minY=max(0,min(scrAY,min(scrBY,scrCY)));int maxY=min(fb-"height-1,max(scrAY,max(scrBY,scrCY));for(int scrX=minX;scrX=maxXscrX){ for(int scrY=minY;scry=maxyscRY){ invViewPortTransform(scrX,scRY,fb-"width,fb-"height,ndcX,ndcY);VECTOR4D ndcPixel(ndcX,ndcY,1,0);向量4D比例4D=face-"clipMatrixInv * NDC pixel;vector 3d proportion fragment(proportion 4d . x,proportion4D.y,proportion 4d . z);
float pa=proportion fragment . xfloat Pb=proportion fragment . yfloat PC=proportion fragment . z浮点求和=pa Pb pcpa/=sum;Pb/=sum;PC/=sum;if(pa《0||pb《0||pc《0继续;碎片fraginterpolate3f(pa,pb,pc,face-》clipA.w,face-》clipB.w,face-》clipC.w,clipW);插值3f(pa,pb,pc,face-》clipA.z,face-》clipB.z,face-》clipC.z,frag。ndcz);frag.ndcZ/=clipW;if(frag.ndcZ 《-1||frag.ndcZ》 1)继续;如果(db!=NULL) {
float storeZ=readDepth(db,scrX,scrY);
if(storeZ
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.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);
}
}
}
光栅化完毕了,这下就能自己实现opengl和directx了!
以上就是关于什么是光栅化,为什么要光栅化怎么实现光栅化方法的知识,希望能够帮助到大家!
声明本站所有作品图文均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系我们
上一篇:电子地图下载使用,电子地图下载