總結來說,Stage3D是跟GPU打交道的技術。涉及到幾方面的知識:
1、渲染的過程,3d管線的概念。有vertex shader,有fragment shader,這連個是管線裏邊提供接口出來,可供自定義編程的
http://hi.baidu.com/haorui1130/item/aa65dcceceaebf3f4494167b
2、Stage3D的context3d是核心,負責跟gpu打交道,上傳頂點信息xy、紋理信息uv、常量等。初始化時,每個xy對應一個uv
3、編寫兩個shader(利用AGAL),將上傳的信息計算出最後的結果值;
vertex shader負責計算圖形的大小變化、位置、旋轉;
fragment shader負責計算貼圖
需要注意的是:
- vertex shader對整個繪圖區域,以中心點爲原點,y軸向上,範圍[-1, 1];而普通stage座標是,左上角爲原點,y軸向下
- fragment shader的紋理座標又不一樣,左上角爲原點,y軸向下,範圍是[0, 1]
AGAL的指令,可以跟PixelBender的做比較,略有類似。
兩段程序,如果要執行片段shader,那麼在頂點shader的代碼最後需要把頂點位置信息傳到v0,以供片段shader取出來用
GPU會對每個頂點信息執行這兩個代碼,這就類似於PixelBender執行每一個像素
指令的相似:一樣用xyzxw存取float4,而float4跟float可以直接相乘,出來的還是float4。float4也可以乘以float4,出來的還是float4,是x和x,y和y分別相乘。
矩陣計算:
Matrix3D可以不斷乘以新的矩陣,等於多個變換集合在一起。比flash原來的Matrix好使多了。AGAL對Matrix3D的使用,其實跟flash普通sprite的matrix是同一個道理。
函數是append和prepend,兩者區別,打印矩陣一看就懂了
例子
利用Matrix3d和Vertex shader實現變形:
var matrix:Matrix3D = new Matrix3D(); matrix.appendScale(0.5, 0.5, 1); //縮小一倍 matrix.appendTranslation(0.5, 0.25, 0); //x移動0.5,也就是1/4,y移動0.25 matrix.appendRotation(45, new Vector3D(0,0,1)); //平時Sprite的旋轉45度 for (var i:int = 0; i < matrix.rawData.length; i+=4) { trace(matrix.rawData[i] + "\t" + matrix.rawData[i + 1] + "\t" + matrix.rawData[i + 2] + "\t" + matrix.rawData[i + 3]); } _context3d.setProgramConstantsFromMatrix( "vertex", 0, matrix, true); //這裏需要注意,涉及到位移,這裏需要把矩陣轉置一下,true表示先轉置一下。否則計算結果有問題 private var _vertexProgram:String = "m44 op, va0, vc0\n" + "mov v0, va1"; //傳遞給片段shader座標值
利用Matrix3d和Fragment Shader實現sepia效果(舊照片濾鏡):
private var _fragmentProgram:String = "tex ft1, v0, fs0<2d,linear,nomip>\n" + "m44 ft2, ft1, fc1\n" + //顏色變換 "mul ft2, ft2, fc0.x\n" + //效果圖跟原圖做multiply,向量float4 * float = float4,類似PixelBender "mul ft1, ft1, fc0.y\n" + "add ft2, ft2, ft1\n" + "mov oc, ft2" ; //multiple比例 _context3d.setProgramConstantsFromVector( "fragment" , 0, new<Number>[1, 0, 0, 0]); //顏色矩陣 _context3d.setProgramConstantsFromMatrix( "fragment" , 1, new Matrix3D( new <Number>[ 0.393, 0.768, 0.189, 0, 0.349, 0.686, 0.168, 0, 0.272, 0.534, 0.13, 0, 0, 0, 0, 1 ]));