查看: 2931|回复: 1
打印 上一主题 下一主题

[Flash3d引擎]Everyday Stage3D(六)Texture

[复制链接]

5472

主题

6

听众

1万

积分

版主

Rank: 7Rank: 7Rank: 7

纳金币
76544
精华
23

活跃会员 荣誉管理 突出贡献 优秀版主 论坛元老

跳转到指定楼层
楼主
发表于 2012-12-14 13:50:21 |只看该作者 |倒序浏览
        贴图的操作是GPU程序的必备功能之一。在stage3D中我们也可以很方便的使用位图数据作为我们程序的纹理贴图。对于纹理的操作本篇这涉及一小部分,更多的内容后面还会继续涉及到。在编写代码之前,我们要先来了解一下UV的概念。
        简单来讲,任何一个知识都不是某些人凭空想像出来的,UV存在即有他存在的理由。当我们对一个模型进行贴图操作的时候,我们希望知道这个贴图每一个像素点对应的顶点位置。为了解决这个问题,我们就产生了UV的概念。由于所有的贴图都是一张矩形图片,而图片并非存在于三维空间中的,也就是说,我们要表达图片中某一个点的位置,可以使用XY来进行表示。但是在实际的程序开发中,我们不希望贴图坐标对应点这类数据与三维顶点的XYZ数据混淆,所以我们使用UV来进行表示。为了方便大家学习,这次的demo我们换了一个稍微复杂一点的,将原来的三角形变为了一个正方形。我们通过下面的图片来说明一个正方形的顶点数据。
        这幅图中有一个正方形,包含四个顶点,坐标值已经标明在图中了。其中蓝色的线将红色的正放心分割为两个三角形,分别为T1和T2,当我们用GPU绘制三角形的时候,GPU是分别绘制T1和T2的,然后将绘制后的结构填充到同一张位图数据中,最后将位图打印到我们FLASH的容器当中。下面我们来看看位图数据。如图2
         图中已经红色的方块表示一张位图,而黑色的线表示笛卡尔坐标轴,XY对应的也是我们的UV,图中的坐标值也是我们的UV值。我们可以看到,在UV中,我们的坐标系和顶点数据的坐标系是不同的。
        oK!如果我们想让图片正确的显示在GPU中,我们要将贴图的UV数据和顶点数据一一对应,并且编写AGAL让GPU理解这些数据的关系以及含义。那么我们来看一下,对于顶点(0,0)来说,它应该对应的UV值为(0,1),具体关系可以参考上面的两幅图。同理,坐标为(1,1)的顶点应该对应UV值为(1,0),以此类推,我们可以得出四个顶点的所有UV值。通过上面的设想,我们设计了新的数据格式,每个顶点有四个值,每个值标识XYUV,代码如下。







   
        
            
            1
            2
            3
            4
            5
            6
            7
            
            
            
            //顶点数据
            var vb:Vector.<Number> = Vector.<Number>([
                0,0, 0,1,
                1,0, 1,1,
                1,1, 1,0,
                0,1, 0,0
            ]);
            
            
        
   



由于现在有两个三角形,那么我们顶点索引数据也相应的变为了如下格式。


?

   
        
            
            1
            2
            3
            4
            5
            
            
            
            //顶点索引
            var ib:Vector.<uint> = Vector.<uint>([
                0,3,1,
                1,2,3
            ]);
            
            
        
   



        有了这些基础的数据之后,我们来看一下关于纹理的操作。在stage3D中,我们可以使用BitmapData作为纹理的数据源。也就是说,到目前为止,你可以不考虑图片的格式,只要是Flash能支持load进来的图片都可以作为我们的纹理。前提是你的纹理一定要为2的次方,比如1&times;1,128&times;128,512&times;512这样的尺寸。这里为了方便,我们选取了一张128&times;128的图片,并且使用下面的代码将纹理上载置GPU。







   
        
            
            1
            2
            3
            4
            5
            6
            
            
            
            //纹理
            tex = this._context3d.createTexture(128,128,Context3DTextureFormat.BGRA,***e);
            var bit:Bitmap = new pic();
            bit.x = 350;
            this.addChild( bit );
            tex.uploadFromBitmapData( bit.bitmapData, 0 );
            
            
        
   



        当程序运行后,我们的贴图纹理就已经被上载到GPU当中,下面我们来编写AGAL,首先是顶点操作。


?

   
        
            
            1
            2
            3
            4
            5
            6
            
            
            
            //AGAL
            var vp:String = "mov op, va0
            " +
            "mov v0, va1";
            var vagal:AGALMiniAssembler = new AGALMiniAssembler();
            vagal.assemble( Context3DProgramType.VERTEX, vp );
            
            
        
   



        和原来的操作相同,只不过这里的va0中存储的数据为xy,而va1中的数据存储的则是UV坐标值。纹理着色器AGAL如下:







   
        
            
            1
            2
            3
            4
            5
            
            
            
            var fp:String = "tex ft0, v0, fs0 <2d,repeat,linear,nomip>
            " +
            "mov oc,ft0";
            var fagal:AGALMiniAssembler = new AGALMiniAssembler();
            fagal.assemble( Context3DProgramType.FRAGMENT, fp );
            
            
        
   



        很多人看到这里就会有些疑问,为什么fs0后面跟着这么一长串乱七八糟的东西。我们来详细解释一下。首先fs0表示我们的纹理,也就是要处理的贴图数据。而v0中则存放着我们的UV坐标。那么tex的作用是什么样子的呢?
         其实非常好理解,因为以前的操作大部分都可以用顶点着色器的方法去理解。我们不关心程序运行的过程,而只关心程序运行时候的某些特定的点。例如,某一个顶点的变换。其实纹理也是一样的,虽然看上去是一个面,但是纹理也是有众多的像素点组成,有了点的概念,这里理解起来也就简单多了。我们知道一个点的颜色值由RGBA组成,这里每运行到一个像素点的时候,我们就可以读取到这个像素点的RBGA颜色值,其实还是对一个点进行操作。那么上面的语句意思是将v0中对应点的数据从fs0中取出。也可以这样理解,我们从v0中知道了一个像素点的位置,并且在fs0中找到了这个像素点,取出他的RGBA颜色值放到ft0中。
         关于tex命令就说明到这里,我们再来看看<2d,repeat,linear,nomip> 这一串代码属于sampler格式。他包含4位有效数据,我们来简单解释一下。
第一位   表示维度,可使用的标签为2d或者Cube。由于我们的demo中不涉及3D效果,所以我们这里写入2d
第二位      表示环绕,可使用标签有clamp(固定不变)和repeat(自动重复)。
第三位      表示滤镜,可使用标签有nearest(临近镜面)和linear (线性)。
第四位      表示mipmap,可使用标签有disable,nearest和linear
        这四个标签代表了你贴图纹理的一些属性,通过修改这四个标签的内容,你可以从最终显示效果看到不一样的画面。




        下面我们继续完善我们的代码,数据都上载完成后,我们编写代码,主要是set操作,以便指定我们GPU绘制的内容,代码如下:


?

   
        
            
            1
            2
            3
            4
            
            
            
            this._context3d.setTextureAt( 0, this.tex );
            this._context3d.setProgram( pm );
            this._context3d.setVertexBufferAt(0,this.vbs,0, Context3DVertexBufferFormat.FLOAT_2 );
            this._context3d.setVertexBufferAt(1,this.vbs,2, Context3DVertexBufferFormat.FLOAT_2);
            
            
        
   



        这部分代码在前面几篇中都有涉及,再次不做过多的讲解。最后运行看一下我们的效果。
全部demo代码在下面:


?

   
        
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53
            54
            55
            56
            57
            58
            59
            60
            61
            62
            63
            64
            65
            66
            67
            68
            69
            70
            71
            72
            73
            74
            75
            76
            77
            78
            79
            80
            81
            82
            83
            84
            85
            86
            87
            88
            89
            90
            91
            92
            93
            94
            95
            96
            97
            98
            99
            100
            101
            102
            103
            104
            105
            106
            107
            108
            109
            110
            111
            112
            113
            114
            115
            116
            117
            
            
            
            package
            {
                import com.adobe.utils.AGALMiniAssembler;
                 
                import flash.display.Bitmap;
                import flash.display.Sprite;
                import flash.display.Stage3D;
                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;
                 
                [SWF(frameRate="60")]
                public class stage3ddemo2 extends Sprite
                {
                    [Embed(source="pic.png")]
                    private var pic:Class;
                     
                    private var _stage3d:Stage3D;
                    private var _context3d:Context3D;
                     
                    public function stage3ddemo2()
                    {
                        trace( stage.stage3Ds.length );
                        
                        this._stage3d = stage.stage3Ds[0];
                        this._stage3d.addEventListener(Event.CONTEXT3D_CREATE,created);
                        this._stage3d.requestContext3D();
                        
                    }
                     
                    private function created(evt:Event):void
                    {
                        trace( this._stage3d.context3D.driverInfo );
                        
                        this._context3d = this._stage3d.context3D;
                        this._context3d.enableErrorChecking = ***e;
                        this._context3d.configureBackBuffer( 300,300,16,***e );
                        
                        init();
                    }
                     
                    private function init():void
                    {
                        //顶点数据
                        var vb:Vector.<Number> = Vector.<Number>([
                            0,0, 0,1,
                            1,0, 1,1,
                            1,1, 1,0,
                            0,1, 0,0
                        ]);
                        
                        vbs = this._context3d.createVertexBuffer( vb.length/4, 4 );
                        vbs.uploadFromVector( vb,0, vb.length/4 );
                        
                        //顶点索引
                        var ib:Vector.<uint> = Vector.<uint>([
                            0,3,1,
                            1,2,3
                        ]);
                        
                        ibs = this._context3d.createIndexBuffer( ib.length );
                        ibs.uploadFromVector( ib, 0, ib.length );
                        
                        //纹理
                        tex = this._context3d.createTexture( 128,128, Context3DTextureFormat.BGRA,***e);
                        var bit:Bitmap = new pic();
                        bit.x = 350;
                        this.addChild( bit );
                        tex.uploadFromBitmapData( bit.bitmapData, 0 );
                        
                        //AGAL
                        var vp:String = "mov op, va0
            " +
                            "mov v0, va1";
                        
                        var vagal:AGALMiniAssembler = new AGALMiniAssembler();
                        vagal.assemble( Context3DProgramType.VERTEX, vp );
                        
                        var fp:String = "tex ft0, v0, fs0 <2d,repeat,linear,nomip>
            " +
                            "mov oc,ft0";
                        
                        var fagal:AGALMiniAssembler = new AGALMiniAssembler();
                        fagal.assemble( Context3DProgramType.FRAGMENT, fp );
                        
                        //shader
                        pm = this._context3d.createProgram();
                        pm.upload( vagal.agalcode, fagal.agalcode );
                        
                        this._context3d.setTextureAt( 0, this.tex );
                        this._context3d.setProgram( pm );
                        this._context3d.setVertexBufferAt(0,this.vbs,0, Context3DVertexBufferFormat.FLOAT_2 );
                        this._context3d.setVertexBufferAt(1,this.vbs,2, Context3DVertexBufferFormat.FLOAT_2);
                        
                        this.addEventListener(Event.ENTER_FRAME, update);
                        
                    }
                    private var pmrogram3D;
                    private var vbs:VertexBuffer3D;
                    private var ibs:IndexBuffer3D;
                    private var tex:Texture;
                     
                    //循环渲染
                    private function update(evt:Event):void
                    {
                        this._context3d.clear();
                        this._context3d.drawTriangles( this.ibs );
                        this._context3d.present();
                    }
                }
            }
            
            
        
   


分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

5472

主题

6

听众

1万

积分

版主

Rank: 7Rank: 7Rank: 7

纳金币
76544
精华
23

活跃会员 荣誉管理 突出贡献 优秀版主 论坛元老

沙发
发表于 2012-12-14 14:03:28 |只看该作者
Flash3d引擎关联教程:





[Flash3d引擎]Everyday Stage3D(五)流化你的数据




[Flash3d引擎]Everyday Stage3D(四)AGAL数据操作




[Flash3d引擎]Everyday Stage3D(三)AGAL的基本概念




[Flash3d引擎]Everyday Stage3D(二)Triangle




[Flash3d引擎]Everyday Stage3D教程(一)


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-1-27 22:20 , Processed in 0.073733 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部