我正在研究使用基于顶点的三角形的玩具光线追踪器,类似于 OpenGL。每个顶点都有自己的颜色,三角形在每个点的着色应基于顶点颜色的加权平均值,由该点与每个顶点的接近程度加权。
我无法弄清楚如何计算每种颜色的重量在上的三角形来模拟通过OpenGL做的颜色不均一个给定的点,如通过许多例子在这里。我有几个想法,但我不知道哪一个是正确的(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|来|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)
Run Code Online (Sandbox Code Playgroud)
并且三角形的面积可以用定义它的两个向量的叉积长度的一半来计算(在直接意义上),例如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
Run Code Online (Sandbox Code Playgroud)
但是经过一些数学(和一点点网络研究: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;
Run Code Online (Sandbox Code Playgroud)
然后,要插入诸如颜色、color1、color2 和 color3 之类的东西作为顶点的颜色,您可以执行以下操作:
float color = C1*color1 + C2*color2 + C3*color3;
Run Code Online (Sandbox Code Playgroud)
但请注意,如果您使用透视变换(或任何暗示w组件的顶点变换),这将无法正常工作,因此在这种情况下,您必须使用:
float color = (C1*color1/w1 + C2*color2/w2 + C3*color3/w3)/(C1/w1 + C2/w2 + C3/w3);
Run Code Online (Sandbox Code Playgroud)
w1,w2和w3分别由该原顶点的第四部件V1,V2和V3。
V1,V2并且V3在第一个计算中,由于叉积必须是 3 维的,但是在第二个(最有效的)中,它可以是 2 维的,也可以是 3 维的,结果将是相同的(我想你猜到了 2D在第二次计算中更快)但在这两种情况下,如果您正在进行透视变换,请不要忘记将它们除以原始向量的第四个分量,并在这种情况下使用第二个公式进行插值。(如果您不明白,这些计算中的所有向量都不应包含第四个分量!)
还有最后一件事;我强烈建议您仅通过在屏幕上渲染一个大四边形并将所有代码放入着色器中来使用 OpenGL(尽管您需要非常深入的 OpenGL 知识才能进行高级使用),因为您将从并行性中受益(甚至从 as #!+ 视频卡),除非您是在 30 年前的计算机上编写它,或者您只是为了看看它是如何工作的。
| 归档时间: |
|
| 查看次数: |
1867 次 |
| 最近记录: |