<p>在CG中,它是由多边形缠绕规则完成的。这意味着所有面都已定义,因此当直接在面上查看时,点按CW(或CCW)顺序排列。然后使用叉积将导致一致的法线</p>
<p>但是,许多网格不符合缠绕规则(有些面是CW的,有些面是CCW的,但不完全相同),对于这些网格来说,这是一个问题。我知道有两种方法:</p>
<ol>
<li><p><strong>对于简单形状(不太凹)</strong></p>
<p>你的<code>face_normal</code>和<code>face_center-cube_center</code>的点积符号将告诉你法线是指向对象的内部还是外部</p>
<p><a href="https://i.stack.imgur.com/mWYmf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mWYmf.png" alt="dot"/></a></p>
<pre><code>if ( dot( face_normal , face_center-cube_center ) >= 0.0 ) normal_points_out
</code></pre>
<p>您甚至可以使用面上的任意点,而不是面中心。无论如何,对于更复杂的凹面形状,这将无法正常工作</p></li>
<li><p><strong>测试表面上方的点是否在内部</strong></p>
<p>只需沿法线方向将面中心移动一小段距离(不要太大),然后测试该点是否位于多边形网格内:</p>
<p><a href="https://i.stack.imgur.com/FXbnv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FXbnv.png" alt="displacement"/></a></p>
<pre><code>if ( !inside( face_center+0.001*face_normal ) ) normal_points_out
</code></pre>
<p>要检查点是否在内部,可以使用<a href="https://stackoverflow.com/a/24465094/2521214">hit test</a></p></li>
</ol>
<p>但是,如果法线仅用于照明计算,则其使用通常在点积中。因此,我们可以使用它的abs值来代替,这将解决所有照明问题,而不管正常侧如何。例如:</p>
<pre><code>output_color = face_color * abs(dot(face_normal,light_direction))
</code></pre>
<p>一些gfx API已经实现了这一点(查找双面材质或法线,打开它们通常使用abs值…),例如在OpenGL中:</p>
<pre><code>glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
</code></pre>