`

[Stage3D]GPU渲染的喷泉粒子

阅读更多

本文版权归 博客园 Clifford 所有,如有转载,请自觉于显式位置标明原创作者及出处,以示尊重!!

作者:Clifford

原文:http://www.cnblogs.com/flash3d/archive/2012/02/01/2332393.html

 

您需要把Flash Player升级到11版本才能正常播放示例程序。

运行效果点击进入原文观看。

如果播放动画的帧率较低,那么有可能是您的显卡不被Flash Player所支持,Flash Player会采用CPU来对画面进行渲染。

 

源码:http://files.cnblogs.com/flash3d/partic.rar

在详细介绍该粒子效果编写方法之前,先让我们简单了解下Stage3D开发基本流程与注意事项。

1. 获取Stage3D对象

Stage3D对象用于显示通过Stage3D技术渲染出来的图像,我们可以通过类似

stage.stage3Ds[0]

的方式获取Stage3D对象,Flash总共提供四个独立的Stage3D对象。

2. 获取Context3D对象

Context3D对象是我们使用Stage3D技术主要操作对象。该对象类似一个大工厂,我们可以向他申请空的顶点缓冲(VertexBuffer3D),顶点索引(IndexBuffer3D),着色器程序(Program3D)等,而后向全新的对象内装入数据再通过Context3D上传至GPU。

Context3D对象并不能通过new来创建,也不能立即申请到。要想获取Context3D对象则需通过

stage3d.requestContext3D()

的方式发起申请请求,而后监听Event.CONTEXT3D_CREATE事件发生才算申请成功。此时则可通过

stage3d.context3D

获取Context3D对象了。这里需要注意Event.CONTEXT3D_CREATE事件可能多次发生,假如其他程序中断了Flash Player的GPU使用权后Flash Player重新获得其使用权,则会再次发生Event.CONTEXT3D_CREATE事件。假如你在Event.CONTEXT3D_CREATE事件的回调中做了一些初始化工作,那么就要小心了,如果你不及时移除监听,就有重复初始化的隐患。

3. 创建Program3D对象并写入程序

通过

context.createProgram()

的方式,可以获得一个空的Program3D对象。Program3D对象负责储存着色器程序。有些朋友可能对着色器程序的概念和工作原理还不是很清楚,这里我简单介绍下。

着色器程序(AGAL写的程序)分为两部分:顶点着色器程序(Vertex Shader),段着色器程序(Fragment Shader)。他们均被上传至GPU运行。顶点着色器程序负责处理顶点缓冲数据并将处理好的数据写入到位置输出寄存器(op)并且将部分必须的中间数据储存到变量寄存器留给段着色器使用,段着色器则是根据从顶点着色器传来的变量,结合纹理数据,计算合成某个像素需要输出的值。

关于用AGAL着色器的语法,请参考http://bbs.9ria.com/viewthread.php?tid=79747

关于Stage3D的最简单“Hello World”程序:http://www.pixelbender.cn/?p=381

所以,从程序的角度看,貌似顶点着色器先被执行,而后再执行段着色器。但是请注意,实际上在GPU中,顶点着色器与段着色器的运行次数是不一样的,这也是为什么在Stage3D的“Hello World”程序中所绘制的是一个渐变图像而不是四个像素点了。

实际上GPU是首先计算完全部的顶点缓冲(可能有并行运算),而后对计算出来的顶点数据投影到2D屏幕上(计算出来的顶点原本是三维点,期间可能还进行了一些消隐等操作),接下来对这些顶点围成的三角形进行栅格化(变成位置确定的像素点,但尚未有颜色),最后才是对栅格化后的像素执行段着色器程序,而其所需的变量寄存器值则通过像素位置关系内插计算得到的渐变值。

如图展示了渲染管线的处理过程

 如下示例展示了一个三角形的绘制过程

我们可以通过Program3D对象的upload方法上传程序,该方法接收两个参数,第一个是顶点着色器程序(Vertex Shader),另外一个是段着色器程序(Fragment Shader)。但是请注意,upload的两个参数类型是字节数组(ByteArray)而非字符串(String),所以我们需要AGALMiniAssembler对象来帮助我们把字符串的着色器程序变成字节数组。通过AGALMiniAssembler对象的assemble方法可以达到上述功能。该方法第一个参数是程序类型,可能值是两个,一个是"vertex",表示第二个参数是顶点着色器程序,另外一个是"fragment",代表第二个参数是段着色器程序。

4. 创建顶点缓冲数据

顶点缓冲数据可以看成n行m列的二维数组。其中每行数据可以产生一个三维模型中某个三角形的顶点,该行的数据值决定着该顶点输出的坐标(具体如何决定则看顶点着色器程序,也有可能部分数据不起作用,而是间接对段着色器起作用)。而顶点缓冲数据的行数则决定顶点的个数。

我们可以通过

context.createVertexBuffer(行数, 列数)

来申请一个空的顶点缓冲包装对象。之后我们需要一个“行数 * 列数”长度的Vector.<Number>类型数组来写入我们的顶点数据。

可以通过

vertex.uploadFromVector(数组, 行偏移量, 行数)

上传数据。通过

context.setVertexBufferAt(寄存器序号, vertex, 列偏移量, 数据长度)

设置一行中的顶点数据如何分配给寄存器。其中寄存器序号就是在agal中va后所带的数字,如寄存器序号是1,则可通过va1访问设置进去的数据。列偏移量表示要设置到寄存器中的数据区间其第一个浮点数是处在该行的第几列(0开始),数据长度则表示要设置几个浮点数到寄存器中,其值是个字符串,类似"float2","float3"等,最大是"float4",因为一个寄存器最多只能储存四个浮点数。
以下例子演示如何将顶点数据设置到寄存器中并在AGAL中访问。

这里我们建立一个最简单的三角形作为模型,一个三角形拥有三个顶点,故顶点缓冲有三行数据,每行数据中,我们需要三角形的坐标,以及顶点处的颜色(数据的数量,意义,作用看具体程序而定),于是我们决定用两个浮点数表示坐标位置(X,Y),用三个浮点数表示颜色值(R,G,B),所以顶点缓冲数据应该是3行5列的,其数据长度是15。通过如下代码

vertex.uploadFromVector(new<Number>[0, 1, 0, 0.5, 1, -1, -1, 0.5, 1, 0, 1, -1, 1, 0, 0.5], 0, 3)

可以将如下数据设置到顶点缓冲中去了。

0 1 0 0.5 1
-1 -1 0.5 1 0
1 -1 1 0 0.5

通过如下两行代码

context.setVertexBufferAt(0, vertex, 0, "float2"); context.setVertexBufferAt(1, vertex, 2, "float3");

可以将蓝色部分的数据设置到va0中,把红色部分数据设置到va1中。

假设顶点着色器程序正在处理第三行,此时访问va0.x为1,va0.y为-1,va1.x为1,va1.y为0,va1.z为0.5。

着色器寄存器可容纳四个浮点数,当设置进去的数据长度不够时(比如设置的是"float2"),则系统默认帮你填上默认值,寄存器前三个浮点数的默认值均为0,第四个浮点数默认值为1。所以此时va0.z为0,va0.w为1。请注意,这个默认值是执行setVertexBufferAt的时候就设置进去的,而非到达GPU后才产生。GPU中的临时寄存器在未被赋值之前是访问不到其值的(直接挂了)。所以对于未被设置过的vt0

mov vt0.xy, va0.xy mov vt1.x, vt0.z //挂了

mov vt0, va0 mov vt1.x, vt0.z //没挂

以上程序产生不同的结果。

顶点着色器程序从头到尾运行一次只处理一行数据,而且只能访问本行数据,各行数据无法相互影响。

5. 创建纹理数据

纹理数据在段着色器运行时被采样,比较常见用处是UV映射,将纹理作为模型贴图,更加高级的用法则比如通过在同个或者多个纹理的多个点上采集像素并通过某种算法合成而产生特殊效果。

可以通过

context.createTexture(宽, 高, "rgba", false);

来获得空的纹理包装对象。

之后向纹理包装对象上传位图

texture.uploadFromBitmapData(位图)

最后通过

context.setTextureAt(寄存器序号, texture)

来设置到指定的纹理寄存器上。

在AGAL中,可以通过类似

tex ft1,v0,fs0<2d,linear,nomip>

的方法把像素采集到寄存器中,fs0是序号为0的纹理寄存器,可以访问到通过setTextureAt设置到0的纹理。<2d,linear,nomip>是采样属性,其依次可能值为

尺寸:2d,3d,cube
投影:nomip,mipnone,mipenearest
滤镜:nearest,linear
拷贝:repeat,wrap,clamp
v0代表要采样的坐标,ft1则是储存采样结果。

6. 设置着色器程序常数

着色器程序的特性与数学函数非常类似,具有纯数据计算的特性。故常数对于着色器的意义相当于常数对于数学函数的意义一样。

比如函数“y = ax”展现出的是y随x线性变化的特征,但是常数a却控制着变化速度的快慢。

通过类似

context.setProgramConstantsFromVector("vertex", 0, new<Number>[0, -0.5, 0.2, 0])

的代码可将常数设置到常数寄存器中。函数第一个参数代表设置的是顶点着色器的常数还是段着色器的常数,"fragment"代表段着色器,设置进入的常量可通过类似fc0的形式访问,"vertex"代表顶点着色器,设置进入的常量可通过类似vc0的形式访问,vc后的数字则是由这个函数的第二个参数确定,表示要设置到哪个标号的寄存器内。第三个参数是常量数据,他是一个不超过4个长度的Vector.<Number>类型数组。其四个值分别对应着vt0.x,vt0.y,vt0.z,vt0.w。

对于as来说,改变常量是非常省力的(一行代码而已),而改变顶点缓冲数据则非常费劲(需要遍历整个数组)。所以如果希望通过Stage3D技术产生流畅的动画,则必须通过不断改变常量来完成,而不能改变顶点缓冲数据的值,否则GPU加速也就没有意义了,这也是最考验着色器设计能力的地方。

7. 创建顶点索引

顶点索引数据是一个n行3列的数据。其一行可绘制一个三角形,一行内的三个数据分别是三角形三个顶点的索引,这里索引所引用的就是顶点缓冲数据里面的某一行(代表某个顶点),索引值便是顶点缓冲数据的行号。

可通过

context.createIndexBuffer(索引数)

来创建空的顶点索引包装对象。这里注意其参数是索引数(即n*3),而非行数。

通过

index.uploadFromVector(Vector.<uint>类型数组, 起始索引偏移量, 索引数)

上传索引数据。在绘制3D画面时,可以将index对象传入context.drawTriangles绘制出所有指定三角形。

 

以上简单介绍了Stage3D技术开发的基本流程,当然Stage3D还有其他功能需要大家深入去研究。

有了上面的基础,下面讲一下Stage3D喷泉粒子效果的制作要点,可能讲的不对或者有更好的方案,还请各路大大多多指教。

1. 粒子模型

Stage3D并非BitmapData,无法直接将粒子以像素的形式设置到画面上,故考虑以一个小三角形作为粒子模型。所以总共的顶点数应该是粒子数的三倍。

2. 动画的实现

考虑到要充分发挥Stage3D的优势,所以动画的实现,也就是粒子位置随时间的连续性改变也不应该让as去实现。否则粒子的位置坐标就必须由as来计算并设置,那么就必须遍历粒子数组,开销大大滴。

所以我的方案是给着色器传一个时间常量,粒子的坐标位置随时间沿着某个曲线运动。

由于是喷泉效果,所以采用的是抛物线轨迹(捂脸~~太没科技含量了)

抛物线原型:y = - x^2

引入一个常量使其变形经过原点的上抛曲线:y - c^2 = -(x - c)^2

由于还考虑到喷泉中每个粒子的喷发角度不一样故还引入常量d:y = c^2 - (d * x - c)^2

d表示x轴缩放比例的倒数,若d为负则抛物线方向向左。

有了曲线方程,则下面需要x关于时间的方程了,根据物理规律,由于喷洒的高度相同,故粒子从升起到落地的时间相同,那么对于x来说就是从0位置移动到2c/d的时间相同。那么当给定0到1范围的时间变量,无论2c/d是多少,经过相同的时间完成x与2c/d的比例也是相同的,于是有了这个方程:x = 2 * c / d * t

由于我们需要不同的粒子处在抛物线运动的不同时刻,这样才会看起来有前后次序的感觉,于是我们还需要给这个t再加上一个时间常量得到x = 2 * c / d * (t + o)

再者需考虑t + o需要在0至1范围内,并且超过1后回归为0,这样才会有粒子的生命结束与重生。所以这里动用到agal里frc这个运算符,其功能是对源操作数取小数,最后得到的公式为:

x = 2 * c / d * frc(t + o)

将该时间方程代入上述曲线方程得到y与时间的关系方程:y = c^2 - (2 * c * frc(t + o) - c)^2

此方程中常量c确定抛物线的高度,由于全部粒子最大高度一致,所以c可设置为全局常量;常量d确定粒子的运动方向与跨度,由于各粒子不相同,所以作为曲线描述信息保存到顶点缓冲中;o为初始时间偏移量,故各粒子也不同,均保存到顶点缓冲中。

3. 粒子模型的形状保持

粒子的运动概念上是以三角形为单位,所以三角形的三个顶点相对位置应该保持不变才能防止粒子形状发生改变,也就是说,每次运动粒子的三个顶点必须加上相同的该变量。

所以我设定的顶点缓冲数据结构是这样的

va0 va1
p1.x p1.y o d
p2.x p2.y
p3.x p3.y

p1 p2 p3分别是三角形的三个顶点坐标,接下来的每三行,其值都与该三行的va0值对应相同,这三个点的数据确定了粒子的形状。但是va1作为描述运动规律的数据,则是三行都相同,但是与其他的三行不相同。这体现了这三行的数据是共同描述一个粒子,而粒子的每个顶点其运动规律都相同,才不至于形状改变。

结合上文推导的运动方程,我们得到如下顶点着色器代码

复制代码
mov vt2, vc1 mov vt0, va0 add vt1.x, vc0.x, va1.x //t + o frc vt1.x, vt1.x //frc(t + o) mov v0, vt1.x //将运动百分比传到段着色器 mul vt1.x, vt1.x, vt2.y //c * frc(t + o) mul vt1.x, vt1.x, vt2.w //2 * c * frc(t + o) div vt0.x, vt1.x, va1.y //x = 2 * c / d * frc(t + o) sub vt1.x, vt1.x, vt2.y //2 * c * frc(t + o) - c pow vt1.x, vt1.x, vt2.w //(2 * c * frc(t + o) - c)^2 pow vt1.y, vt2.y, vt2.w //c^2 sub vt0.y, vt1.y, vt1.x //y = c^2 - (2 * c * frc(t + o) - c)^2 add vt0.xy, vt0.xy, va0.xy //粒子坐标累加到顶点坐标 add vt0.xy, vt0.xy, vc0.yz //原点做一定偏移 mov op, vt0 //输出

复制代码

而段着色器上,只是做了一点颜色渐变。主要是根据运动百分比来线性增加颜色的亮度,符合水喷出去就白了的规律(囧~)

mov ft0, fc //获取设定的颜色常量 //给三原色加上运动百分比 add ft0.x, ft0.x, v0.x add ft0.y, ft0.y, v0.x add ft0.z, ft0.z, v0.x mov oc, ft0 //输出

程序源码在最上面。。。

分享到:
评论

相关推荐

    Adobe Flash 11 Stage3D游戏编程初学者指南 代码

    Adobe Flash 11引入了一个强大的新特性,Stage3D,为游戏开发者提供了高效、低级别的图形渲染能力,极大地提升了在Web上开发复杂2D和3D游戏的性能。本指南面向初学者,旨在帮助读者掌握如何利用Stage3D进行游戏编程...

    源码Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner's Guide

    Stage3D借鉴了现代GPU加速的图形处理概念,使得开发者能够充分利用硬件加速,创建出流畅、细腻的3D视觉体验。 压缩包内的文件主要包含不同章节的代码示例,例如: 1. Stage3D_Code_Chapter07:这一部分可能涵盖了第...

    stage3d参考

    Stage3D是Flash Player 11及更高版本中引入的新特性,它为ActionScript 3(AS3)提供了一个直接访问GPU硬件加速的接口,极大地提升了2D和3D图形的渲染性能。相比传统的Canvas和Sprite,Stage3D能实现接近原生的速度...

    基于as3 stage3d 的基础2d渲染 练手的时候写的,跟opengl原理很像

    《基于AS3 Stage3D的基础2D渲染:深入理解GPU编程》 在计算机图形学的世界里,OpenGL和Stage3D都是实现硬件加速图形渲染的重要工具。这篇内容将深入探讨基于ActionScript 3(AS3)的Stage3D技术,这是一种在Flash...

    Starling基于Stage3D开发GPU加速的2D游戏

    Stage3D API是Adobe Flash Platform Runtimes最新版本提供的低级别的GPU加速API,旨在提供更高效、更灵活的渲染方式。它支持在多种设备上运行,包括浏览器、桌面、移动设备和电视等。通过Stage3D API,开发者可以...

    Stage3D教程

    Stage3D是Adobe Flash Player 11和AIR 3引入的一项重大革新,它允许开发者利用硬件GPU(图形处理器单元)加速来渲染复杂的3D场景,从而极大提升了应用程序的性能和视觉效果。本文将深入探讨Stage3D的启用方法、环境...

    Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner's Guide

    Stage3D是ActionScript 3.0的一个重要组件,它提供了一个硬件加速的渲染层,允许开发者直接访问GPU的计算能力,从而提高了图形处理的速度和效率。通过Stage3D,开发者可以创建出与原生游戏平台相媲美的3D视觉效果,...

    AS3 stage3d 平滑滚屏案例

    1. **批处理渲染**:为了提高效率,Stage3D允许将多个几何形状或纹理打包成一个批次进行一次性渲染,减少了CPU和GPU之间的数据交换次数。 2. **视口裁剪**:只渲染当前可视区域的内容,避免不必要的计算,节省GPU...

    stage3d_atf_demo

    1. **Stage3D API**:Stage3D提供了一系列的低级接口,如Context3D,允许开发者直接与GPU进行交互,实现高效的图形渲染。它包括了绘制几何形状、设置着色器、管理纹理和顶点缓冲等功能。 2. **ATF纹理加载**:在...

    Stage3D新手入门教程

    Stage3D非常适合于开发高性能的2D和3D游戏、交互式媒体展示、虚拟现实应用以及任何需要高渲染性能的可视化项目。利用Stage3D技术,开发者可以实现高质量的视觉效果,同时还能保持良好的性能,尤其是在桌面、移动设备...

    深入Stage3D_7yue

    - **硬件加速模式(GPU mode)**:Stage3D优化了三角形的渲染,专为渲染三角形进行了优化,能够提供更高的渲染性能和更高级的2D/3D体验。它不仅吸引传统游戏开发社区,而且因为它依赖GPU硬件加速,其渲染性能通常远...

    Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner 书源码

    Stage3D是Flash Player 11及更高版本中的一项底层API,它允许开发者直接访问GPU资源,实现高效的硬件加速3D图形渲染。这一改进使得Flash能够支持复杂的3D游戏、应用程序和互动体验,与Unity和WebGL等其他3D技术相...

    stage3D写的切屏效果

    舞台3D(Stage3D)是Adobe开发的一种底层图形渲染技术,主要应用于Flash Player和Air平台上,为开发者提供了高效、低级别的硬件加速图形处理能力。它使得在浏览器或桌面应用中实现复杂的3D图形和游戏成为可能。在本...

    Adobe Flash 11 Stage3D Molehill Game Programming Beginners Guide

    Stage3D (代号Molehill) 是Adobe Flash Player 11和AIR 3引入的一项新技术,它允许开发者通过低级的API访问GPU硬件加速,从而实现高性能的2D和3D图形渲染。这一技术大大提升了Flash平台上的图形处理能力,使得开发者...

    Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner's Guide.pdf

    - **新特性**:包括改进的文本渲染、增强的视频编码支持、更强大的音频处理能力以及最重要的Stage3D API。 - **工具和环境**:Adobe Flash Professional CC 或更高版本是常用的开发工具,提供了一整套用于设计和...

Global site tag (gtag.js) - Google Analytics