android:GLSurfaceView绘制bitmap图片及glViewport调整的效果-亲测可用
https://blog.csdn.net/nupt123456789/article/details/40375731
首先看一下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:GLSurfaceView绘制bitmap图片及glViewport调整的效果-亲测可用相关推荐
- css3 实现图片闪过一道光效果 亲测可用
html部分: <div class="icon_div"> <img style="display: block; h ...
- Android FFmpeg移植总攻略——获取视频帧数(亲测可用)
第一次尝试使用Android 移植FFmpeg算法,一路坎坷,最终做如下总结,适用于Android手机.Android开发板.亲测可用. 一.下载组件 在Android Studio中下载所需组件:C ...
- Java生成二维码并把图片流导出压缩包下载(亲测可用)
目录 背景 Maven依赖相关 二维码生成 基础实体类 二维码工具类 控制层代码 结果展示 单个二维码 二维码压缩包 源码地址 背景: 实际开发中有不少二维码生成并下载的需求,单个和批量下载都比较常见 ...
- Android开发之设置Dialog外部页透明的方法亲测可用
老套路先看默认的弹框 再看处理后透明的弹框 实现方法也很简单,只需要给dialog设置一个透明的主题,主题很重要! <style name="transparent_dialog&qu ...
- h5+app打开pdf,图片,excel,world(亲测可用)
链接:https://pan.baidu.com/s/1fGJdDd9yS5A5QZ46ZAytNw 提取码:gbi9 没找到在线pdf预览,按照图片方式自己替换下路径 HbuilderX工具打开 真 ...
- Android开发之设置DialogFragment的窗体背景色的方法亲测可用
先看DialogFragment带有背景的: 再看去除背景的: 请看方法:请在onCreateView方法中调用 //设置dialog背景色为透明色getDialog().getWindow().se ...
- android bitmap 替换指定颜色,Android 实现把bitmap图片的某一部分的颜色改成其他颜色...
把bitmap图片的某一部分的颜色改成其他颜色 private Bitmap ChangeBitmap(Bitmap bitmap){ int bitmap_h; int bitmap_w; int ...
- Android 高效显示Bitmap图片
Android 高效显示Bitmap图片 本文会介绍一些处理与加载Bitmap对象的常用方法,这些技术能够使得程序的UI不会被阻塞,并且可以避免程序超出内存限制.如果我们不注意这些,Bitmap会迅速 ...
- android bitmap 替换指定颜色,Android实现把bitmap图片的某一部分的颜色改成其他颜色的方法...
Android实现把bitmap图片的某一部分的颜色改成其他颜色的方法 发布时间:2020-07-29 14:11:15 来源:亿速云 阅读:107 作者:小猪 这篇文章主要讲解了Android实现把 ...
最新文章
- PL/SQL developer export/import (转)
- LOL手游诺手对线技巧,上分率提高60%,战神玩家推荐玩法
- group_concat 不是可以识别的 内置函数名称。_Python 函数库 APIs 编写指南
- python 投资组合_重新设计投资组合的好处
- 160 - 19 Brad Soblesky.2
- ygo游戏王卡组_ACG大科普(7)游戏王
- 韩国女主播被中国土豪打赏13万 差点吓晕!网友:真是没见过世面
- ADO.NET_05_OracleDataReader
- 20200530每日一句
- Atitit table的类型 表类型目录1. 元数据表 日志表 12. 按照文件结构分为堆组织表(HOT)和索引组织表(IOT) 13. 内存表和文件存储表q 24. 全局表 2
- Excel图表工具——添加数据标签
- 大一C语言和线性代数,线性代数:对于编程很重要
- 导出手机缓存的B站视频或者在PC电脑端下载B站视频到本地
- matlab中nnt,Matlab语言的Neural Network Toolbox 及其在同步中
- CSDN,一个可能即将被遗忘的角落
- 【翻译】GRAIL-手写识别 1
- 给div添加漂亮的边框背景图
- 挖掘视频网站【优酷】上被截断的视频的地址--001
- JAVA-TOMCAT环境变量的设置方法
- 使用PfamScan的API对蛋白结构域进行注释
热门文章
- 如何使用Synopsys VCS在Vivado中编译库并执行仿真
- MySQL三种循环语句的区别_While、Loop和Repeat三种循环语句有什么异同?
- 色彩还有这些用笔错误?用笔直接影响整个画面~
- 跟我一起学Python——机械学习实现之数据预处理(混淆矩阵,印第安人糖尿病案例)(Second day)
- Spring设计模式(装饰器模式)
- 一剑封喉:Uniswap V3引领AMM向CEX发起冲锋
- 管理员管理页面(管理员添加、重置密码)
- Linux 下的金山词霸--星际译王的安装过程
- 王义辉:浅谈网站用户深度访谈
- 关于启动tomcatINFO警告错误问题解决