gouroud算法实现的相关问题总结和解析

本文针对Gouraud算法在3D图形渲染过程中遇到的非正规三角形问题进行了深入探讨,通过实例分析了颜色不融合现象的原因,并提出了相应的解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在用gouroud算法给3d图形进行渲染时。大致思路是将三角形分成三种结构, 第一是top, 第二种是bottom,第三种则是其他情况
如图

对于第三种情况,结合作者在实现过程中遇到的问题,进行以下几点总结分析 (以下用加粗红色字母“c”指代非正规三角形)
1 : 在绘制c的时候, 会出现一下这种情况。请看图(1-1)

  

                           (1-1)                                                                                                                 (1 - 2)
                                    

图(1-2)是一个c, 而在绘制的时候人工的将其分成两个三角形进行绘制,
结合(1-1)(1-2)
很容易发现m区的颜色渲染明显和n区不相融合,那么究竟是哪里出了问题呢?
解析:
为了方便说明,我将自己实现的部分代码截图粘贴在下面(1-3)

                                             (1 - 3)
第一:c的绘制思路。
我们能从代码上得到一条信息,
DrawTopTriangle_Gouroud
DrawBottomTriangle_Gouroud
这两个接口他们是共用同样的三个顶点的。

c本身是非正规的,但通过(1-2)我们可以发现他的实现是可以通过两个正规三角形组合绘制而成。

第二:分析问题出现原因
根据gouroud的绘制原理,在y坐标不变的情况下,计算出x轴方向的深度斜率dz, 红色斜率dr,绿色斜率dg和蓝色斜率db,用来实现图形渲染。
具体代码如下所示:

在此对dr进行举例说明问题原因。在作者的程序,绘制top,永远假定middle.x > bottom.x。 
fSize的结果是对x_mt,x_bt比较之后,用较大的减去较小的,从而保证了fSize > 0.那么如果
middle.x < bottom.x 那么在计算dr的时候人工手动改变了fsize的正负值,那么为了保证dr的正确性,
应该手动将redtm,redtb二者的数值进行互换。

其次,结合图(1-1),(1-2)观察c,可以发现,m区和n区他们是共享y = middle.y这个横线的(接下来用红色粗体字母d指代这条直线).那么当top的绘制,
由于middle.x < bottom.x,进行颜色斜率和深度斜率交换,此时d已经被绘制(理解这句很重要!:))。
此时top已经绘制完毕,[假定](d左定点的颜色是1,右定点的颜色是2, 即d的颜色是从做到右逐渐加深的)。接下来根据代码截图(1-3),要绘制bottom。而bottom此时的绘制如果不进行斜率互换,那么就会出现图(1-1)的结果.
拿[假定]来进行简单的分析,在top中由于斜率互换,d的颜色随着x的增加而加深。如果bottom不进行
斜率互换,那么就会造成d的颜色左定点是2,右定点是1,导致深度变化和top方向相反. 这就是作者最初犯错误的原因,即导致图(1-1)绘制效果的原因。


fSize = (fxmax - fxmin) + 1;
有的小伙伴可能会问了, 为什么要手动改变fSize的正负值呢? 如果不改变直接写成
dr = (redtm - redtb) / (x_tm - x_tb)不就得了。这样写乍一看没啥问题,但细细想来,如果x_tm == x_tb呢?
由于我们此时并不知道x_tm和x_tb的大小,后面的那个1不知道怎么加上去。(加1是为了保证党x_tm == x_tb的时候则应绘制一个像素点,即这条长度为零的直线的左端点)。所以最后还是要对x_tm, x_tb比较大小。然后将二者比较后的绝对者 + 1.


常见问题解答 :

1 ,在代码中为什么要对1/z1操作处理,而不是直接用z? (z-buffer的原理公式)
解析:

ax + by + cz + d = 0; (1-1)

在绘制3d图形的时候我们最后用的都是透视坐标
根据透视坐标共识
xp = x *d/ z;(1-2)
yp = y * d /z;(1-3)
可以推出
x = xp * z / d;
y = yp * z / d;
然后将x, y带入(1-1)中
,得到(a/dc)*xp + (b/dc)*yp = (-1) * (1/z + 1) .


所以最后得出的结论是xp, yp, (-1)*(1/z)成线性关系。


2, 在接口drawtop_gouroud和drawbottom_gouroud中都用到了
        long midX = (long)( top.x + (middle. y - top .y) * dx_bt);

这个公式的意义是什么,依据的又是什么原理呢?

他的意义在于判断,middle.x是否在d线的左侧,如果不是,则根据作者在设计程序时的假定,对颜色斜率值
进行互换。

原理是相似三角形公式。请看图(1-4)


具体代码实现,我放到了代码片段里面,需要的小伙伴可以作为参考。


邮箱 : matrix_zxf@yahoo.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值