2

我目前正在使用 JavaFX 3D 应用程序,并在 TriangleMesh 类中遇到了 getNormals() 方法。

如 TriangleMesh 类用于创建用户定义的 Java FX 3D 对象,其中
getPoints() 用于添加点
getFaces() 用于添加面
getTexCoords() 用于管理 3D 对象的纹理,
但我不确定TriangleMesh 类中 getNormals() 方法的用途。

在 TriangleMesh 类中,我们可以将顶点格式设置为 VertexFormat.POINT_TEXCOORD 和 VertexFormat.POINT_NORMAL_TEXCOORD。
但是如果我们将 vertexFormat 设置为“VertexFormat.POINT_NORMAL_TEXCOORD”,那么我们需要将法线索引添加到 Faces 中,如下所示:
[ p0, n0, t0, p1, n1, t1, p3, n3, t3, // 第一个三角形带纹理的矩形

p1, n1, t1, p2, n2, t2, p3, n3, t3 // 纹理矩形的第二个三角形]

https://docs.oracle.com/javase/8/javafx/api/javafx/scene/shape/TriangleMesh.html中所述

如果我使用 vertexFormat 作为 POINT_TEXCOORD 或 POINT_NORMAL_TEXCOORD,我没有发现 3D 形状有任何区别。

那么在 TriangleMesh JavaFX 中 getNormals() 方法有什么用呢?

提前致谢..

4

1 回答 1

3

在计算机图形学中使用法线

法线通常在计算机图形学中用于确定表面朝向光源的方向以进行平面着色,或确定每个角(顶点)的方向以模拟具有 Phong 着色的曲面。


法线影响应用于面的着色。

JavaFX 8 的标准着色机制是Phong ShadingPhong Reflection Model。默认情况下,Phong 着色假定平滑变化(线性插值)表面法线向量。这允许您通过提供有限顶点几何图形的着色来渲染球体。默认情况下,法线向量s 将被计算为垂直于面。

JavaFX 允许您提供自己的法线,而不是依赖默认计算的法线。然后,JavaFX 中的 Phong 着色算法实现将在您提供的法线之间进行插值,而不是在它计算的法线之间进行插值。改变表面法线的方向将通过改变模型表示光线从其反射回来的方式来改变着色模型,本质上,光线将以修改后的法线在不同的方向上反射。

这个来自 Wikipedia 的示例在右侧显示了一个 phong 阴影球体。两个球体实际上具有相同的几何形状。对 phong 着色方程有贡献的法线分布是默认的,基于每个面的标准法线计算平滑插值(因此不提供用户法线)。PhongMaterial javadoc中描述了用于计算阴影的公式,您可以在此处看到法线对阴影算法的贡献,包括漫反射颜色和镜面高光的计算。

phong 阴影

标准 3D 模型,例如obj 文件可以选择允许提供法线:

vn ijk

多边形和自由形式的几何语句。

指定具有分量 i、j 和 k 的法线向量。

顶点法线影响几何体的平滑着色和渲染。对于多边形,使用顶点法线代替实际的面法线。对于曲面,顶点法线在整个曲面上进行插值并替换实际的解析曲面法线。

当存在顶点法线时,它们会取代平滑组。

ijk 是顶点法线的 i、j 和 k 坐标。它们是浮点数


那么,你为什么想要它?

最简单的解释方法可能是查看所谓的平滑组(请单击链接,由于版权原因,我不会在此处嵌入)。从链接的图像可以看出,当平滑组应用于面部集合时,可以在分组的面部之间获得清晰的轮廓(例如折痕或角)。指定法线允许您完成与平滑组类似的事情,只是具有更多控制权,因为您可以为每个顶点指定单独的法线,而不是为相关面的整体组指定。注意 JavaFX 允许您通过getFaceSmoothingGroups()指定平滑组,以用于您不想通过getNormals()定义完整法线几何的麻烦。

另一个类似的想法是法线贴图(或凹凸贴图)。这样的贴图将法线信息存储在图像中,而不是作为矢量信息,例如getNormals()方法,所以它是一个稍微不同的东西。但是你可以看到与反射模型算法类似的交互:

法线贴图

背景阅读 - 如何理解 Phong 材料(和其他东西)

于 2016-06-28T10:04:36.160 回答