必備知識
用戶級別
必需產品
- Flash Builder (下載試用版)
- Flash Professional (下載試用版)
- Flash Player
引言
瞭解透視技術
將透視轉換成數學函數
圖1. 一個3D對象的透視投影
- xP = K1 * xW / zW
- yP = K2 * yW / zW
將透視數學函數轉換成代碼
- xW -> xP' = xP * zW = K1 * xW
- yW -> yP' = yP * zW = K2 * yW
- zW -> zP' = K3 * (zW - zNear)
- xP = K1 * xW
- yP = K2 * yW
- zP = K3 * (zW - zNear) / zW
- (x, y, z, w) = (xP', yP', zP', zW)
使用PerspectiveMatrix3D
- K1 = zProj / aspect
- K2 = zProj
- K3 = zFar / (zFar – zNear)
圖2. 投影參考系統的side視圖
- zProj = 1 / tg (fov/2)
- K1 = 1 / (aspect*tg(fov/2))
- K2 = 1 / tg(fov/2)
- K3 = zFar / (zFar – zNear)
- PerspectiveMatrix3D::perspectiveFieldOfViewLH
- PerspectiveMatrix3D::perspectiveFieldOfViewRH
- var aspect:Number = 4/3;
- var zNear:Number = 0.1;
- var zFar:Number = 1000;
- var fov:Number = 45*Math.PI/180;
- var projectionTransform:PerspectiveMatrix3D = new PerspectiveMatrix3D();
- projectionTransform.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
構建一個透視投影範例應用程序
- var m:Matrix3D = new Matrix3D();
- m.appendRotation(getTimer()/30, Vector3D.Y_AXIS);
- m.appendRotation(getTimer()/10, Vector3D.X_AXIS);
- m.appendTranslation(0, 0, 2);
- m.append(projectionTransform);
- public class PerspectiveProjection extends Sprite
- {
- [Embed( source = "RockSmooth.jpg" )]
- protected const TextureBitmap:Class;
-
- protected var context3D:Context3D;
- protected var vertexbuffer:VertexBuffer3D;
- protected var indexBuffer:IndexBuffer3D;
- protected var program:Program3D;
- protected var texture:Texture;
- protected var projectionTransform:PerspectiveMatrix3D;
-
-
- public function PerspectiveProjection()
- {
- stage.stage3Ds[0].addEventListener( Event.CONTEXT3D_CREATE, initMolehill );
- stage.stage3Ds[0].requestContext3D();
- stage.scaleMode = StageScaleMode.NO_SCALE;
- stage.align = StageAlign.TOP_LEFT;
- addEventListener(Event.ENTER_FRAME, onRender);
- }
-
- protected function initMolehill(e:Event):void
- {
- context3D = stage.stage3Ds[0].context3D;
- context3D.configureBackBuffer(800, 600, 1, true);
-
- var vertices:Vector.<Number> = Vector.<Number>([
- -0.3,-0.3,0, 0, 0, // x, y, z, u, v
- -0.3, 0.3, 0, 0, 1,
- 0.3, 0.3, 0, 1, 1,
- 0.3, -0.3, 0, 1, 0]);
-
- // 4 vertices, of 5 Numbers each
- vertexbuffer = context3D.createVertexBuffer(4, 5);
- // offset 0, 4 vertices
- vertexbuffer.uploadFromVector(vertices, 0, 4);
-
- // total of 6 indices. 2 triangles by 3 vertices each
- indexBuffer = context3D.createIndexBuffer(6);
-
- // offset 0, count 6
- indexBuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
-
- var bitmap:Bitmap = new TextureBitmap();
- texture = context3D.createTexture(bitmap.bitmapData.width, bitmap.bitmapData.height, Context3DTextureFormat.BGRA, false);
- texture.uploadFromBitmapData(bitmap.bitmapData);
-
- var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
- vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
- "m44 op, va0, vc0\n" + // pos to clipspace
- "mov v0, va1" // copy uv
- );
- var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
- fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
- "tex ft1, v0, fs0 <2d,linear,nomip>\n" +
- "mov oc, ft1"
- );
-
- program = context3D.createProgram();
- program.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
-
- projectionTransform = new PerspectiveMatrix3D();
- var aspect:Number = 4/3;
- var zNear:Number = 0.1;
- var zFar:Number = 1000;
- var fov:Number = 45*Math.PI/180;
- projectionTransform.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
- }
-
- protected function onRender(e:Event):void
- {
- if ( !context3D )
- return;
-
- context3D.clear ( 1, 1, 1, 1 );
-
- // vertex position to attribute register 0
- context3D.setVertexBufferAt (0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
- // uv coordinates to attribute register 1
- context3D.setVertexBufferAt(1, vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
- // assign texture to texture sampler 0
- context3D.setTextureAt(0, texture);
- // assign shader program
- context3D.setProgram(program);
-
- var m:Matrix3D = new Matrix3D();
- m.appendRotation(getTimer()/30, Vector3D.Y_AXIS);
- m.appendRotation(getTimer()/10, Vector3D.X_AXIS);
- m.appendTranslation(0, 0, 2);
- m.append(projectionTransform);
-
- context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
-
- context3D.drawTriangles(indexBuffer);
-
- context3D.present();
- }
- }