C语言实现光栅化实现过程,为什么要光栅化?怎么实现光栅化方法?

C语言实现光栅化实现过程,为什么要光栅化?怎么实现光栅化方法?描述光栅化是在计算机上生成图像的重要步骤 然而无论是 opengl 还是 directx 还是其他的图形接口都封装了光栅化方法 我自己做了个光栅器 接下来就说一下怎样实现光栅化的 为什么要光栅化 图形管线的输入是图元顶点 输出的则是像素 pixel 这个步骤其中还有个中间产物叫做片段 fragment 一个片段相应一个像素 但片段比像素多了用于计算的属性 比如 深度值和法向量 通过片段能够计算出终于将

描述

光栅化是在计算机上生成图像的重要步骤,然而无论是opengl还是directx还是其他的图形接口都封装了光栅化方法。我自己做了个光栅器,接下来就说一下怎样实现光栅化的。

为什么要光栅化?

图形管线的输入是图元顶点,输出的则是像素(pixel),这个步骤其中还有个中间产物叫做片段(fragment),一个片段相应一个像素,但片段比像素多了用于计算的属性,比如:深度值和法向量。通过片段能够计算出终于将要生成像素的颜色值,我们把输入顶点计算片段的过程叫作光栅化。为什么要光栅化?由于要生成用以计算终于颜色的片段。

光栅化的输入和输出各自是啥?

和普通函数一样,光栅化函数也须要输入和输出,从之前的定义来看函数的输入就是组成图元的顶点结构,输出的就是片段结构,为什么说是结构?由于这些能够用c语言中的struct描写叙述。

光栅化发生在哪一步?

通常在图形接口中会暴露顶点处理程序和片段处理程序(感觉着色器听起来也是云里雾里就换成处理程序),可是这其中gpu会进行光栅化插值计算,这也就是为什么片段处理程序的input是顶点处理程序的output经过了插值以后得到的值。既然光栅化是在顶点处理程序以后发生的步骤,那么输入的顶点结构是经过顶点处理以后的,也就是进行过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);

然后得到三个二维坐标代表三个顶点终于在屏幕上的位置,它们能够组成一个二维三角形,求取三角形的包围盒:”

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《=maxX;scrX++) {

for(int scrY=minY;scrY《=maxY;scrY++) {

。。.。

}

}

分别求取片段相应的标准化空间坐标:

invViewPortTransform(scrX,scrY,fb-》width,fb-》height,ndcX,ndcY);

这里用了逆视口变换,视口变换和逆视口变换非常方便,仅仅要对坐标进行缩放和平移即可了。

那么我们得到了可能片段的标准化空间的x和y坐标,为什么是可能片段呢?由于如今还没法确定这些片段在将要被光栅化三角形的外部还是内部,我们仅仅计算三角形内部的片段。

然而知道了这些有什么用呢?

这边有一个公式能够算出三个顶点对片段产生影响的比例,也叫权值:

b296322282fbc9a734deeeb8556b4922.png

这个公式的a b c分别代表三角形的三个顶点, ax ay aw 各自是顶点a在裁剪空间的齐次坐标(是四维的)的x y w值,这边没用到z值,由于z也要通过这个权值进行计算。

这个怎么推导这个公式?

已知待光栅化三角形abc的三个顶点在裁剪空间的齐次坐标,把权值alpha beta gamma设为pa pb pc,可得每一个片段的裁剪空间齐次坐标为:

x=pa*ax+pb*bx+pc*cx

y=pa*ay+pb*by+pc*cy

z=pa*az+pb*bz+pc*cz

w=pa*aw+pb*bw+pc*cw

然后计算片段在标准化坐标系的坐标值为:

nx=x/w

ny=y/w

nz=z/w

nw=1

能够推得:

x=w*nx

y=w*ny

w=w

由于:

x=pa*ax+pb*bx+pc*cx

y=pa*ay+pb*by+pc*cy

w=pa*aw+pb*bw+pc*cw

转换为3×3矩阵就是

ax bx cx pa w*nx ay by cy * pb = w*ny aw bw cw pc w

当中nx和ny就是之前取得的片段在标准化坐标系的x y值;而且因为pa pb pc是比值,所以w能够去除;这样仅仅要求取3×3矩阵的逆就能够取得pa pb pc的值。

可是要注意pa+pb+pc=1,所以计算出值以后要进行例如以下处理:

float sum=pa+pb+pc;

pa/=sum; pb/=sum; pc/=sum;

然后把有比值小于0的片段抛弃:

if(pa《0||pb《0||pc《0)

continue;

接下来就能够用这三个权值对顶点属性进行插值运算了。

详细的光栅化函数是这样:

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《=maxX;scrX++) {

for(int scrY=minY;scrY《=maxY;scrY++) {

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;

float sum=pa+pb+pc;

pa/=sum; pb/=sum; pc/=sum;

if(pa《0||pb《0||pc《0)

continue;

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

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了!

打开APP阅读更多精彩内容

点击阅读全文

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/178125.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午5:58
下一篇 2026年3月26日 下午5:58


相关推荐

  • mysql 符串类型的数字排序(字符串转数字)[通俗易懂]

    mysql 符串类型的数字排序(字符串转数字)[通俗易懂]针对字符串类型的字符排序需要先转换成数字再进行排序1.直接用加法  字符串+0select*fromordersorderby(mark+0)desc2.使用函数CAST(valueastype);CONVERT(value,type);注:这里的type可以为:浮点数:DECIMAL整数:SIGNED无符号整数:UNSIGNEDselect*fromordersorderby…

    2022年5月25日
    39
  • poj3984迷宫问题_迷宫代码

    poj3984迷宫问题_迷宫代码POJ 3984 迷宫问题

    2022年4月21日
    49
  • 永磁同步电机矢量控制(四)——simulink仿真搭建

    永磁同步电机矢量控制(四)——simulink仿真搭建由于是初学,对于simulink很多地方不熟悉,在此记下整个仿真搭建的选择元件的细节。1电机模型的选择及参数设置永磁同步电机的英文缩写为PMSM,全称PermanentMagnetSynchronousMachine。在library内搜索Permanent即可找到它。Numberofphase电机相数Back…

    2022年6月4日
    73
  • 惠普台式机如何装系统_惠普的台式机如何用u盘安装系统

    惠普台式机如何装系统_惠普的台式机如何用u盘安装系统惠普在计算机行业是一个很有声誉的品牌,无论是台式机还是笔记本,惠普都是一款值得考虑和购买的品牌产品之一。但是当计算机系统出了问题需要重装系统时,很多人并不知道如何进行系统的重装,那么惠普的台式机如何进行重装系统呢?下面介绍一下台式小机惠普电脑怎么装系统。惠普电脑装系统步骤阅读1、打开浏览器搜索云骑士官网,找到云骑士官网并点击打开。2、在官网下载云骑士一键重装系统软件,下载后打开云骑士装机大师。3、…

    2022年8月13日
    7
  • Could not find a version that satisfies the requirement tensorflow问题汇总+解决!!!

    Could not find a version that satisfies the requirement tensorflow问题汇总+解决!!!前言:极力推荐使用Anaconda——————————————————————————一般报错就是:问题一CouldnotfetchURLhttps://pypi.python.org/simple/….然后就是:问题二Couldnotfindaver…

    2022年6月25日
    42
  • linux下的C语言编程(总结篇)

    linux下的C语言编程(总结篇)【声明:版权所有,欢迎转载,请勿用于商业用途。联系信箱:feixiaoxing@163.com】在Linux下面关于C语言的内容其实挺多的。不同的人关注的地方也不一样。关注系统设计的人可能更关注整个linux系统的结构;设计驱动的人可能更关注linux驱动的配置和实现;而我在这里所关注的只是linux应用层方面的内容,属于最基础的内容,当然也是最重要的内容。实际上对应于………

    2022年7月26日
    11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号