stage3D 搭建2d图形引擎 (五)不同纹理的显示对象
2012-11-30 21:32
302 查看
在进入主题之前,我们先来回顾一下之前所走过的思路:
1.首先是为了绘制多个四边形,并且为了节省效率,我们将多个四边形的数据集中到一起,一次上传到缓冲,并且只执行一次绘制,一次呈现。
2.但是当需要纹理贴图时,我们发现颜色填充的四边形和贴图的四边形无法公用shader program,所以我们不得不将这两者分开,执行多次绘制,最后一次呈现。
在这篇文章中我们会延续以上的思路,继续探索下去,来处理多纹理的情况。
如果你仔细研究了前一篇文章中的ImageRender类,你会发现有一个很严重的问题,那就是一个ImageRender对象只有一个纹理对象,因而它只能批量渲染那些拥有相同纹理的Image对象。但是实际的问题中,你的应用越丰富,你所用到的纹理肯定也会越多。因此如果一个ImageRender对象只针对一个纹理,那么我们可能要创建很多的ImageRender对象才能满足实际的需求。
看起来很不应该,不是吗?还会有更好的方案吗?
这个问题并不是很好回答,按照我们目前的这种情况,答案是肯定的,我们没有别的选择,只能针对具有相同纹理的显示对象来进行批处理。但脱离我们之前的一些设定(主要是我们规定一个QuadVertex对象最多有8个数据),方法还是有的,也就是说可以同时批处理拥有不同纹理的显示对象,不过这不是本篇的主题。可以看下面的批注来了解大概内容。
当然单个纹理的批处理也不至于那么糟糕,虽然我们可能需要针对每一个纹理对象来制定一个ImageRender(它的本质是一个shader program,和有限的纹理样本寄存器),但是我们完全可以将具有关联性的纹理素材做在一张图片上,然后对不同的显示对象设置纹理坐标来获取正确的纹理内容。
说到这里也有必要跟Starling做一下对比,在Starling中,通过QuadBatch对象来渲染四边形组,这里所说的四边形当然也包括Image对象。因此,我们这里的QuadRender和ImageRender类似于Starling中的QuadBatch。区别只是在于QuadBatch这种设计更加的抽象,但并不是所有的四边形对象都是仅由一个QuadBatch来做渲染管理的,一个QuadBatch对象只能包含相似的四边形对象,这里相似的定义可以从RenderSuppor::batchQuad()这一方法中看出来:
我们看到,结束一个QuadBatch的条件是满足QuadBatch::isStateChange()执行结果为true,这个方法定义了四边形的“相似”。而我们看到,其中便有texture这一项。本篇文章只会涉及texture和smoothing两项,其他的以后涉及到再说。
话说回来,QuadBatch所做的抽象是有代价的,因为他要同时处理颜色填充四边形和贴图四边形,再加上其他的一些特性,他所处理的情况要复杂的多(当然也不是特别多,只是有这种倾向,呵呵),我们从学习的角度来看,完全可以将这些复杂性进行分离,为此我们建立一个抽象基类RenderBase:
这个类将会作为QuadRender从而也是ImageRender的基类。这个类的重点在于render()这一方法上。其他的函数包括构造函数将在后面解释。
接下来修改ImageRender类。我们前面说每个ImageRender都针对一个Texture对象,因此我们在ImageRender的构造函数中加入一个Texture类型的参数:
另外每一个Render对象(QuadRender or ImageRender)都对应着特有的shader program,而这些program在反复的绘制过程中是可以重复利用的,因此我们不应该每次都重复创建,应该将他们缓存起来,这样每个Render对象都应该有一个注册shader program的方法:
具体地可以参考Starling中的设计。这一方法的执行应该在Context3D建立之后(因为只有有了Context3D对象之后我们才能请求Program3D实例),因此我们可以在Render对象的构造函数中侦听相关的事件。于是就有了RenderBase中的构造函数的内容和侦听函数。
在下面放出的源码中,我们还调整了其他的一些内容,比如仿照Starling的设计,我们用一个叫做Sparrow,:),的类作为整个2d引擎的入口。同时我们用一个Context2D类来对Context3D进行了封装。
截图留念
注:
上面所说的,在一次批处理中处理多个纹理对象的问题,可以通过扩展顶点数据来实现,比如我们在原来的u,v之后再加上u1,v1这一坐标用来对应第二个纹理寄存器fs1中的纹理。
其实有了RenderBase这样的一种抽象,我们就可以走的更远一些,比如我们可以扩展五边形的批处理,即使是四边形,我们也可以用另外的一种批处理方式来渲染,比如增加每个顶点的数据个数来处理多贴图的批处理。
源码
1.首先是为了绘制多个四边形,并且为了节省效率,我们将多个四边形的数据集中到一起,一次上传到缓冲,并且只执行一次绘制,一次呈现。
2.但是当需要纹理贴图时,我们发现颜色填充的四边形和贴图的四边形无法公用shader program,所以我们不得不将这两者分开,执行多次绘制,最后一次呈现。
在这篇文章中我们会延续以上的思路,继续探索下去,来处理多纹理的情况。
如果你仔细研究了前一篇文章中的ImageRender类,你会发现有一个很严重的问题,那就是一个ImageRender对象只有一个纹理对象,因而它只能批量渲染那些拥有相同纹理的Image对象。但是实际的问题中,你的应用越丰富,你所用到的纹理肯定也会越多。因此如果一个ImageRender对象只针对一个纹理,那么我们可能要创建很多的ImageRender对象才能满足实际的需求。
看起来很不应该,不是吗?还会有更好的方案吗?
这个问题并不是很好回答,按照我们目前的这种情况,答案是肯定的,我们没有别的选择,只能针对具有相同纹理的显示对象来进行批处理。但脱离我们之前的一些设定(主要是我们规定一个QuadVertex对象最多有8个数据),方法还是有的,也就是说可以同时批处理拥有不同纹理的显示对象,不过这不是本篇的主题。可以看下面的批注来了解大概内容。
当然单个纹理的批处理也不至于那么糟糕,虽然我们可能需要针对每一个纹理对象来制定一个ImageRender(它的本质是一个shader program,和有限的纹理样本寄存器),但是我们完全可以将具有关联性的纹理素材做在一张图片上,然后对不同的显示对象设置纹理坐标来获取正确的纹理内容。
说到这里也有必要跟Starling做一下对比,在Starling中,通过QuadBatch对象来渲染四边形组,这里所说的四边形当然也包括Image对象。因此,我们这里的QuadRender和ImageRender类似于Starling中的QuadBatch。区别只是在于QuadBatch这种设计更加的抽象,但并不是所有的四边形对象都是仅由一个QuadBatch来做渲染管理的,一个QuadBatch对象只能包含相似的四边形对象,这里相似的定义可以从RenderSuppor::batchQuad()这一方法中看出来:
public function batchQuad(quad:Quad, parentAlpha:Number, texture:Texture=null, smoothing:String=null):void { if(mQuadBatches[mCurrentQuadBatchID].isStateChange(quad.tinted, parentAlpha, texture, smoothing, mBlendMode)) { finishQuadBatch(); } mQuadBatches[mCurrentQuadBatchID].addQuad(quad, parentAlpha, texture, smoothing, mModelViewMatrix, mBlendMode); }
我们看到,结束一个QuadBatch的条件是满足QuadBatch::isStateChange()执行结果为true,这个方法定义了四边形的“相似”。而我们看到,其中便有texture这一项。本篇文章只会涉及texture和smoothing两项,其他的以后涉及到再说。
话说回来,QuadBatch所做的抽象是有代价的,因为他要同时处理颜色填充四边形和贴图四边形,再加上其他的一些特性,他所处理的情况要复杂的多(当然也不是特别多,只是有这种倾向,呵呵),我们从学习的角度来看,完全可以将这些复杂性进行分离,为此我们建立一个抽象基类RenderBase:
package psw2d.render { import flash.events.Event; import psw2d.Sparrow; import psw2d.core.Context2D; public class RenderBase { public function RenderBase() { Sparrow.instance.addEventListener("contextCreated",onContextCreated); } protected function onContextCreated(e:Event):void { } public function render():void { } } }
这个类将会作为QuadRender从而也是ImageRender的基类。这个类的重点在于render()这一方法上。其他的函数包括构造函数将在后面解释。
接下来修改ImageRender类。我们前面说每个ImageRender都针对一个Texture对象,因此我们在ImageRender的构造函数中加入一个Texture类型的参数:
public function ImageRender(texture:Texture) { super(); _texture = texture; _texture && _texture.uploadData(); }
另外每一个Render对象(QuadRender or ImageRender)都对应着特有的shader program,而这些program在反复的绘制过程中是可以重复利用的,因此我们不应该每次都重复创建,应该将他们缓存起来,这样每个Render对象都应该有一个注册shader program的方法:
private static function registerPrograms():void { }
具体地可以参考Starling中的设计。这一方法的执行应该在Context3D建立之后(因为只有有了Context3D对象之后我们才能请求Program3D实例),因此我们可以在Render对象的构造函数中侦听相关的事件。于是就有了RenderBase中的构造函数的内容和侦听函数。
在下面放出的源码中,我们还调整了其他的一些内容,比如仿照Starling的设计,我们用一个叫做Sparrow,:),的类作为整个2d引擎的入口。同时我们用一个Context2D类来对Context3D进行了封装。
截图留念
注:
上面所说的,在一次批处理中处理多个纹理对象的问题,可以通过扩展顶点数据来实现,比如我们在原来的u,v之后再加上u1,v1这一坐标用来对应第二个纹理寄存器fs1中的纹理。
其实有了RenderBase这样的一种抽象,我们就可以走的更远一些,比如我们可以扩展五边形的批处理,即使是四边形,我们也可以用另外的一种批处理方式来渲染,比如增加每个顶点的数据个数来处理多贴图的批处理。
源码
相关文章推荐
- stage3D 搭建2d图形引擎 (七) 简单纹理动画
- stage3D 搭建2d图形引擎 (八) 动态纹理
- stage3D 搭建2d图形引擎 (六) 显示列表
- stage3D 搭建2d图形引擎 (四)静态文理贴图
- stage3D 搭建2d图形引擎 (三)透明度(alpha混合)
- 幻世(OurDream)2D图形引擎使用教程6——使用纹理
- WEBGL 2D游戏引擎研发系列 第五章 <操作显示对象>
- 2D游戏引擎Allegro 系列教程(三) 加载并显示图片!
- 幻世(OurDream)2D图形引擎使用教程17——易语言编写幻世程序系列(1)
- cocos2d-x学习笔记(1)--coco2d-x引擎下载及环境搭建
- 【2D游戏引擎】那些年对游戏对象的思考
- JAVAFX:在图形场景中显示 UI 对象
- 2D图形加速引擎(GE2D)
- 通过请求不同的url返回Json对象并在前端显示的解决方法
- 猎头职位 c++ 显示引擎图形技术研究员
- sqlserver2008r2报"由于某些空间对的SRID与记录集中第一个对象的SRID不同 因此未显示这些空间对象"
- 定义对象或数组直接量时不同引擎对多余逗号的处理
- 幻世(OurDream)2D图形引擎易语言汉化版更新提示
- 如何将不同信息的数据对象合并显示到同一个页面上或者滚动窗口中
- 使用QT搭建点云显示框架系列五·基于QT的QML图像选点、动态绘制十字丝功能 ,以及纹理映射