我正在使用基于顶点的三角形开发玩具光线追踪器,类似于 OpenGL。每个顶点都有自己的颜色,三角形每个点的着色应基于顶点颜色的加权平均值,并根据点与每个顶点的距离进行加权。
我不知道如何计算三角形上给定点处每种颜色的权重以模仿 OpenGL 完成的颜色着色,如许多示例所示 here 。我有几种想法,但不确定哪一种是正确的(V
是一个顶点,U
和 W
是另外两个顶点,P
是颜色点,C
是三角形的质心,|PQ|
是距点P的距离
指向Q
):
- 权重等于 `1-(|VP|/|VC|),但这会在质心处留下黑色(所有颜色的权重均为 0),这是不正确的。
- 权重等于
1-(|VP|/max(|VU|,|VW|))
,因此 V 在两个顶点较近的位置具有非零权重,我认为不正确。 - 权重等于
1-(|VP|/min(|VU|,|VW|))
,因此 V 在两个顶点较近的位置处的权重为零,负权重 (两者中较远的一个会饱和到 0)。我不确定这是否正确。 - 线段
L
从V
经过P
延伸到三角形的对边(UW
):权重是|VP|
与|L|
的比率。因此,V
沿相反一侧的权重均为 0。
最后一个似乎是最有可能的,但我在实现它时遇到了困难,所以我不确定它是否正确。
最佳答案
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;
然后,要插入诸如颜色、颜色 1、颜色 2 和颜色 3 作为顶点颜色的内容,您需要执行以下操作:
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 维的,但在第二个计算中(最有效),它可以是二维的,也可以是三维的,结果是相同的(我想你猜到第二次计算中二维更快),但在这两种情况下,不要忘记将它们除以原始值的第四个分量如果您正在进行透视变换,请使用向量,并在这种情况下使用第二个公式进行插值。 (如果您不明白,这些计算中的所有向量不应包含第四个分量!)
最后一件事;我强烈建议您使用 OpenGL,只需在屏幕上渲染一个大四边形并将所有代码放入着色器中(尽管您需要有关 OpenGL 的高级知识非常丰富的知识),因为您将受益于并行性(甚至可以从并行性中受益) #!+ 视频卡)除非您在一台 30 年前的计算机上编写该代码,或者您只是为了看看它是如何工作的。
关于opengl - 按顶点颜色为三角形着色的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26513712/