[翻译]XNA 3.0 Game Programming Recipes之thirtyeight

PS:自己翻译的,转载请著明出处格
                                                  6-2  在顶点之间共享法线
问题
                        在前面的章节,你学会如何确保每个三角形获得正确的光照通过提供法线数据在每一个它自己的顶点。
                        然而,盲目地应用这种方式对一个对象的所有三角形,得不到最好的效果。如果你得到一个三角形每个顶点同样的法线方向,一个三角形的每个顶点将会阴暗成同样的,因此所有三角形内部象素将会得到同样的阴影。
                        如果两个临近的三角(不在同一个平面)渐变就象这样,一个三角形的所有的象素可能得到同样的阴影,另外三角形的所有象素可以得到一个不同的阴影。这可以使它很容易看见它们之间的边框,因为,这两个三角形得到不同的最终的颜色。
                        你想获得一个更好的颜色结果,如果三角形的内部颜色不断的改变从一个三角形到另一个。为了完成这个,这阴影同样必须不断的改变从一个三角形到另一个三角形。
解决方案
                        阴影通过你的图象卡被计算为一个三角形的三个顶点(角),由于它们包含了法线。从这里,阴影是以内插值替换所有三角形内部象素。如果所有一个三角形的三个顶点的法线都是一样的,所有三角形内部象素将得到同样的阴影。如果它们不同,三个角将得到不同的阴影,这三角形内部象素将阴影遮盖,这样阴影在角之间变换的很平稳。
                        想象一下临近的两个三角形,共享一条边,由六个顶点定义。这种情况如图6-3左边部分所显示。为了使颜色不断的变换从一个三角形到另一个三角形,你需要确保颜色在两边是相同的。你可以完成这个只在当两个共享的顶点有相同的法线,因此有同样的阴影。在图6-3左边部分,这垂直与顶点1和4有同样的法线,顶点2和3也有同样的法线。

它是如何工作的

                        这一节,你定义两个三角形使用两个方法。首先,你绘制两个三角形,这样同样三角形的所有顶点都有同样的法线,这将导致均等的阴影为一个三角形内部的象素。接下来,你确保法线在共享顶点是相同的,这样你得到平滑的阴影通过三角形的边框。
每个三角形它自己的法线
                       这种方法归结为寻找垂直于三角形的方向,并且保存这个方向在它自己的每一个顶点,如图6-1所示。
                       下面代码定义了六个顶点如6-3左边所示。每个三角形的三个顶点有相同的法线方向,垂直于三角形。左边的三角形是垂直放置的,这样它的法线指向左边。第二三角形被水平放置,这样它的顶点指向上。
 1 private void InitVertices()
 2 {
 3       vertices=new VertexPositionNormalTexture[6];
 4       vertices[0]=new VertexPositionNormalTexture(new Vector3(0,-1,0),new Vector3(-1,0,0),new Vector2(0,1));
 5       vertices[1]=new VertexPositionNormalTexture(new Vector3(0,0,0),new Vector3(-1,0,0),new Vector2(0.5f,0));
 6       vertices[2]=new VertexPositionNormalTexture(new Vector3(0,0,0),new Vector3(-1,0,0),new Vector2(0.5f,1));
 7       vertices[3]=new VertexPositionNormalTexture(new Vector3(0,0,0),new Vector3(0,1,0),new Vector2(0.5f,1));
 8       vertices[4]=new VertexPositionNormalTexture(new Vector3(0,0,-1),new Vector3(0,1,0),new Vector2(0.5f,1));
 9       vertices[5]=new VertexPositionNormalTexture(new Vector3(1,0,0),new Vector3(0,1,0),new Vector2(1,1));
10       myVertexDeclaration=new VertexDeclaration(device,VertexPositionNormalTexture.VertexElement);
11 }
                        接下来,定义一个光照,它是非常亮从右边也可能有点低。确保你规格化这方向,这样它的长度正好为1:
1 Vector3 lightDirection=new Vector3(10,-2,0);
2 lightDirection.Normalize();
3 basicEffect.DirectionalLight0.Direction=lightDirection;
                        下一步,绘制两个三角形,使用这代码从前面的章节中:
1 basicEffect.Begin();
2 foreach(EffectPass pass in basicEffect.CurrentTechnique.Passes)
3 {
4      pass.Begin();
5      device.VertexDeclaration=myVertexDeclaration;
6      device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,vertices,0,2);
7      pass.End();   
8 }
9 basicEffect.End();
                        读这节"规格化你的法线"在6-1节去理解为什么你需要规格化光照的方向。
                        你可以看见两个三角形,它们两个有一个实心的颜色,如图6-4左边所示。因为这个,你很容易看见它们之间的边框,这绝对不是想要的大的物体。

共享法线

                        这次,你已经准备得到1和4两个顶点,和顶点2和3,相同的法线方向。有一个问题被提出来,它的方向你应该挑选。
                        为得到流畅的效果,你可以简单的采取平均的法线。可以使用下面的代码:
 1 private void InitVertices()
 2 {
 3      vertices=new VertexPositionNormalTexture[6];
 4      Vector3 normal1=new Vector3(-1,0,0);
 5      Vector3 normal2=new Vector3(0,1,0);
 6      Vector3 sharedNormal=normal1+normal2;
 7      sharedNormal.Normalize();
 8       vertices[0]=new VertexPositionNormalTexture(new Vector3(0,-1,0),new Vector3(-1,0,0),new Vector2(0,1));
 9       vertices[1]=new VertexPositionNormalTexture(new Vector3(0,0,0),new Vector3(-1,0,0),new Vector2(0.5f,0));
10       vertices[2]=new VertexPositionNormalTexture(new Vector3(0,0,0),new Vector3(-1,0,0),new Vector2(0.5f,1));
11       vertices[3]=new VertexPositionNormalTexture(new Vector3(0,0,0),new Vector3(0,1,0),new Vector2(0.5f,1));
12       vertices[4]=new VertexPositionNormalTexture(new Vector3(0,0,-1),new Vector3(0,1,0),new Vector2(0.5f,1));
13       vertices[5]=new VertexPositionNormalTexture(new Vector3(1,0,0),new Vector3(0,1,0),new Vector2(1,1));
14       myVertexDeclaration=new VertexDeclaration(device,VertexPositionNormalTexture.VertexElement);     
15 }
                         首先你总结两个三角形的两个法线。确保规格化这个结果,这样长度又变成了1(参看这节"规格化你的法线"在6-1)。这个结果的方向将会指向正确的在左和上之间的中间位置。
                         接下来,你定义的六个顶点。那两个外部的顶点没有共享,这样他们得到它们的旧法线。共享的顶点,虽然,得到同样的法线。
                         现在,当你绘制两个三角形,三角形的内部阴影将平滑的改变从外部顶点到共享边缘,如图6-4右边部分所显示的。这使它很难发现两个三角形之间的边缘,所以用户将不能看见对象由单独的三角形组成。
提示:5-7节描述你能计算共享的法线为大自动的对象。
                         你同样使用这个方法当使用这些索引时(参看5-3节)
代码
                        参看上面的代码!
原文地址:https://www.cnblogs.com/315358525/p/1543465.html