假设场景中有一个角色,带有骨骼动画,面数在3W左右。角色右上方有一个平行光源,光源会实时生成阴影贴图(shadow mapping)。
1、使用GPU更新骨骼动画。GPU很快,但是如果场景中带有会生成阴影贴图的光源时GPU就不得不多次计算同一个数据。
   也就是说从灯光方向看场景,生成depth map时需要把模型上的顶点更新到指定帧;
   在实际把场景显示到屏幕时也需要把模型上的顶点更新到指定帧。根据上面提到的情况GPU不得不对同一个顶点
   做两次骨骼更新运算。光源越多,计算次数越多,越不划算。 
2、使用CPU更新骨骼动画。虽然CPU计算能力不如GPU,但是CPU更新顶点后可以把顶点放在内存,之后不管什么时候
   需要这些数据都可以直接使用,不需要再次计算。 
计算骨骼动画有上面两种方法,但是不知道在多光源下哪个会比较有优势? 
在shader中有没有办法把计算好的顶点数据拿回内存?如果有,那么这个问题也可以得到解决。 
------------有效建议1------------
肯定用GPU了,一般最多也就四五个光源,如果你用的光源多肯定要用光源管理的方式每次只选择部分有效的光源,

基本不存在你讲的问题。 还有就是如果骨骼动画的顶点少,GPU肯定没有影响,如果顶点多了,就更要用GPU计算了。


======================================================================================


由于CPU与GPU之间进行数据传递并不像CPU从内存中调用数据那样方便,二者之间的数据传递
相对来说是比较费时的,特别是在传递大段数据的时候更是如此。所以在算法设计中应尽量
减少两者之间数据传递的频率,并且传递的数据量不要太大。
CPU与GPU之阆数据的传递方法有两种:
①直接传递,该方法在传递数据时消耗比较大。传递后的数据放在GPU的内存中,在GPU计算过程中调用比较方便;
②利用数据纹理进行传递,该方法在数据传递时消耗比较小。但传递后的数据存放在GPU的纹理内存中,
   为了获取所需的数据,我们需要计算出数据在纹理中的位置,并对相应位置的纹理进行采样。


以数据纹理作为传输方法,通过将骨骼动画创建到纹理中,再通过纹理采样的方式来获取骨骼矩阵。
本方法的优点在于减少了CPU与GPU之间的通讯,缺点在于仅使用GPU进行计算,加重了GPU的负担。
但是数据纹理作为一种能方便传输大量数据的方法,为实现骨骼动画提供了另一种途径。
预创建骨骼动画法可以将骨骼动画数据制作成纹理,也可以创建一个纹理的ResourceView将数据映射到纹理中去。
前者需要事先创建好纹理,而后者需要在初始化的过程中,计算骨骼动画的信息并映射到纹理的ResourceView中。
首先需要创建一个纹理或者一个ResourceView,然后将该资源传到GPU中去,然后对传递到GPU中的纹理进行采样
能够得到骨骼矩阵,最后利用骨骼矩阵对顶点信息进行更新。


======================================================================================


基于GPU的骨骼动画优化,其步骤如下:
1)根据当前的骨骼动画关键帧,更新骨骼动画的骨骼矩阵;
2)组织顶点,把局部坐标下的网格信息,包括影响该顶点的骨骼序号,传入到顶点着色器中。
    一般来说,我们限制一个顶点最多受3个骨骼的影响;
3)把更新之后的骨骼矩阵,作为常量寄存器传入到顶点着色器中,根据shader的版本,这个常量寄存器有着长度限制;
4)编写着色器代码,根据传入的顶点位置,影响该顶点的骨骼号,在顶点着色器中计算顶点的世界坐标;
5)根据顶点着色器的输出结果,对骨骼模型进行渲染。


======================================================================================


一个顶点最多受到4个骨骼的影响
因为每个float4只能存xyzw四个数,按照某些引擎的顶点着色器的处理,就只能记录4个骨骼索引号。

优化办法:
1,由于骨骼动画中经常使用的是相对父骨骼的位置旋转信息,基本不会对骨骼进行缩放,
      因此可将向GPU传入两个四元数(或者两个向量)代替传输矩阵,减少CPU GPU传输数据的总线带宽。
2,对关键帧信息预计算并保存到内存,毎帧直接从内存中取得当前帧对应的关键帧信息,避免毎帧的CPU计算。


======================================================================================


在HLSL脚本中,下面语句都可以正确的定义一个矩阵:

float2x2 fMatrix = { 0.0f, 0.1, // row 1
                      2.1f, 2.2f // row 2
                    }; 

 matrix <float, 2, 2> fMatrix = { 0.0f, 0.1,   // row 1
                                  2.1f, 2.2f   // row 2
                                };

 float4x4 worldMatrix = float4( {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} );
======================================================================================


顶点是每帧变化的,法线也要每帧变化吗?

由于顶点的位置变化了,三角形面片的朝向也就变化了,法线也要相应的进行变换。
如果你正在使用面法线,那么你每一帧都要重新计算面法线;
如果你正在使用顶点法线,并且一开始就计算了顶点法线,那么顶点法线不必完全重新计算,它们能利用和顶点相同的变换矩阵来进行变换。
        唯一不同的是,你不需要考虑平移,使用matrix类的Transform3()函数将旋转你的顶点法向量,同时仍能保留其原始大小。


======================================================================================