Android游戏框架libgdx笔记(二):图像处理

Mesh: 

本质上讲,Libgdx中所有可见的3D物体首先都是一个Mesh(网格,或者说三维网格形式的高级图元)。Mesh是如何生成的呢?众所周知,数学上讲的立体几何由点、线、面三部分组成,无论多么复杂的图像也可以分解为无数细小的这三部分,或者说可以由非常基础的N个这三部分所组合而成;到了3D游戏开发时,当我们要构建复杂的3D图像,首先会以一系列有序的vertices(顶点)构成这些具体的点、线、三角要素,即构成绘图基本图元(Primitives),再将基本图元组合成更完整的高级图元也就是具体3D对象。因此,如果对Mesh概念进行简单的理解,其实它就是一个象征完整图像的基本图元集合体,Libgdx先让我们把一个个细分的vertices组成基本图元,再由Mesh类将基本图元制成更加复杂的高级图元展示出来。

具体可见Libgdx作者提供的returntomarchfeld示例,基本效果如下图所示:

 

00

 

(勿看FPS,一切信真机)

PS:如果对此类认识不足,可以去玩玩模拟人生,下个修改器尝试编辑角色或物品造型后就懂了……
 

Texture:
 

Libgdx所提供的游戏纹理用类,其实质可理解为保存在显存中的Image,它以贴图的方式通过OpenGL将图片显示到游戏界面之上。Libgdx的纹理可以直接从指定文件路径加载,也可以通过它提供的Pixmap类凭空创建(它的Texture(int width, int height, Format format)构造内部直接调用了Pixmap,不是必须在外部生成Pixmap后注入)。另外在加载Texture时,个人建议通过Libgdx提供的TextureDict.loadTexture函数调用,该方法内部提供了Texture缓存管理,能够避免无意义的资源重复加载。此外,Texture通常会与TextureRegion类配套使用,利用TextureRegion包装Texture后,再利用SpriteBatch进行绘制,可以很方便的修订Texture为我们需要的显示范围。还有,Libgdx中Sprite类为TextureRegion子类,因此能够将Sprite当作TextureRegion来使用,只是Sprite类比TextureRegion有所扩展。不过Libgdx的SpriteCache类并没有继承Sprite或TextureRegion,所以起不到TextureRegion的作用,只能构建一组静态贴图集合罢了,特此说明。

[java]  view plain copy
  1. // Libgdx的Texture与Sprite使用  
  2. public class Main extends AndroidApplication {  
  3.     class TestSprite implements ApplicationListener {  
  4.         // 准备绘图用SpriteBatch  
  5.         SpriteBatch spriteBatch;  
  6.         // 准备游戏精灵  
  7.         Sprite sprite;  
  8.         // 准备图片加载用Texture  
  9.         Texture texture;  
  10.         public void create() {  
  11.             // 构建SpriteBatch  
  12.             spriteBatch = new SpriteBatch();  
  13.             // 构建Texture,图像宽与高大小都必须为2的整数次幂,否则提示异常  
  14.             // PS:在Android环境使用Libgdx的internal加载时必须文件必须位于assets目录下  
  15.             texture = new Texture(Gdx.files.internal("mySprite.png"));  
  16.             // 以指定Texture构建Sprite  
  17.             sprite = new Sprite(texture);  
  18.             // 定位到100, 180(Libgdx使用标准笛卡尔坐标系,自左下0,0开始)  
  19.             sprite.setPosition(100180);  
  20.         }  
  21.         public void render() {  
  22.             // 清屏  
  23.             Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);  
  24.             // 初始化绘图调用  
  25.             spriteBatch.begin();  
  26.             // 绘制精灵到游戏屏幕  
  27.             sprite.draw(spriteBatch);  
  28.             // 结束绘图调用  
  29.             spriteBatch.end();  
  30.         }  
  31.         public void dispose() {  
  32.             // 释放占用的资源  
  33.             spriteBatch.dispose();  
  34.             texture.dispose();  
  35.         }  
  36.         public void resume() {  
  37.         }  
  38.         public void pause() {  
  39.         }  
  40.         public void resize(int width, int height) {  
  41.         }  
  42.     }  
  43.     public void onCreate(Bundle bundle) {  
  44.         super.onCreate(bundle);  
  45.         // 初始化游戏屏幕,并设置是否支持GLES 2.0,如果您对向下兼容没什么需要选择true即可(2.1以上),否则选择false。  
  46.         initialize(new TestSprite(), true);  
  47.     }  
  48. }  


Pixmap:
 

Libgdx所提供的像素级图像渲染用类,由于Libgdx目前以JNI方式自带图像解码器,所以我们可以直接将Pixmap理解为一个Android中Bitmap的替代者,两者间实现细节虽有差别,但具体作用却大同小异。Pixmap支持Alpha、LuminanceAlpha、RGB565、RGBA4444、RGB888、RGBA8888等五种图像彩色模式,支持png、jpg、bmp等三种图像文件的读取和加载。一般来说,Pixmap必须和Texture混用才能真正显示画面。不过在事实上,Libgdx的Texture里已经内置有Pixmap了。

 

[java]  view plain copy
  1. // Libgdx的Pixmap使用  
  2. public class Main extends AndroidApplication {  
  3.       
  4.     class TestPixmap implements ApplicationListener {  
  5.         // 准备绘图用SpriteBatch  
  6.         SpriteBatch spriteBatch;  
  7.         // Pixmap是Libgdx提供的针对opengl像素操作的上级封装,它可以凭空构建一个像素贴图,  
  8.         // 但是它的现实必须通过Texture。  
  9.         Pixmap pixmap;  
  10.         // 准备Texture  
  11.         Texture texture;  
  12.         public void create() {  
  13.             // 构建SpriteBatch  
  14.             spriteBatch = new SpriteBatch();  
  15.             // 构建Pixmap(在Android环境使用internal加载模式时,文件必须放置于assets文件夹下)  
  16.             pixmap = new Pixmap(Gdx.files.internal("myPixmap.png"));  
  17.             // 绘制一个蓝方块到Ball图像之上  
  18.             pixmap.setColor(Color.BLUE.r, Color.BLUE.g, Color.BLUE.b,  
  19.                     Color.BLUE.a);  
  20.             pixmap.drawRectangle(15154040);  
  21.             // 以指定Pixmap构建Texture  
  22.             texture = new Texture(pixmap);  
  23.             // 注入Texture后的pixmap已经没用,可以注销  
  24.             pixmap.dispose();  
  25.         }  
  26.         public void dispose() {  
  27.             spriteBatch.dispose();  
  28.             texture.dispose();  
  29.         }  
  30.         public void pause() {  
  31.         }  
  32.         public void render() {  
  33.             // 清屏  
  34.             Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);  
  35.             // 初始化绘图调用  
  36.             spriteBatch.begin();  
  37.             // 绘制精灵到游戏屏幕  
  38.             spriteBatch.draw(texture, 100180);  
  39.             // 结束绘图调用  
  40.             spriteBatch.end();  
  41.         }  
  42.         public void resize(int width, int height) {  
  43.         }  
  44.         public void resume() {  
  45.         }  
  46.     }  
  47.     public void onCreate(Bundle bundle) {  
  48.         super.onCreate(bundle);  
  49.         // 初始化游戏屏幕,并设置是否支持GLES 2.0,如果您对向下兼容没什么需要选择true即可(2.1以上),否则选择false。  
  50.         initialize(new TestPixmap(), true);  
  51.     }  
  52. }  



BitmapFont:
 

Libgdx所提供的OpenGL文字用类,构造BitmapFont时需要一个描述文字构成的fnt文件,和一个提供文字图片的png文件(PS:在Libgdx的com.badlogic.gdx.utils包下有提供内置字库,目前仅支持英文、数字和常见符号),同SpriteBatch相配合时能够完成一些基础的文字绘图。值得一提的是,我们也可以使用BitmapFontCache类将BitmapFont包装成了一个静态的Font实例,以避免大量贴图时产生的不必要损耗。

 

[java]  view plain copy
  1. //libgdx的文字显示  
  2. public class Main extends AndroidApplication {  
  3.     class TestFont extends Game {  
  4.         // SpriteBatch是libgdx提供的opengl封装,可以在其中执行一些常规的图像渲染,  
  5.         // 并且libgdx所提供的大多数图形功能也是围绕它建立的。  
  6.         SpriteBatch spriteBatch;  
  7.         // BitmapFont是libgdx提供的文字显示用类,内部将图片转化为可供opengl调用的  
  8.         // 文字贴图(默认不支持中文)。  
  9.         BitmapFont font;  
  10.         public void create() {  
  11.             //构建SpriteBatch用于图像处理(内部调用opengl或opengles)  
  12.             spriteBatch = new SpriteBatch();  
  13.             //构建BitmapFont,必须有一个fnt文件描述文字构成,一个图片文件提供文字用图  
  14.             font = new BitmapFont(Gdx.files.internal("font.fnt"), Gdx.files  
  15.                     .internal("font.png"), false);  
  16.         }  
  17.         public void render() {  
  18.                 // 调用清屏  
  19.             Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);  
  20.             // 初始要有begin起始  
  21.             spriteBatch.begin();  
  22.             // 显示文字到屏幕指定位置  
  23.             // PS:Libgdx采用标准笛卡尔坐标系,自左下0,0开始  
  24.             font.draw(spriteBatch, "FPS" + Gdx.graphics.getFramesPerSecond(),  
  25.                     5475);  
  26.             font.draw(spriteBatch, "Hello Libgdx"255255);  
  27.             // 结束要有end结尾  
  28.             spriteBatch.end();  
  29.         }  
  30.         public void resize(int width, int height) {  
  31.         }  
  32.         public void pause() {  
  33.         }  
  34.         public void resume() {  
  35.         }  
  36.         public void dispose() {  
  37.             // 释放占用的资源  
  38.             spriteBatch.dispose();  
  39.             font.dispose();  
  40.         }  
  41.     }  
  42.     public void onCreate(Bundle bundle) {  
  43.         super.onCreate(bundle);  
  44.         // 初始化游戏屏幕,并设置是否支持GLES 2.0,如果您对向下兼容没什么需要选择true即可(2.1以上),否则选择false。  
  45.         initialize(new TestFont(), true);  
  46.     }  
  47. }  

 

00


SpriteBatch:
 

Libgdx所提供的纹理渲染器,本质上是OpenGL的简易封装体,具体实现上与XNA中的SpriteBatch类非常近似,每次调用SpriteBatch类都必须以begin函数开头,以end函数结尾。由于Libgdx中SpriteBatch提供的功能还非常有限,所以在完全不懂OpenGL的前提下使用其进行游戏开发或许有一定难度。

ShaderProgram:
 

Libgdx所提供的着色器,在Android环境使用时需要GLES2.0或以上版本才能完整支持的高级渲染功能之一,内部封装着GLES2.0专用的顶点着色与片断着色Shader Model,它的本质作用是对3D对象表面进行渲染处理,此物性能基本取决于GPU(除了Google Nexus系列手机暂未见能完全跑出速度的机型)。

 

[java]  view plain copy
  1. //libgdx的ShaderProgram使用  
  2. public class Main extends AndroidApplication {  
  3.     class TestShader implements ApplicationListener {  
  4.         ShaderProgram shader;  
  5.         Texture texture;  
  6.         Texture texture2;  
  7.         Mesh mesh;  
  8.         public void create() {  
  9.             // 以下命令供GPU使用(不支持GLES2.0就不用跑了)  
  10.             String vertexShader = "attribute vec4 a_position;   /n"  
  11.                     + "attribute vec2 a_texCoord;   /n"  
  12.                     + "varying vec2 v_texCoord;     /n"  
  13.                     + "void main()                  /n"  
  14.                     + "{                            /n"  
  15.                     + "   gl_Position = a_position; /n"  
  16.                     + "   v_texCoord = a_texCoord;  /n"  
  17.                     + "}                            /n";  
  18.             String fragmentShader = "#ifdef GL_ES/n"  
  19.                     + "precision mediump float;/n"  
  20.                     + "#endif/n"  
  21.                     + "varying vec2 v_texCoord;                            /n"  
  22.                     + "uniform sampler2D s_texture;                        /n"  
  23.                     + "uniform sampler2D s_texture2;                        /n"  
  24.                     + "void main()                                         /n"  
  25.                     + "{                                                   /n"  
  26.                     + "  gl_FragColor = texture2D( s_texture, v_texCoord ) * texture2D( s_texture2, v_texCoord);/n"  
  27.                     + "}                                                   /n";  
  28.             // 构建ShaderProgram  
  29.             shader = new ShaderProgram(vertexShader, fragmentShader);  
  30.             // 构建网格对象  
  31.             mesh = new Mesh(true46new VertexAttribute(Usage.Position, 2,  
  32.                     "a_position"), new VertexAttribute(  
  33.                     Usage.TextureCoordinates, 2"a_texCoord"));  
  34.             float[] vertices = { -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f,  
  35.                     1.0f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 0.0f };  
  36.             short[] indices = { 012023 };  
  37.             // 注入定点坐标  
  38.             mesh.setVertices(vertices);  
  39.             mesh.setIndices(indices);  
  40.             // 以Pixmap生成两个指定内容的Texture  
  41.             Pixmap pixmap = new Pixmap(256256, Format.RGBA8888);  
  42.             pixmap.setColor(1111);  
  43.             pixmap.fill();  
  44.             pixmap.setColor(0001);  
  45.             pixmap.drawLine(00256256);  
  46.             pixmap.drawLine(25600256);  
  47.             texture = new Texture(pixmap);  
  48.             pixmap.dispose();  
  49.             pixmap = new Pixmap(256256, Format.RGBA8888);  
  50.             pixmap.setColor(1111);  
  51.             pixmap.fill();  
  52.             pixmap.setColor(0001);  
  53.             pixmap.drawLine(1280128256);  
  54.             texture2 = new Texture(pixmap);  
  55.             pixmap.dispose();  
  56.         }  
  57.         public void dispose() {  
  58.         }  
  59.         public void pause() {  
  60.         }  
  61.         public void render() {  
  62.             // PS:由于使用了ShaderProgram,因此必须配合gl20模式(否则缺少关键opengles接口)  
  63.             Gdx.gl20.glViewport(00, Gdx.graphics.getWidth(), Gdx.graphics  
  64.                     .getHeight());  
  65.             Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);  
  66.             Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);  
  67.             texture.bind();  
  68.             Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE1);  
  69.             texture2.bind();  
  70.             // 开始使用ShaderProgram渲染  
  71.             shader.begin();  
  72.             shader.setUniformi("s_texture"0);  
  73.             shader.setUniformi("s_texture2"1);  
  74.             mesh.render(shader, GL20.GL_TRIANGLES);  
  75.             // 结束ShaderProgram渲染  
  76.             shader.end();  
  77.         }  
  78.         public void resize(int width, int height) {  
  79.         }  
  80.         public void resume() {  
  81.         }  
  82.     }  
  83.     public void onCreate(Bundle bundle) {  
  84.         super.onCreate(bundle);  
  85.         // 初始化游戏屏幕,并设置是否支持GLES 2.0,如果您对向下兼容没什么需要选择true即可(2.1以上),否则选择false。  
  86.         initialize(new TestShader(), true);  
  87.     }  
  88. }  

 


FrameBuffer:

Libgdx所提供的帧缓冲器,在Android环境使用时需要GLES2.0或以上版本才能完整支持的高级渲染功能之一,也就是常说的FrameBuffer Object(FBO)功能封装(用过JavaSE或JavaME开发游戏的朋友,绘图时大概都接触过双缓存这个概念,虽然有所差别,不过将FrameBuffer理解成起近似作用也未尝不可)此物性能彻底取决于GPU(除了Google Nexus系列手机暂未见能完全跑出速度的机型)。

 

[java]  view plain copy
  1. //libgdx的FrameBuffer使用  
  2. public class Main extends AndroidApplication {  
  3.     class TestFrameBuffer implements ApplicationListener {  
  4.         FrameBuffer frameBuffer;  
  5.         Mesh mesh;  
  6.         ShaderProgram meshShader;  
  7.         Texture texture;  
  8.         SpriteBatch spriteBatch;  
  9.         // PS:如果不支持GLES2.0就不用试了  
  10.         public void create() {  
  11.             mesh = new Mesh(true30new VertexAttribute(Usage.Position, 3,  
  12.                     "a_Position"), new VertexAttribute(Usage.ColorPacked, 4,  
  13.                     "a_Color"), new VertexAttribute(Usage.TextureCoordinates,  
  14.                     2"a_texCoords"));  
  15.             float c1 = Color.toFloatBits(25500255);  
  16.             float c2 = Color.toFloatBits(25500255);  
  17.             float c3 = Color.toFloatBits(00255255);  
  18.             mesh.setVertices(new float[] { -0.5f, -0.5f, 0, c1, 000.5f,  
  19.                     -0.5f, 0, c2, 1000.5f, 0, c3, 0.5f, 1 });  
  20.             texture = new Texture(Gdx.files.internal("myTest.png"));  
  21.             spriteBatch = new SpriteBatch();  
  22.             frameBuffer = new FrameBuffer(Format.RGB565, 128128true);  
  23.             String vertexShader = "attribute vec4 a_Position;    /n"  
  24.                     + "attribute vec4 a_Color;/n"  
  25.                     + "attribute vec2 a_texCoords;/n" + "varying vec4 v_Color;"  
  26.                     + "varying vec2 v_texCoords; /n" +  
  27.                     "void main()                  /n"  
  28.                     + "{                            /n"  
  29.                     + "   v_Color = a_Color;"  
  30.                     + "   v_texCoords = a_texCoords;/n"  
  31.                     + "   gl_Position =   a_Position;  /n"  
  32.                     + "}                            /n";  
  33.             String fragmentShader = "precision mediump float;/n"  
  34.                     + "varying vec4 v_Color;/n"  
  35.                     + "varying vec2 v_texCoords; /n"  
  36.                     + "uniform sampler2D u_texture;/n"  
  37.                     +  
  38.                     "void main()                                  /n"  
  39.                     + "{                                            /n"  
  40.                     + "  gl_FragColor = v_Color * texture2D(u_texture, v_texCoords);/n"  
  41.                     + "}";  
  42.             meshShader = new ShaderProgram(vertexShader, fragmentShader);  
  43.             if (meshShader.isCompiled() == false)  
  44.                 throw new IllegalStateException(meshShader.getLog());  
  45.         }  
  46.         public void dispose() {  
  47.         }  
  48.         public void pause() {  
  49.         }  
  50.         public void render() {  
  51.             frameBuffer.begin();  
  52.             Gdx.graphics.getGL20().glViewport(00, frameBuffer.getWidth(),  
  53.                     frameBuffer.getHeight());  
  54.             Gdx.graphics.getGL20().glClearColor(0f, 1f, 0f, 1);  
  55.             Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);  
  56.             Gdx.graphics.getGL20().glEnable(GL20.GL_TEXTURE_2D);  
  57.             texture.bind();  
  58.             meshShader.begin();  
  59.             meshShader.setUniformi("u_texture"0);  
  60.             mesh.render(meshShader, GL20.GL_TRIANGLES);  
  61.             meshShader.end();  
  62.             frameBuffer.end();  
  63.             Gdx.graphics.getGL20().glViewport(00, Gdx.graphics.getWidth(),  
  64.                     Gdx.graphics.getHeight());  
  65.             Gdx.graphics.getGL20().glClearColor(0.2f, 0.2f, 0.2f, 1);  
  66.             Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);  
  67.             spriteBatch.begin();  
  68.             spriteBatch.draw(frameBuffer.getColorBufferTexture(), 00256,  
  69.                     25600, frameBuffer.getColorBufferTexture().getWidth(),  
  70.                     frameBuffer.getColorBufferTexture().getHeight(), false,  
  71.                     true);  
  72.             spriteBatch.end();  
  73.         }  
  74.         public void resize(int width, int height) {  
  75.         }  
  76.         public void resume() {  
  77.         }  
  78.     }  
  79.     public void onCreate(Bundle bundle) {  
  80.         super.onCreate(bundle);  
  81.         // 初始化游戏屏幕,并设置是否支持GLES 2.0,如果您对向下兼容没什么需要选择true即可(2.1以上),否则选择false。  
  82.         initialize(new TestFrameBuffer(), true);  
  83.     }  
  84. }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值