前面已经学习了“常见的3D显像术语”与“常见的3D编码术语”。今天所要探讨的是Molehill。
什么是Molehill:
Molehill是Adobe官方预计推出的一套底层3D渲染引擎,该引擎能够调用GPU,借助GPU强大的浮点运算能力实现开创新的Flash3D技术。
package
{
import com.adobe.utils.AGALMiniAssembler;
import com.adobe.utils.PerspectiveMatrix3D;
import flash.display.Bitmap;
import flash.display.BitmapData;
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.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.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
[SWF(width=1024,height=590)]
public class lesson1 extends Sprite
{
[Embed(source = "assset/bricks_a_spec.jpg")]
private var myTextureBitmap:Class;
/**
* 舞台的宽度
*/
public const stageW:int = 1024;
/**
* 舞台的高度
*/
public const stageH:int = 590;
/**
* 纹理大小
*/
public const textureSize:int = 512;
/**
* 3D图形窗口
*/
private var context3D:Context3D;
/**
*定义着色器
*/
private var shaderProgram:Program3D;
/**
* 定义一个顶点缓冲
*/
private var vertexBuffer:VertexBuffer3D;
/**
* 定义一个索引缓冲
*/
private var indexBuffer:IndexBuffer3D;
/**
* 定义网格的顶点数据
*/
private var meshVertexData:Vector.<Number>;
/**
* 定义网格的索引数据
*/
private var meshIndexData:Vector.<uint>;
/**
* 影响模型位置和相机的角度的矩阵
*/
private var projectionMatrix3D:PerspectiveMatrix3D = new PerspectiveMatrix3D();
/**
* 定义一个模型的矩阵
*/
private var modelMatrix:Matrix3D = new Matrix3D;
/**
* 定义一个视图的矩阵
*/
private var viewMatrix:Matrix3D = new Matrix3D;
/**
* 定义一个投影
*/
private var modelViewProjection:Matrix3D = new Matrix3D;
/**
* 用于动画的帧计数器
*/
private var t:Number = 0;
/**
* 创建纹理
*/
private var myTextureData:Bitmap = new myTextureBitmap();
private var myTexture:Texture;
public function lesson1()
{
this.stage ? addEventListener(Event.ADDED_TO_STAGE,init) : init();
}
private function init(event:Event = null):void
{
hasEventListener(Event.ADDED_TO_STAGE) && removeEventListener(Event.ADDED_TO_STAGE,init);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE,onContext3DCreate);
stage.stage3Ds[0].requestContext3D();
}
private function onContext3DCreate(event:Event):void
{
removeEventListener(Event.CONTEXT3D_CREATE,onContext3DCreate);
var stage3D:Stage3D = event.target as Stage3D;
context3D = stage3D.context3D;
if(!context3D)
{
return;
}
context3D.enableErrorChecking = true;
initData();
}
private function initData():void
{
//定义一个正方形的顶点信息
meshVertexData = Vector.<Number>([
-1, -1, 1, 0, 0, 0, 0, 1,
1, -1, 1, 1, 0, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
-1, 1, 1, 0, 1, 0, 0, 1
]);
// 定义一个正方形的索引
meshIndexData = Vector.<uint>
([
0,1,2, 0,2,3
]);
// 3D缓冲区的像素尺寸
context3D.configureBackBuffer(stageW,stageH,0,true);
//创建一个顶点着色器
var vertexShader:AGALMiniAssembler = new AGALMiniAssembler();
vertexShader.assemble
(
Context3DProgramType.VERTEX,
// 创建一个4X4矩阵乘以相机角度
"m44 op, va0, vc\n"+
//告诉片段着色器X,Y,Z的值
"mov v0, va0\n"+
//告诉片段着色器u,v的值
"mov v1, va1\n"
);
// 创建一个片段着色器
var pixelShader:AGALMiniAssembler = new AGALMiniAssembler();
pixelShader.assemble
(
Context3DProgramType.FRAGMENT,
"tex ft0, v1, fs0 <2d,repeat,miplinear>\n"+
// 结果输出
"mov oc, ft0\n"
);
shaderProgram = context3D.createProgram();
//上传网格索引
shaderProgram.upload(vertexShader.agalcode,pixelShader.agalcode);
indexBuffer = context3D.createIndexBuffer(meshIndexData.length);
indexBuffer.uploadFromVector(meshIndexData,0,meshIndexData.length);
// 上传网格顶点数据
// 因为包含X,Y,Z,U,V,nX,nY,nZ 所以每个顶点各占8个数组元素
vertexBuffer = context3D.createVertexBuffer(meshVertexData.length/8,8);
vertexBuffer.uploadFromVector(meshVertexData,0,meshVertexData.length / 8);
//产生MIP映射
myTexture = context3D.createTexture(textureSize,textureSize,Context3DTextureFormat.BGRA,false);
var ws:int = myTextureData.bitmapData.width;
var hs:int = myTextureData.bitmapData.height;
var level:int = 0;
var transform:Matrix = new Matrix();
var tmp:BitmapData = new BitmapData(ws,hs,true,0x00000000);
while(ws >=1 && hs >=1)
{
tmp.draw(myTextureData.bitmapData,transform,null,null,null,true);
myTexture.uploadFromBitmapData(tmp,level);
transform.scale(0.5,0.5);
level++;
ws >>=1;
hs >>=1;
if(hs && ws)
{
tmp.dispose();
tmp = new BitmapData(ws,hs,true,0x00000000);
}
}
tmp.dispose();
// 创建透视矩阵
projectionMatrix3D.identity();
// 设置45度视角,1024 / 590 长宽比,0,1的近裁剪面,100的远裁剪面
projectionMatrix3D.perspectiveFieldOfViewRH(45,stageW / stageH,0.01,100);
// 创建一个定义相机位置的矩阵
viewMatrix.identity();
// 为了看到Mesh,把相机往后移;
viewMatrix.appendTranslation(0,0,-4);
// 准备就绪 开始渲染
addEventListener(Event.ENTER_FRAME,onRendering);
}
protected function onRendering(event:Event):void
{
context3D.clear(0,0,0);
context3D.setProgram(shaderProgram);
// 创建变换矩阵
modelMatrix.identity();
modelMatrix.appendRotation(t*0.6,Vector3D.X_AXIS);
modelMatrix.appendRotation(t*0.7,Vector3D.Y_AXIS);
modelMatrix.appendRotation(t*0.8,Vector3D.Z_AXIS);
modelMatrix.appendTranslation(0,0,0);
t+=2.0;
//重置矩阵
modelViewProjection.identity();
modelViewProjection.append(modelMatrix);
modelViewProjection.append(viewMatrix);
modelViewProjection.append(projectionMatrix3D);
//把矩阵传给着色器
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,modelViewProjection,true);
// 着色器处理顶点数据
context3D.setVertexBufferAt(0,vertexBuffer,0,Context3DVertexBufferFormat.FLOAT_3);
// 着色器处理纹理
context3D.setVertexBufferAt(1,vertexBuffer,3,Context3DVertexBufferFormat.FLOAT_3);
context3D.setTextureAt(0,myTexture);
context3D.drawTriangles(indexBuffer,0,meshIndexData.length / 3);
context3D.present();
}
}
}