我正在使用基于顶点的三角形制作玩具光线跟踪器,类似于OpenGL。每个顶点都有自己的颜色,每个点上三角形的颜色应该基于顶点颜色的加权平均值,加上点与每个顶点的接近程度。
我无法弄清楚如何计算三角形上给定点的每种颜色的权重,以模仿OpenGL完成的颜色着色,如许多示例here所示。我有几个想法,但我不确定哪一个是正确的(V
是顶点,U
和W
是另外两个顶点,P
是要点颜色,C
是三角形的质心,|PQ|
是点P
到点Q
的距离:
1-(|VP|/max(|VU|,|VW|))
,因此V在两个顶点的较近处具有非零权重,我认为这是不正确的。1-(|VP|/min(|VU|,|VW|))
,因此V在两个顶点的较近处具有零权重,而在两个顶点的较远处具有负权重(其将饱和为0)。我不确定这是否正确。L
从V
延伸到P
到三角形的相对一侧(UW
):权重是|VP|
与{的比率{1}}。所以|L|
的重量在整个对面都是0。最后一个似乎最有可能,但我在实施它时遇到了麻烦,所以我不确定它是否正确。
答案 0 :(得分:4)
OpenGL使用重心坐标(精确线性插值,尽管您可以使用插值函数或最新版本中的centroid
或noperspective
等限定符来更改它。)
如果您不知道,重心坐标的作用如下:
对于由顶点V1,V2和V3组成的三角形中的位置P,其各自的系数是C1,C2,C3,例如C1 + C2 + C3 = 1(这些系数是指每个顶点在P的颜色中的影响)OpenGL必须计算那些结果等于
C1 = (AreaOfTriangle PV2V3) / (AreaOfTriangle V1V2V3)
C2 = (AreaOfTriangle PV3V1) / (AreaOfTriangle V1V2V3)
C3 = (AreaOfTriangle PV1V2) / (AreaOfTriangle V1V2V3)
并且三角形的面积可以用定义它的两个向量(在直接传感中)的叉积长度的一半来计算,例如AreaOfTriangle V1V2V3 = length(cross(V2-V1, V3-V1)) / 2
然后我们得到类似的东西:
float areaOfTriangle = length(cross(V2-V1, V3-V1)); //Two times the area of the triangle
float C1 = length(cross(V2-P, V3-P)) / areaOfTriangle; //Because A1*2/A*2 = A1/A
float C2 = length(cross(V3-P, V1-P)) / areaOfTriangle; //Because A2*2/A*2 = A2/A
float C3 = 1.0f - C1 - C2; //Because C1 + C2 + C3 = 1
但经过一些数学(以及一点点网络研究:D),我发现最有效的方法是:
YOURVECTYPE sideVec1 = V2 - V1, sideVec2 = V3 - V1, sideVec3 = P - V1;
float dot11 = dot(sideVec1, sideVec1);
float dot12 = dot(sideVec1, sideVec2);
float dot22 = dot(sideVec2, sideVec2);
float dot31 = dot(sideVec3, sideVec1);
float dot32 = dot(sideVec3, sideVec2);
float denom = dot11 * dot22 - dot12 * dot12;
float C1 = (dot22 * dot31 - dot12 * dot32) / denom;
float C2 = (dot11 * dot32 - dot12 * dot31) / denom;
float C3 = 1.0f - C1 - C2;
然后,要插入像颜色,color1,color2和color3这样的顶点颜色,你可以这样做:
float color = C1*color1 + C2*color2 + C3*color3;
但请注意,如果您正在使用透视变换(或隐含w
组件的任何顶点变换),这不能正常工作,所以在这种情况下,您必须使用方法:
float color = (C1*color1/w1 + C2*color2/w2 + C3*color3/w3)/(C1/w1 + C2/w2 + C3/w3);
w1
,w2
和w3
分别是V1
,V2
和V3
的原始顶点的第四个组成部分。
第一次计算中的V1
,V2
和V3
因为交叉积而必须是3维,但在第二个中(最有效),它可以是2维以及3维度,结果将是相同的(我想你猜测2D在第二次计算中速度更快),但在这两种情况下,如果你没有忘记将它们除以原始矢量的第四个分量。在这种情况下进行透视变换并使用第二个公式进行插值。 (如果您不理解,那些计算中的所有向量都不应该包含第四个组件!)
最后一件事;我强烈建议您使用OpenGL只需在屏幕上渲染一个大四边形并将所有代码放在着色器中(尽管您需要非常强大的OpenGL知识才能获得高级用途),因为您将从并行性中受益(即使是作为#!+视频卡),除非您在30年前的计算机上写过,或者您只是这样做以了解它是如何工作的。
答案 1 :(得分:0)
编辑:是的,这不回答这个问题 - 正确答案在上面的第一条评论中:使用重心坐标(这就是GL的作用)。