Molehill初探

  关注flash的同学肯定都知道Adobe推出了新的基于硬件加速的API Molehill。它可以在60Hz左右的高分辨率显示器下全屏渲染近百万的Z缓冲三角形。就算你的显卡不兼容,也会通过一个叫SwiftShader软件来利用CPU进行渲染。

  我们熟悉的2D显示列表位于Molehill的Stage3D上面,而Stage3D又位于StageVideo上面。实际上3D内容可以通过bitmapdata呈现在2D显示列表中。

  下图表示了Molehill的基本架构

  

Molehill初探

  

  下面的代码在Stage3D中创建了一个三角形,从中我们可以略微熟悉一下这套API的用法

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.Context3DProgramType;

	import flash.display3D.Context3DTriangleFace;

	import flash.display3D.Context3DVertexBufferFormat;

	import flash.display3D.IndexBuffer3D;

	import flash.display3D.Program3D;

	import flash.display3D.VertexBuffer3D;

	import flash.events.Event;

	import flash.geom.Matrix3D;

	import flash.geom.Rectangle;

	

	[SWF(width="980", height="570", frameRate="60")]

	public class MoleHillTest extends Sprite

	{

		//Context3D 是渲染发生的地方,它和Stage3D的关系就像bitmapdata和bitmap的关系

		private var context3d:Context3D;

	

		//VertexBuffer3D将存储顶点数据

		private var vertexBuffer:VertexBuffer3D;

	

		//这里定义顶点的渲染顺序

		private var indexBuffer:IndexBuffer3D;



		//Program3D是用来包含两个着色器的

		private var program:Program3D;



		//这是一个矩阵,我们的顶点着色器将使用它来修改顶点的位置

		private var model:Matrix3D=new Matrix3D();

		

		public function MoleHillTest()

		{

		

			//监听flash什么时候给我们返回一个Context3D对象,因为当你请求Context3D的时候,flash不一定会马上回应

			stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onGotContext);

			//请求一个Context3D对象

			stage.stage3Ds[0].requestContext3D();

			

		}

		protected function onGotContext(ev:Event):void

		{

			//获得Stage3D对象,它将给我们Context3D

			var stage3d:Stage3D=Stage3D(ev.currentTarget);

			//我们获得了Context3d

			context3d=stage3d.context3D;

			//如果没有获得,那我们就跳出函数

			trace(context3d)

			if(context3d==null)

				return;

			//当发生问题的时候,我们可以获得error信息。请在正式发布的时候设为false以提高性能

			context3d.enableErrorChecking=true;

			//基本上,你可以看成是 new BitmapData(980, 570),表示渲染的大小。而4表示反锯齿的强度,可以设置的值为0,2,4,16.

			context3d.configureBackBuffer(980, 570, 4, true);

			//这里是说当三角形没有对着我们的时候,就不要渲染它,还有可能的值是Context3DTriangleFace.FRONT,Context3DTriangleFace.FRONT_AND_BACK,Context3DTriangleFace.NONE。

			context3d.setCulling(Context3DTriangleFace.BACK);

			//创建一个顶点缓冲,我们将有3个顶点(三角形),每个顶点包含6个元素,分别表示

			//x坐标,y坐标,z坐标,红色,绿色,蓝色。

			vertexBuffer=context3d.createVertexBuffer(3, 6);

			//为顶点创建一个索引缓冲来为三角形排序,我们有一个三角形,因此这里有3个顶点,因此有3个索引

			indexBuffer=context3d.createIndexBuffer(3);

			//顶点数据包含每个顶点的位置信息以及颜色信息

			//x==-1表示屏幕的左边

			//x==1表示屏幕的右边

			//x==0表示屏幕的中央

			//y也是同样的道理。1,0,-1分别表示屏幕的上中下

			//颜色值在0-1之间,比如1,0,0表示纯红色

			//下面的数据描述了一个三角形,它左下角的顶点是红色,中间上面的顶点是绿色,右下角的顶点是蓝色

			var vertexData:Vector.<Number>=Vector.<Number>(

				[

					-1, -1, 0,  255/255, 0, 0, //<- 1st vertex x,y,z,r,g,b

					0, 1, 0,  0, 255/255, 0, //<- 2nd vertex x,y,z,r,g,b

					1, -1, 0,  0, 0, 255/255 //<- 3rd vertex x,y,z,r,g,b

				]

			);

			//这个是我们渲染顶点的顺序,0是第一个顶点,1是第二个,2是第三个。

			var indexData:Vector.<uint>=Vector.<uint>([0, 1, 2]);

			//将我们的顶点数据传递给顶点缓冲

			vertexBuffer.uploadFromVector(vertexData, 0, 3);

			//将我们表示顺序的索引值传递给顶点缓冲

			indexBuffer.uploadFromVector(indexData, 0, 3);

			//AGAL(Adobe Graphics Assembly Language)是Adobe开发的图形汇编语言,可以操控机器硬件比如可编程显卡

			//AGALMiniAssembler是Adobe官方提供的编译器类,它通过字符串指令来获得一个AGAL二进制流,再通过context3D上传给显卡的编程管线。最后由显卡来处理顶点以及片段的运算

			//在此我们创顶点和片段两个‘编译器’,来处理顶点和片段

			var agalVertex:AGALMiniAssembler=new AGALMiniAssembler();

			var agalFragment:AGALMiniAssembler=new AGALMiniAssembler();

			//m44 op, va0, vc0 表示应用一个4x4矩阵到我们的顶点并输出到屏幕

			//mov v0, va1 表示取出我们顶点的颜色值,并传给片段着色器

			var agalVertexSource:String="m44 op, va0, vc0\n" +

				"mov v0, va1\n";

	

			//将我们的颜色输出到屏幕

			var agalFragmentSource:String="mov oc, v0\n";

			//编译AGAL源字符串,这个过程中将产生一个ByteArray供着色器使用

			agalVertex.assemble(Context3DProgramType.VERTEX, agalVertexSource);

			agalFragment.assemble(Context3DProgramType.FRAGMENT, agalFragmentSource);



			//创建一个Program3D来使用我们的着色器,包括顶点着色器和片段着色器,Program3D是显卡管线上的程序

			program=context3d.createProgram();



			//传递编译过的着色器给我们的Program3D使用

			program.upload(agalVertex.agalcode, agalFragment.agalcode);

			

			//定时触发渲染

			addEventListener(Event.ENTER_FRAME, onRenderLoop);

		}

		

		protected function onRenderLoop(event:Event):void

		{

			

			//清除颜色和透明度

			context3d.clear(0.5, 0.5, 0.5, 1);



			//设置会渲染到屏幕上的Program3D

			context3d.setProgram(program);

		

			//现在我们为顶点缓冲定义两个属性val0和val1,val0表示位置,val1表示颜色

			//第一个参数是属性的id,0代表位置val0,1代表颜色val1;第二个参数vertextBuffer提供了运算对象;第三个参数表示该属性要从什么位置开始取值;第四个参数可以理解为取几个值

			context3d.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);

			//颜色值是从3开始的,所以从3取值,如果使用的是带alpha的颜色值,可能最后一个参数就该使用 Context3DVertexBufferFormat.FLOAT_4

			context3d.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);

			

			//重设矩阵

			model.identity();



			//将三角形在x,y,z上各缩放0.5倍;你还可以通过model.appendScale,model.appendTranslation来旋转和移动三角形

			model.appendScale(0.5, 0.5, 0.5);

		

			//通过矩阵定义一个常量

			context3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, model);

	

			//将三角形绘制到屏幕,0表示起始位置,1表示我们只画一个三角形

			context3d.drawTriangles(indexBuffer, 0, 1);

		

			//将三角形显示到屏幕上

			context3d.present();

		}

	}

}    

  其中最核心的是Context3D,它是一个三维空间的处理环境,负责创建并处理三维对象的各个要素比如顶点、片段、透视等,并将处理的结果使用AGAL(Adobe Graphics Assembly Language)传递给显卡进行运算,运算结果最终被传给CPU并呈现在舞台上。

  如果你对上面的代码感到疑惑和陌生,这很正常,毕竟这套API是为底层3D开发者准备的,幸好大家所熟知的ActionScript 3D第三方框架如Alternativa3D, Away3s, Flare3D都开始支持Molehill了,因此对于AS开发者来说,我们可以在更高的层次去开发3D应用而不用去过多了解底层的实现。同时还有人开发了一些东西让Stage3D来加速2D图形的渲染,比如M2D框架。

  最后,如果你想测试上面的代码,请配置好你的运行环境使其能支持molehill,具体的配置方法请google ‘Molehill配置’。

你可能感兴趣的:(ol)