News:快速了解Stage3D的一个实例

来自Starling中文站
跳转到: 导航, 搜索

下面的这段代码出处在这里:

http://uh.9ria.com/link.php?url=http://bbs.9ria.com/viewthread.php?tid=108015

感谢原作者和译者。

为了方便像我这样的懒人,通过代码快速了解Stage3D,就把代码略微整理了一下,添加了注释,如下:

补充:参阅James Li的这篇教程,加深对Stage3D和AGAL的了解: http://www.adobe.com/cn/devnet/flash/articles/molehill_trangle.html

package
{
	import com.adobe.utils.AGALMiniAssembler;
 
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DBlendFactor;
	import flash.display3D.Context3DCompareMode;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.Program3D;
	import flash.display3D.VertexBuffer3D;
	import flash.display3D.textures.Texture;
	import flash.events.Event;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.utils.getTimer;
	import flash.display.BitmapData;
 
	/**
	 * 这是一个快速演示Stage3D用法的测试类,使用一张图片作为纹理
	 */	
	[SWF(backgroundColor="#000000")]
	public class TestStage3D extends Sprite
	{
		/**Context3D实例*/
		private var context3D:Context3D;
		/**用于向GPU提交顶点着色器和片段着色器的对象*/
		private var program:Program3D;
		/**顶点缓冲*/
		private var vertexbuffer:VertexBuffer3D
		/**顶点索引(确定三角形)*/
		private var indexBuffer:IndexBuffer3D;
		/**图片*/
		[Embed(source="assets/bird.png")]
		protected const birdTextureClass:Class;
		/**纹理*/
		public static var texture:Texture;
 
		/**@private*/
		public function TestStage3D()
		{
			super();
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			this.addEventListener(Event.ADDED_TO_STAGE,initApp);
		}
		/**
		 * 初始化应用
		 * @param args
		 */		
		private function initApp(...args):void
		{
			//有几个Stage3D实例可用.I got 4
			trace(stage.stage3Ds.length);
			//得到Stage3D实例
			var stage3D:Stage3D = stage.stage3Ds[0];
			//请求Context3D
			stage3D.addEventListener(Event.CONTEXT3D_CREATE,initStage3D);
			stage3D.requestContext3D();
		}
		/**
		 * 当Context3D可用,进一步初始化
		 * @param event
		 */		
		protected function initStage3D(event:Event):void
		{
			context3D = stage.stage3Ds[0].context3D;
			//输出加速类型,在Mac下输出'OpenGL'
			trace(context3D.driverInfo);
			//场景渲染大小为800乘以600像素,最小等级抗锯齿(第三个参数),并且为渲染表面创建深度和模版缓冲(第四个参数)
			context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, true);
			//设置混合模式
			context3D.setBlendFactors(Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
			//关闭深度测试,PNG透明背景必须
			context3D.setDepthTest(false, Context3DCompareMode.NOT_EQUAL);
			//设置纹理
			var birdBmd:BitmapData = (new birdTextureClass()).bitmapData;
			texture = context3D.createTexture(birdBmd.width, birdBmd.height, Context3DTextureFormat.BGRA, false);
			texture.uploadFromBitmapData(birdBmd);
			context3D.setTextureAt(0, texture);
			// 先把矩形的4个顶点定义出来,每个点有5个属性:x, y, z, u, v
			// x,y,z 是坐标系数值(-1到1),uv是坐标(0到1)
			var vertices:Vector.<Number> = Vector.<Number>([
				-0.8,0.8,0, 0, 0,
				-0.8, -0.8, 0, 0, 1,
				0.8, -0.8, 0, 1, 1,
				0.8, 0.8, 0, 1, 0]);
			// 单纯的数组无法提交给GPU,必须用顶点缓冲进行包装
			vertexbuffer = context3D.createVertexBuffer(4, 5);
			vertexbuffer.uploadFromVector(vertices, 0, 4);
			//Stage3D需要缓冲面,而一个三角形可以确定一个面,所以创建一个额外的数组,利用矩形的4个顶点,组成两个三角形,0,1,2是一个,2,3,0是另一个
			var indices:Vector.<uint> = Vector.<uint>([
				0, 1, 2, 
				2, 3, 0]);
			//同样这个数组也需要包装,用IndexBuffer3D
			indexBuffer = context3D.createIndexBuffer(6);  //两个三角形,6个顶点
			indexBuffer.uploadFromVector(indices, 0, 6);   //将数据置入缓冲区,0是起始索引,6是顶点数量
			//由于Stage3D使用可编程管道,要将数据提交给显卡,
			//必须有顶点着色器和片段着色器,而这两个着色器需要AGAL编写(一种汇编语言)
			//AGALMiniAssembler是Adobe提高的AGAL编写辅助工具
			var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();//顶点着色器
			vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
				"m44 op, va0, vc0\n" + 
				"mov v0, va1" 
			);
			var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();//片段着色器
			fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
				"tex ft0, v0, fs0 <2d>\n" +
				"mov oc, ft0"
			);
			//Program3D类负责将AGAL编写的着色器提交给显卡
			program = context3D.createProgram();
			program.upload(vertexShaderAssembler.agalcode,fragmentShaderAssembler.agalcode);
			//开始呈现
			//因为Stage3D是不透明的,这里将背景色设置为黑色
			context3D.clear( 0, 0, 0, 1 );
			//这里参照vertices的定义,每一个顶点定义的前三个是坐标(XYZ),所以用FLOAT_3
			//我们将XYZ数据填入到va属性寄存器中,编号为0(即va0),偏移量为0
			context3D.setVertexBufferAt (0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
			//同上理,UV信息是两位,所以用FLOAT_2,因为va0已经被使用了,所以我们va1中,偏移量为3(跳过XYZ)
			context3D.setVertexBufferAt(1, vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
			//应用着色器
			context3D.setProgram(program);
			//需要一个3维矩阵才能完成到2D屏幕的映射
			var m:Matrix3D = new Matrix3D();
			//把3维矩阵传递给着色器
			context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
			//绘制三角形,you know,最后的矩形是两个三角形组成的
			context3D.drawTriangles(indexBuffer);
			//绘制到屏幕
			context3D.present();
		}
	}
}

整理: 郭少瑞(NeoGuo)

个人工具
名字空间

变换
操作
导航
Starling中文资料
Starling原创教程
论坛
友链
工具箱