android:GLSurfaceView绘制bitmap图片及glViewport调整的效果
首先看一下GLSurfaceView是怎样绘制的。正如android开发文档中描写叙述的那样,我们须要new一个GLSurfaceView对象,然后设置一个实现了Renderer接口的对象,我们须要写一个MyRender类,实现Renderer的方法等等。我们先看一下Activity的写法。它不须要一个布局文件,我们将GLSurfaceView对象作为activity的contentview就可以。例如以下:
package net.mobctrl.glsurfaceviewbmp; import java.util.Random; import android.annotation.SuppressLint;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.WindowManager; /**
*
* @author Zheng Haibo
* @web http://www.mobctrl.net
*
*/
public class MainActivity extends Activity { private GLSurfaceView glView; // Use GLSurfaceView
Random rnd = new Random(); @SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(android.R.style.Theme_Translucent_NoTitleBar);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
glView = new GLSurfaceView(this); // Allocate a GLSurfaceView
glView.setRenderer(new MyGLRenderer(this)); // Use a custom renderer
glView.getAlpha();
this.setContentView(glView); } @Override
protected void onPause() {
super.onPause();
glView.onPause();
} @Override
protected void onResume() {
super.onResume();
glView.onResume();
android.provider.Settings.System.putInt(this.getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS,
rnd.nextInt(256)); }
}
以下,我们主要看一下MyGLRender类的写法,它实现了Renderer接口,详细例如以下:
package net.mobctrl.glsurfaceviewbmp; import java.util.Random; import javax.microedition.khronos.opengles.GL10; import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU; /**
* @date 2014年10月20日 下午2:49:17
* @author Zheng Haibo
* @Description: TODO
*/
public class MyGLRenderer implements Renderer {
Context context; // Application's context
Random r = new Random();
//private Square square;
private GLBitmap glBitmap;
private int width = 0;
private int height = 0;
private long frameSeq = 0;
private int viewportOffset = 0;
private int maxOffset = 400; public MyGLRenderer(Context context) {
this.context = context;
//square = new Square();
glBitmap = new GLBitmap();
} @Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0) { // Prevent A Divide By Zero By
height = 1; // Making Height Equal One
}
this.width = width;
this.height = height;
gl.glViewport(0, 0, width, height); // Reset The
// Current
// Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); // Select The Projection Matrix
gl.glLoadIdentity(); // Reset The Projection Matrix // Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
100.0f); gl.glMatrixMode(GL10.GL_MODELVIEW); // Select The Modelview Matrix
gl.glLoadIdentity();
} /**
* 每隔16ms调用一次
*/
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Reset the Modelview Matrix
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f); // move 5 units INTO the screen is
// the same as moving the camera 5
// units away
// square.draw(gl);
glBitmap.draw(gl);
changeGLViewport(gl);
} /**
* 通过改变gl的视角获取
*
* @param gl
*/
private void changeGLViewport(GL10 gl) {
System.out.println("time=" + System.currentTimeMillis());
frameSeq++;
viewportOffset++;
// The
// Current
if (frameSeq % 100 == 0) {// 每隔100帧,重置
gl.glViewport(0, 0, width, height);
viewportOffset = 0;
} else {
int k = 4;
gl.glViewport(-maxOffset + viewportOffset * k, -maxOffset
+ viewportOffset * k, this.width - viewportOffset * 2 * k
+ maxOffset * 2, this.height - viewportOffset * 2 * k
+ maxOffset * 2);
}
} @Override
public void onSurfaceCreated(GL10 gl,
javax.microedition.khronos.egl.EGLConfig arg1) {
glBitmap.loadGLTexture(gl, this.context); gl.glEnable(GL10.GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
gl.glShadeModel(GL10.GL_SMOOTH); // Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
gl.glClearDepthf(1.0f); // Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); // Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL); // The Type Of Depth Testing To Do gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
}
注意,这里主要实现了例如以下三个方法:onSurfaceCreated,onSurfaceChanged和onDrawFrame,当中,关键就是onDrawFrame方法,它的绘制机制是:1s的时间内,onDrawFrame方法会调用60次,大约每隔16ms调用一次。我们先看里面的glBitmap对象,changeGLViewport方法待会再说。
package net.mobctrl.glsurfaceviewbmp; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import net.mobctrl.glsurfaceviewbmp.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils; /**
* @date 2014年10月20日 下午3:09:33
* @author Zheng Haibo
* @Description: TODO
*/
public class GLBitmap {
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
}; private FloatBuffer vertexBuffer; // buffer holding the vertices private float vertices[] = { -1.0f, -1.0f, 0.0f, // V1 - bottom left
-1.0f, 1.0f, 0.0f, // V2 - top left
1.0f, -1.0f, 0.0f, // V3 - bottom right
1.0f, 1.0f, 0.0f // V4 - top right
}; public GLBitmap() {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0); byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
} /** The texture pointer */
private int[] textures = new int[1]; public void loadGLTexture(GL10 gl, Context context) {
// loading texture
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.plane_image); // generate one texture pointer
gl.glGenTextures(1, textures, 0);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); // create nearest filtered texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR); // Use Android GLUtils to specify a two-dimensional texture image from
// our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); // Clean up
bitmap.recycle();
} public void draw(GL10 gl) {
// bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); // Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Set the face rotation
gl.glFrontFace(GL10.GL_CW); // Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); // Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3); // Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
} }
从GLBitmap能够看出,我们首先须要载入一个图片资源,然后生成texture。在这里,特别说明一下changeGLViewport这种方法,假设在MyRender里面去掉这种方法,执行结果是,GLSurfaceView绘制出一张图片。加入这种方法以后,则是周期性得绘制一个由远到近的一个“动画”。注意,这样的动画,并没有改变图像本身,并且调整不通的视角产生的,因此效率非常高。它的原理,就像你拿一个相机,去拍摄墙壁上得一幅画,相机离画越来越近时,画面在放大,而墙壁本身并没有变化。
-------------------------------------------------------------------
很多其它交流,Android开发联盟QQ群:272209595
android:GLSurfaceView绘制bitmap图片及glViewport调整的效果的更多相关文章
- Android Developers:绘制9-patch图片
绘制9-patch图片工具让你使用可见即可得(WYSIWYG)编辑器轻松创建Nine Patch图像. 关于介绍Nine-path图片和它是如何工作的,请在2D Graphics的文档中查阅关于Nin ...
- android中对Bitmap图片设置任意角为圆角
http://blog.csdn.net/l448288137/article/details/48276681 最近项目开发中使用到了圆角图片,网上找到的圆角图片控件大多比较死板,只可以全圆角.其中 ...
- 【Android实战】Bitmap图片的截屏、模糊处理、传递、使用
项目中遇到了这样一个需求: 当某个条件满足时就截取当前屏幕.并跳转到另外一个页面,同一时候将这个截屏图片作为下一个页面的背景图片,同一时候背景图片须要模糊处理 接下来就一步一步解决这个问题: 1.截取 ...
- android中保存Bitmap图片到指定文件夹中的方法
/** 保存方法 */ public void saveBitmap() { Log.e(TAG, "保存图片"); File f = new File("/s ...
- Android下利用Bitmap切割图片
在自己自定义的一个组件中由于需要用图片显示数字编号,而当前图片就只有一张,上面有0-9是个数字,于是不得不考虑将其中一个个的数字切割下来,需要显示什么数字,只需要组合一下就好了. 下面是程序的关键代码 ...
- android绘制圆形图片的两种方式
看下效果先 下面有完整的示例代码 使用BitmapShader(着色器) 我们在绘制view 的时候 就是小学上美术课 用水彩笔在本子上画画 使用着色器绘制圆形图片最简单的理解方式 就是把bitmap ...
- android开发 两张bitmap图片合成一张图片
场景:对android4.4解码gif(解码文章见前面一篇)后的图片进行每帧处理,android4.3 解码出来的每帧都很完整,但是到android4.4版本就不完整了,每帧都是在第一帧的基础上把被改 ...
- Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据
Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据 2014-06-11 10:45:14 阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何 ...
- Android—将Bitmap图片保存到SD卡目录下或者指定目录
直接上代码就不废话啦 一:保存到SD卡下 File file = new File(Environment.getExternalStorageDirectory(), System.currentT ...
随机推荐
- 关于cocos2dx3.0 UITextField不能使用退格键删除字符的解决方式
近日開始将项目移植到cocos2dx 3.0版本号,出现了一些问题,UI方面眼下就发现UITextField控件不能响应退格键或者删除键,在Windows以下调试如此,我開始以为是平台支持不好,后来公 ...
- ZOJ 3795 Grouping 求最长链序列露点拓扑
意甲冠军:特定n积分.m向边条. 该点被划分成多个集合随机的每个集合,使得2问题的关键是无法访问(集合只能容纳一个点) 问至少需要被分成几个集合. 假设没有戒指,接着这个话题正在寻求产业链最长的一个有 ...
- siwft初学(一)
今天刚開始学习swift语言.首先须要下载xcode6 beta版本号.正式版本号然后会公布.自己学习总结一下,假设有误.请大家指出. 创建project的时候.language选择swift语言. ...
- Java对于私有变量“反思暴力”技术
(1)这两个类:(在相同的包装可以是) watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGxnZW4xNTczODc=/font/5a6L5L2T/font ...
- Windows8.1硬盘安装Ubuntu14.04双系统参考教程和多硬盘的注意事项[画画]
硬盘安装.无需光盘.U盘:Win8.1为主,Ubuntu14.04为辅,可将Windows或Ubuntu设置为开机默认启动项.在Ubuntu下可查看.操作Windows系统下的文件:适用于安装和14. ...
- wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)
原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码) pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依 ...
- 深度分析 Java 的 ClassLoader 机制(源码级别)(转)
写在前面:Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,JVM在加载类的时候,都是通过ClassLoa ...
- wpf做的3d滑动gallery
原文:wpf做的3d滑动gallery wpf做的3d滑动gallery 随着iphone\ipad的流行及热捧,现在做移动产品不管是什么平台的,领导总想做成像ios系统的样子.自从微软发布了wind ...
- effective c++ 条款11 Handle assignment to self in operator=
赋值给自己,听起来有些不可思议,但是却要引起重视,它很容易把自己隐藏起来. 例如 1 a[i]=a[j]; 如果 i, j的值一样? 2 *px=*py; 如果px py指向同一个object 3 ...
- WPF中两条路径渐变的探讨
原文:WPF中两条路径渐变的探讨 我们在WPF中,偶尔也会涉及到两条路径作一些“路径渐变 ”.先看看比较简单的情形:如下图(关键点用红色圆点加以标识):(图1) 上面图1中的第1幅图可以说是最简单的路 ...