gpt4 book ai didi

c# - 顶点着色和计算光照矢量效果

转载 作者:行者123 更新时间:2023-12-02 13:25:50 25 4
gpt4 key购买 nike

给定一个由三个 3D 点定义的三角形顶点,如何计算它与给定点之间的角度。

class Point3D
{
double x, y, z;
}

class Vertex
{
Point3D P1, P2, P3;
}

Point3D LightPoint;

http://www.ianquigley.com/iq/RandomImages/vextor.png

红色光点。蓝点 - 显示表面法线的三角形。

我需要计算表面法线,以及表面法线与 LightPoint 之间的角度。我找到了一些碎片,但没有找到将它们组合在一起的东西。

最佳答案

好的,开始了...

有点 A、B 和 C,每个点都有坐标 x、y 和 z。正如马蒂亚斯所说,您需要法线的长度,以便您可以计算点和法线原点之间的向量与法线本身形成的角度。它可能会帮助您认识到您的图像对于我们的计算目的具有误导性;法线(蓝线)应该从三角形的顶点之一发出。要将你的点变成向量,它必须到达某个地方,并且你只知道顶点的点(虽然你可以插入三角形内的任何点,但顶点着色的整个点不必这样做)。

无论如何,第一步是将 Point3D 转换为 Vector3D。这只需通过获取每个起点和目的地点坐标之间的差异即可完成。使用一个点作为两个向量的原点,另两点作为每个向量的目的地。因此,如果 A 是原点,则从 B 中减去 A,然后从 C 中减去 A。现在您有一个向量,该向量描述了从 A 点到 B 点以及从 A 点沿 X、Y 和 Z 轴移动的幅度值得注意的是,理论向量没有自己的起点;要到达 B 点,您必须从 A 开始并应用矢量。

System.Windows.Media.Media3D 命名空间有一个可以使用的 Vector3D 结构,并且很方便,同一命名空间中的 Point3D 有一个返回 Vector3D 的 Subtract() 函数:

Vector3D vectorAB = pointB.Subtract(pointA);
Vector3D vectorAC = pointC.Subtract(pointA);

现在,法线是两个向量的叉积。使用以下公式:

v1 x v2 = [ y1*z2 - y2*z1 , z1*x2 - z2*x1 , x1*y2 - x2*y1 ]

这是基于矩阵数学的,您不必严格了解即可实现它。矩阵中的三项是法向量的 X、Y 和 Z。幸运的是,如果您使用 Media3D 命名空间,Vector3D 结构有一个 CrossProduct() 方法可以为您执行此操作:

Vector3D vectorNormal = Vector3D.CrossProduct(vectorAB, vectorAC);

现在,您需要第三个向量,位于 LightPoint 和 A 之间:

Vector3D vectorLight = PointA.Subtract(LightPoint);

这是光线从光源到达 A 点的方向。

现在,要找到它们之间的角度,请计算这两者的点积以及这两者的长度:

|v| = sqrt(x^2 + y^2 + z^2)

v1 * v2 = x1*x2 + y1*y2 + z1*z2

或者,如果您使用 Media3D,Vector3D 具有 Length 属性和 DotProduct 静态方法:

double lengthLight = vectorLight.Length;
double lengthNormal = vectorNormal.Length;
double dotProduct = Vector3D.DotProduct(vectorNormal, vectorLight);

最后,Matias提到的公式:

v1 * v2 = |v1||v2|cos(θ)

重新排列和替换变量名称:

double theta = arccos(dotProduct/(lengthNormal*lengthLight))

或者,如果您足够聪明,可以使用 Media3D 对象,请忘记所有长度和点积内容:

double theta = Vector3D.AngleBetween(vectorNormal, vectorLight);

Theta 现在是角度(以度为单位)。如果您需要的话,将其乘以 2(pi)/360 即可得到弧度。

这个故事的寓意是,使用框架给你的东西,除非你有充分的理由不这样做;使用 Media3D 命名空间,所有向量代数都消失了,您可以在 5 行易于阅读的行中找到答案 [我编辑了此内容,添加了我使用的代码 - Ian]:

Vector3D vectorAB = Point3D.Subtract(pointB, pointA);
Vector3D vectorAC = Point3D.Subtract(pointC, pointA);
Vector3D vectorNormal = Vector3D.CrossProduct(vectorAB, vectorAC);
Vector3D vectorLight = Point3D.Subtract(pointA, LightPoint);

double lengthLight = light.Length;
double lengthNormal = norm.Length;
double dotProduct = Vector3D.DotProduct(norm, light);
double theta = Math.Acos(dotProduct / (lengthNormal * lengthLight));

// Convert to intensity between 0..255 range for 'Color.FromArgb(...
//int intensity = (120 + (Math.Cos(theta) * 90));

关于c# - 顶点着色和计算光照矢量效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3622136/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com