创建VertexBuffer3D
VertexBuffer3D 类表示上载到渲染上下文的一组顶点数据。
使用 VertexBuffer3D 对象定义与一组顶点中每个点相关联的数据。您可以从 Vector 数组或 ByteArray 上载顶点数据。(上载完成后,将不再引用原始数组中的数据;更改或放弃源数组不会更改顶点数据。) 与每个顶点相关联的数据采用应用程序定义的格式,并用作顶点着色器程序的输入。使用 Context3D setVertexBufferAt() 函数标识哪些值属于哪个顶点程序输入。一个顶点程序最多可以使用 8 个输入(也称为顶点属性寄存器)。每个输入可能需要 1 到 4 个 32 位值。例如,一个顶点的 [x,y,z] 位置坐标可以作为包含 3 个 32 位值的矢量传递到顶点程序。Context3DVertexBufferFormat 类定义表示着色器输出支持的格式的常量。您最多可以为每个点提供 64 个 32 位值(256 字节)数据(但在这种情况下,单个顶点着色器无法使用所有数据)。 setVertexBufferAt() 函数还标识渲染任何后续 drawTriangles() 调用要使用哪个顶点缓冲区。要渲染来自其他顶点缓冲区的数据,请使用适当的参数再次调用 setVertexBufferAt()。(您可以在多个顶点缓冲区中存储同一个点的数据,例如将位置数据存入一个缓冲区并将坐标数据存入另一个缓冲区,但如果一个点的所有数据来自单个缓冲区,渲染效率通常会更高。) 传递到 Context3D drawTriangles() 方法的 Index3DBuffer 对象会将顶点数据组织为三角形。索引缓冲区中的每个值是顶点缓冲区中某个顶点的索引。按顺序排列的由 3 个索引组成的一组索引定义一个三角形。 您无法直接创建 VertexBuffer3D 对象。请改用 Context3D createVertexBuffer() 方法。 要释放与顶点缓冲区相关联的渲染上下文资源,请调用对象的 dispose() 方法。 例子:
下面的示例说明如何创建和加载顶点数据缓冲区。此示例中的缓冲区为每个顶点包含两种数据类型:位置,表示为 x、y、z 坐标;颜色,表示为 rgb 组件。创建顶点缓冲区后,该示例调用 setVertexBufferAt() 方法以指定前三个数据点作为 va0 中的 3 个浮点值传递到顶点程序,后三个数据点作为 va1 中的 3 个浮点值传递到顶点程序。顶点程序最多可以有 8 个输入,也称为顶点属性寄存器,按下面的方式定义。
const dataPerVertex:int = 6;
var vertexData:Vector.<Number> = Vector.<Number>
( [ // x, y, z r, g, b format
0, 0, 0, 1, 1, 1,
-1, 1, 0, 0, 0,.5,
1, 1, 0, 0, 0, 1,
1,-1, 0, .5, 0, 0,
-1,-1, 0, 1, 0, 0 ]);
var vertexes:VertexBuffer3D = renderContext.createVertexBuffer( vertexData.length/dataPerVertex, dataPerVertex );
vertexes.uploadFromVector( vertexData, 0, vertexData.length/dataPerVertex ); //Identify vertex data inputs for vertex programrender
Context.setVertexBufferAt( 0, vertexes, 0, Context3DVertexBufferFormat.FLOAT_3 ); //Defines shader input va0 as the position datarender
Context.setVertexBufferAt( 1, vertexes, 3, Context3DVertexBufferFormat.FLOAT_3 ); //Defines shader input va1 as the color data
Context3D
Context3D 类提供了用于呈现几何定义图形的上下文。渲染上下文包括一个绘图表面及其关联的资源和状态。在可能的情况下,渲染上下文使用硬件图形处理单元 (GPU)。否则,渲染上下文使用软件。(如果在某个平台上不支持通过 Context3D 呈现,则 Stage 对象的 stage3Ds 属性包含一个空列表。) Context3D 渲染上下文是一个可编程的管道,与 OpenGL ES 2 类似,不过它是抽象的,从而可与某一范围内的硬件和 GPU 接口兼容。尽管专为 3D 图形设计,但是呈现管道并不强制呈现必须是三维的。因此,您可以通过提供适当的顶点和像素片段程序来创建 2D 渲染器。在 3D 和 2D 这两种情况下,支持的几何基元只有三角形。 通过调用 Stage3D 对象的 requestContext3D() 方法可以获取 Context3D 类的实例。每个页面只能存在有限数量的 Context3D 对象;Stage.stage3Ds 列表中的每个 Stage3D 只能有一个。当创建上下文时,Stage3D 对象会调度一个 context3DCreate 事件。渲染上下文可能会随时被损坏并重新创建,例如,当使用 GPU 的另一个应用程序获得焦点时。您的代码将会接收到多个context3DCreate 事件。使用相关联 Stage3D 实例的 x 和 y 属性指定舞台上渲染区域的位置。
若要呈现并显示某个场景(在获取 Context3D 对象后),下面是典型的步骤: - 通过调用 configureBackBuffer() 来配置主显示缓冲区属性。
- 创建并初始化您的呈现资源,包括:
- 定义场景几何的顶点和索引缓冲区
- 用于呈现场景的顶点和像素程序(着色器)
- 纹理
- 呈现帧:
- 为场景中的一个对象或一组对象设置适当的呈现状态。
- 调用 drawTriangles() 方法可以呈现一组三角形。
- 更改下一组对象的呈现状态。
- 调用 drawTriangles() 可以绘制定义对象的三角形。
- 重复直至场景全部呈现。
- 调用 present() 方法可以在舞台上显示呈现的场景。
资源 允许的数量 总内存
Vertex buffers 4096 256 MB
Index buffers 4096 128 MB
Programs 4096 16 MB
Textures 4096 128 MB¹
Cube textures 4096 256 MB
AGAL 限制:每个程序 200 个 opcode。 绘制调用限制:每个 present() 调用 32,768 个 drawTriangles() 调用。 ¹350 MB 是纹理的绝对限制,包括 mipmap 所需的纹理内存。但是,许多设备不支持这么多的纹理内存。为了最大限度地保证兼容性,请将使用的纹理内存限制为 128 MB 或更少。 您无法使用 Context3D 构造函数创建 Context3D 对象。它是作为 Stage3D 实例的属性构建并提供的。Context3D 类仅可以用于桌面平台上,在 Flash Player 和在 AIR 中运行时都适用。
例子(附件)
package
{
import com.adobe.utils.AGALMiniAssembler;
import com.adobe.utils.PerspectiveMatrix3D;
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.Context3DRenderMode;
import flash.display3D.Context3DTriangleFace;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
public class Context3DExample extends Sprite
{
public const viewWidth:Number = 320;
public const viewHeight:Number = 200;
public const zNear:Number = 1;
public const zFar:Number = 500;
public const fov:Number = 45;
private var stage3D:Stage3D;
private var renderContext:Context3D;
/*IndexBuffer3D 用于表示顶点索引列表,由图形子系统保留的图形元素构成。
由 IndexBuffer3D 对象管理的索引可用于从顶点流中选择顶点。索引为 16 位无符号整数。
所允许的最大索引值为 65535 (0xffff)。图形子系统不会保留对提供给此对象的顶点的引用。
修改或丢弃上载到此对象中的数据不会影响已存储的值。*/
private var indexList:IndexBuffer3D;
private var vertexes:VertexBuffer3D;
private var projectionerspectiveMatrix3D = new PerspectiveMatrix3D();
private var model:Matrix3D = new Matrix3D();
private var view:Matrix3D = new Matrix3D();
private var finalTransform:Matrix3D = new Matrix3D();
//用于旋转立方体
private const pivot:Vector3D = new Vector3D();
private const VERTEX_SHADER:String =
"m44 op, va0, vc0 \n" + // 4x4 矩阵变换 //3d转2d坐标
"mov v0, va1"; //移动颜色信息到v0
private const FRAGMENT_SHADER:String =
"mov oc, v0"; //设置输出颜色值从三个三角形顶点插值
private var vertexAssembly:AGALMiniAssembler = new AGALMiniAssembler();
private var fragmentAssembly:AGALMiniAssembler = new AGALMiniAssembler();
private var programPairrogram3D;
public function Context3DExample()
{
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
//this.stage.nativeWindow.activate(); //AIR only
stage3D = this.stage.stage3Ds[0];
stage3D.x = 10;
stage3D.y = 10;
//添加注册事件
stage3D.addEventListener( Event.CONTEXT3D_CREATE, contextCreated );
stage3D.addEventListener( ErrorEvent.ERROR, contextCreationError );
stage3D.requestContext3D( Context3DRenderMode.AUTO );
//编译着色器
vertexAssembly.assemble( Context3DProgramType.VERTEX, VERTEX_SHADER, false );
fragmentAssembly.assemble( Context3DProgramType.FRAGMENT, FRAGMENT_SHADER, false );
}
//注,context3DCreate事件可以发生在任何时间,例如,当由另一个进程的硬件资源
private function contextCreated( event:Event ):void
{
renderContext = Stage3D( event.target ).context3D;
trace( "3D driver: " + renderContext.driverInfo );
setupscene();
}
private function setupScene():void
{
renderContext.enableErrorChecking = true; //可以减缓渲染 - 开发/测试时开启
renderContext.configureBackBuffer( viewWidth, viewHeight, 2, false );
//显示模式,可以多试试选项
renderContext.setCulling( Context3DTriangleFace.BACK );
//索引列表 三角形-正方体
var triangles:Vector.<uint> = Vector.<uint>( [
2,1,0, //前面
3,2,0,
4,7,5, //底面
7,6,5,
8,11,9, //后面
9,11,10,
12,15,13, //上面
13,15,14,
16,19,17, //左面
17,19,18,
20,23,21, //右面
21,23,22
] );
indexList = renderContext.createIndexBuffer( triangles.length );
indexList.uploadFromVector( triangles, 0, triangles.length );
//Create vertexes - cube faces do not share vertexes
const dataPerVertex:int = 6;
var vertexData:Vector.<Number> = Vector.<Number>(
[
// x,y,z r,g,b format
//补充一句:4行代表4个点,你可以尝试改变其中的数值,来进一步发现与理解
0,0,0, 1,0,0, //front face
0,1,0, 1,0,0,
1,1,0, 1,0,0,
1,0,0, 1,0,0,
0,0,0, 0,1,0, //bottom face
1,0,0, 0,1,0,
1,0,1, 0,1,0,
0,0,1, 0,1,0,
0,0,1, 1,0,0, //back face
1,0,1, 1,0,0,
1,1,1, 1,0,0,
0,1,1, 1,0,0,
0,1,1, 0,1,0, //top face
1,1,1, 0,1,0,
1,1,0, 0,1,0,
0,1,0, 0,1,0,
0,1,1, 0,0,1, //left face
0,1,0, 0,0,1,
0,0,0, 0,0,1,
0,0,1, 0,0,1,
1,1,0, 0,0,1, //right face
1,1,1, 0,0,1,
1,0,1, 0,0,1,
1,0,0, 0,0,1
]
);
vertexes = renderContext.createVertexBuffer( vertexData.length/dataPerVertex, dataPerVertex );
vertexes.uploadFromVector( vertexData, 0, vertexData.length/dataPerVertex );
//为顶点程序输出顶点数据
renderContext.setVertexBufferAt( 0, vertexes, 0, Context3DVertexBufferFormat.FLOAT_3 ); //va0 is position
renderContext.setVertexBufferAt( 1, vertexes, 3, Context3DVertexBufferFormat.FLOAT_3 ); //va1 is color
//上载并渲染
programPair = renderContext.createProgram();
programPair.upload( vertexAssembly.agalcode, fragmentAssembly.agalcode );
renderContext.setProgram( programPair );
//3d变换
projection.perspectiveFieldOfViewRH( fov, viewWidth/viewHeight, zNear, zFar );
view.appendTranslation( 0, 0, -2 ); //摄像机距离
model.appendTranslation( -.5, -.5, -.5 ); //正方体位置
this.stage.addEventListener( Event.ENTER_FRAME, render );
}
private function render( event:Event ):void
{
model.appendRotation( .5, Vector3D.Z_AXIS, pivot );
model.appendRotation( .5, Vector3D.Y_AXIS, pivot );
model.appendRotation( .5, Vector3D.X_AXIS, pivot );
//编译变换
finalTransform.identity();
finalTransform.append( model );
finalTransform.append( view );
finalTransform.append( projection );
//上传3D矩阵对应AGAL中的vc0
renderContext.setProgramConstantsFromMatrix( Context3DProgramType.VERTEX, 0, finalTransform, true );
//背景色
renderContext.clear( .3,.3,.3 );
//上传三角顶点索引,起点为0,画12个三角形
renderContext.drawTriangles( indexList, 0, 12 );
renderContext.present();
}
private function contextCreationError( error:ErrorEvent ):void
{
trace( error.errorID + ": " + error.text );
}
}
}
|