Android OpenGL例子学习

简介: Android OpenGL例子学习

例子见附件.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="anson.code.openGLDemo1"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".OGDActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

OGDActivity.java

package anson.code.openGLDemo1;
import android.app.Activity;
import android.os.Bundle;
public class OGDActivity extends Activity {
    /** Called when the activity is first created. */
  VortexView vortexView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);
        vortexView = new VortexView(this);
        setContentView(vortexView);
    }
  @Override
  protected void onPause() {
  // TODO Auto-generated method stub
  super.onPause();
  vortexView.onPause();
  }
  @Override
  protected void onResume() {
  // TODO Auto-generated method stub
  super.onResume();
  vortexView.onResume();
  }
}

VortexView.java

package anson.code.openGLDemo1;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class VortexView extends GLSurfaceView {
  private VortexRenderer renderer;
  public VortexView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
  }
  public VortexView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  renderer = new VortexRenderer();
  setRenderer(renderer);  
  }
  @Override
  public boolean onTouchEvent(final MotionEvent event) {
  // TODO Auto-generated method stub
  queueEvent(new Runnable(){
    @Override
    public void run() {
    // TODO Auto-generated method stub
    renderer.setColor(event.getX()/getWidth(), event.getY() /getHeight(), 1.0f);
    renderer.setAngle(event.getX()/10);
    }
  });
  return super.onTouchEvent(event);
  }
}

VortexRenderer.java

package anson.code.openGLDemo1;
/**
 * 程序开始      :onSurfaceCreated  -->  onSurfaceChanged  --> onDrawFrame  --> onDrawFrame  --> onDrawFrame -->
 * 程序后台唤醒:onSurfaceChanged  --> onDrawFrame  --> onSurfaceChanged   --> onDrawFrame  --> onDrawFrame -->
 * 
 * 1) onDrawFrame() 方法会在每帧中被调用,用于描述一个时时绘制的场景,你还可以通过调用 glclear 方法去清空帧缓冲,接着通过其他OpenGl ES 调用去绘制目前的场景。
 * 2) onSurfaceChanged() 方法在surface 大小尺寸改变的时候被调用,它主要设置你的openGL的观察点,你也可以在这里设置一个不会被移动到固定Camera
 * 3) onSurfaceCreated() 方法被调用在开始渲染的时候,OpenGL ES 绘图上下文时都会被重建(当activity暂停和恢复的时候,绘图的上下文也随着丢失和重建.
 */
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
public class VortexRenderer implements Renderer {
  private float red = 0f;
  private float green = 0f;
  private float blue = 0f;
  private ShortBuffer indexBuffer;
  private FloatBuffer vertexBuffer;
  private short[] indicesArray = {0, 1, 2};
  private int numberOfVertices = 3;
  private float angle;
  private void initTriangle(){
  /**
   * allocate和allocateDirect方法都做了相同的工作,
   * 不同的是allocateDirect方法 "直接"使用操作系统来分配Buffer.
   * 因而它将提供更快的访问速度。不幸的是,并非所有的虚拟机都支持这种直接分配的方法.
   * Sun推荐将以字节为单位的直接型缓冲区allocateDirect用于与大型文件相关并具有较长生命周期的缓冲区.
   */
  ByteBuffer vbb = ByteBuffer.allocateDirect(numberOfVertices *3 *4);//36;
  // ByteOrder nativeOrder() 返回当前硬件平台的字节序.
  vbb.order(ByteOrder.nativeOrder());//返回ByteOrder的字节序, 并赋给ByteBuffer.
  /** 为当前的ByteBuffer创建一个CharBuffer的视图。
   * 在该视图buffer中的读写操作会按照ByteBuffer的字节序作用到ByteBuffer中的数据上
   */
  vertexBuffer = vbb.asFloatBuffer();
  ByteBuffer ibb = ByteBuffer.allocateDirect(numberOfVertices *2);
  ibb.order(ByteOrder.nativeOrder());
  indexBuffer = ibb.asShortBuffer();
  /**
   * coords分别定义了三个顶点的座,
   * 对应为: X, Y, Z
   * 这里需要注意的是:
   * 相对于屏幕中, 原点既是在屏幕中的中点(取X/2, Y/2)
   * 原点: 0, 0, 0
   * 其中, Z轴需要以设置场景的深度为准.
   * 各个座标取值[0, 1]的浮点值.
   */
  float[] coords = {-0.5f, -0.5f, 0f,
        0.5f, -0.5f, 0f,
        0f, 0.5f, 0.1f};
  vertexBuffer.put(coords);// 写入顶点座标到vertexBuffer, 以便下面显示场景.
  indexBuffer.put(indicesArray);
  vertexBuffer.position(0);//设置当前的读取起始位置.
  indexBuffer.position(0);
  }
  public void setColor(float red, float green, float blue){
  this.red = red;
  this.green = green;
  this.blue = blue;
  }
  public void setAngle(float an){
  this.angle = an;
  }
  @Override
  public void onDrawFrame(GL10 gl) {
               // TODO Auto-generated method stub
  /**
   * RGB + A
   * 绝大多数人都认为Alpha分量代表材料的透明度。这就是说,alpha值为0.0时所代表的材料是完全透明的。alpha值为1.0时所代表的材料则是完全不透明的。
   * 红,绿,蓝和AFA值是在颜色缓冲区被清除之后使用的,并且缺省值全是0.即(0,0,0,0),其实就是设置颜色
   */
  gl.glClearColor(red, green, blue, 0.0f);
  gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//表示把整个窗口清除为当前的清除颜色,glClear()的唯一参数表示需要被清除的缓冲区。
  /**
   * 定义旋转轴
   * glRotatef(速度, X, Y, Z);
   */
  gl.glRotatef(angle, 0f, 0f, 1f);
  gl.glColor4f(0.5f, 0f, 0f, 0.5f);
  gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
  gl.glDrawElements(GL10.GL_TRIANGLES, numberOfVertices, GL10.GL_UNSIGNED_SHORT, indexBuffer);
  }
  @Override
  public void onSurfaceChanged(GL10 gl, int w, int h) {
  // TODO Auto-generated method stub
  gl.glViewport(0, 0, w, h);
  }
  @Override
  public void onSurfaceCreated(GL10 gl, EGLConfig cf) {
  // TODO Auto-generated method stub
  gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  initTriangle();
  }
}

添加画圆圈:

package anson.code.openGLDemo1;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
public class CRenderer implements Renderer {
  float rotateAngle;
  float rotateY;
  float r = 0.5f;
    //顶点数组,GL ES只能用这个办法画圆吗?  
    private float[] vertices = new float[720];  
    //度到弧度的转换  
    public float DegToRad(float deg)  
    {
      //360 = 2PI
      float Pi = 3.14159265358979323846f;
      float Du = 360;
      float v = deg * (2*Pi) / Du;
      return v;
    }  
    public void setAnX(float angle){
      rotateAngle -= angle;
    }
    public void setAnY(float ay){
      rotateY += ay;
    }
  public void onDrawFrame(GL10 gl) {
  // TODO Auto-generated method stub
  // 进入这个函数第一件要做的事就是清除屏幕和深度缓存  
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);  
        //画圆形  
        drawCircle(gl);
  }
    public void drawCircle(GL10 gl)
    {  
        //重置投影矩阵  
        gl.glLoadIdentity();  
        // 移动操作,移入屏幕(Z轴)5个像素, x, y , z  
        gl.glTranslatef(0.0f, 0.0f, -1.5f);  
        //旋转, angle, x, y , z  
        gl.glRotatef(rotateAngle, 1.0f, 0f, 0f);
        gl.glRotatef(rotateY, 0f, 1f, 0f);
        // 设置当前色为红色, R, G, B, Alpha  
        gl.glColor4f(1.0f, 0.1f, 0.1f, 1.0f);  
        //设置圆形顶点数据,这个是在创建时生成  
        FloatBuffer verBuffer = FloatBuffer.wrap(vertices);  
        //设置顶点类型为浮点坐标(GL_FLOAT),不设置或者设置错误类型将导致图形不能显示或者显示错误  
        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, verBuffer);  
        //打开顶点数组  
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  
        //向OGL发送实际画图指令
        /**
         * GL_TRIANGLE_FAN
         * GL_LINES
         * GL_LINES_LOOP
         */
        gl.glDrawArrays(GL10.GL_LINES, 0, 360);  
        //关闭顶点数组功能  
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);  
        //画图结束  
        gl.glFinish();  
        //更改旋转角度  
        //rotateAngle += 0.5;  
    }  
  public void onSurfaceChanged(GL10 gl, int width, int height) {
  // TODO Auto-generated method stub
      float ratio = (float) width / height;  
         //设置OpenGL场景的大小  
         gl.glViewport(0, 0, width, height);  
         //设置投影矩阵,既告诉OPENGL 如何把三维矩阵换为二维显示到界面上.  
         gl.glMatrixMode(GL10.GL_PROJECTION);  
         //重置投影矩阵,初始化.  
         gl.glLoadIdentity();  
         // 设置视口的大小
         /**
          * glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar)
          * 设置了显示视口的大小,也就是说,一个可视范围.
          * 把三维的东西用二维显示出来, 需要知道可以平面有多大 和 能看多近和多远.
          * 前面四个参数指定视口平面的大小, 后两个参数分别是可以看到的最近和最远.
          */
         //gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
         gl.glFrustumf(-ratio, ratio, 1f, -1f, 1f, 25);  
         // 选择模型观察矩阵  
         gl.glMatrixMode(GL10.GL_MODELVIEW);      
         // 重置模型观察矩阵  
         gl.glLoadIdentity();      
  }
  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  // TODO Auto-generated method stub
        // 启用阴影平滑 
  /** glShadeModel函数用于控制opengl中绘制指定两点间其他点颜色的过渡模式。
    * 参数一般为GL_SMOOTH(默认),GL_FLAT。OpenGL默认是将制定的两点颜色进行插值,绘制之间的其他点。
    * 如果两点的颜色相同,使用两个参数效果相同。
    * 如果两点颜色不同,GL_SMOOTH会出现过渡效果,GL_FLAT 则只是以指定的某一点的单一色绘制其他所有点。
          */
        gl.glShadeModel(GL10.GL_SMOOTH);  
        // 黑色背景  
        gl.glClearColor(0, 0, 0, 0);  
        // 设置深度缓存  
        gl.glClearDepthf(1.0f);
        // 启用深度测试
        /**
         * 在三维空间里一个物体A,在另一个物体B后面,为了不让档住的部分不显示,
         * 需要告诉OpenGL把被档住的部分隐藏, glEnable(GL10.GL_DEPTH_TEST)就是实现这个功能.
         */
        gl.glEnable(GL10.GL_DEPTH_TEST);  
        /**
         *  所作深度测试的类型
         * 这里我们比较常用的深度测试函数有 GL_LESS 和 GL_LEQUAL 
         * 两者的区别在于当深度相同时是显示新的象素 还是老的象素。
         */
        gl.glDepthFunc(GL10.GL_LEQUAL);                              
        // 告诉系统对透视进行修正
        /**
         * 在OpenGL中,许多细节的实现算法有所不同。
         * 这样,可以调用函数glHint()对图像质量和绘制速度之间的权衡作一些控制,但并非所有的实现都采用它。
         * 其函数形式为:void glHint(GLenum target,GLenum hint);
         * 控制OpenGL行为的某些方面。
         * 参数target说明控制什么行为
         * 参数hint可以是:GL_FASTEST(即给出最有效的选择)、GL_NICEST(即给出最高质量的选择)、GL_DONT_CARE(即没有选择)。
         */
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);  
        //初始化圆形数据  
        for (int i = 0; i < 720; i += 2) {  
            // x value
          if(i%4 ==0)
          vertices[i]   = (float) (Math.cos(DegToRad(i)) * r);
            // y value
            if(i%4 ==0)
              vertices[i+1] = -(float) (Math.sin(DegToRad(i)) * r);
        }
  }
}

要使圆圈运动起来:

package anson.code.openGLDemo1;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class CView extends GLSurfaceView {
  CRenderer renderer;
  float oX = 0f;
  float oY = 0f;
  public CView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
  }
  public CView(Context context) {
  super(context, null);
  // TODO Auto-generated constructor stub
  renderer = new CRenderer();
  setRenderer(renderer);
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
  //android.util.Log.d("AnsonLog", "TouchEvent:::::::::");
  // TODO Auto-generated method stub
  switch(event.getAction()){
  case MotionEvent.ACTION_DOWN:
    oX = event.getRawX();
    oY = event.getRawY();
    break;
  case MotionEvent.ACTION_MOVE:
    float cX = event.getRawX();
    float cY = event.getRawY();
    float disX = cX - oX;
    float disY = cY - oY;
    oX = cX;
    oY = cY;
    renderer.setAnX(disY/4f);
    renderer.setAnY(disX/4f);  
    break;
  case MotionEvent.ACTION_UP:
    oX = 0f;
    oY = 0f;
    break;
  }
  return true;
  }
}

http://hi.baidu.com/fairzy/blog/item/959200fcd1b60dfbfc037f9b.html这里的几篇文件不错.

OpenGLDemo1.zip (53.8 KB)

下载次数: 188

相关文章
|
6月前
|
XML 缓存 Android开发
Android开发,使用kotlin学习多媒体功能(详细)
Android开发,使用kotlin学习多媒体功能(详细)
150 0
|
2月前
|
Java Maven 开发工具
第一个安卓项目 | 中国象棋demo学习
本文是作者关于其第一个安卓项目——中国象棋demo的学习记录,展示了demo的运行结果、爬坑记录以及参考资料,包括解决Android Studio和maven相关问题的方法。
第一个安卓项目 | 中国象棋demo学习
|
1月前
|
Web App开发 编解码 视频直播
视频直播技术干货(十二):从入门到放弃,快速学习Android端直播技术
本文详细介绍了Android端直播技术的全貌,涵盖了从实时音视频采集、编码、传输到解码与播放的各个环节。文章还探讨了直播中音视频同步、编解码器选择、传输协议以及直播延迟优化等关键问题。希望本文能为你提供有关Andriod端直播技术的深入理解和实践指导。
45 0
|
6月前
|
监控 Unix 应用服务中间件
Android-音视频学习系列-(八)基于-Nginx-搭建(rtmp、http)直播服务器
Android-音视频学习系列-(八)基于-Nginx-搭建(rtmp、http)直播服务器
|
2月前
|
Android开发
Android学习 —— 测试init.rc中的条件触发的处理顺序
Android学习 —— 测试init.rc中的条件触发的处理顺序
|
3月前
|
搜索推荐 Android开发
学习AOSP安卓系统源代码,需要什么样的电脑?不同配置的电脑,其编译时间有多大差距?
本文分享了不同价位电脑配置对于编译AOSP安卓系统源代码的影响,提供了从6000元到更高价位的电脑配置实例,并比较了它们的编译时间,以供学习AOSP源代码时电脑配置选择的参考。
239 0
学习AOSP安卓系统源代码,需要什么样的电脑?不同配置的电脑,其编译时间有多大差距?
|
5月前
|
编解码 算法 程序员
老程序员分享:OpenGL学习进程(10)第七课:四边形绘制与动画基础
老程序员分享:OpenGL学习进程(10)第七课:四边形绘制与动画基础
|
6月前
|
存储 定位技术 开发工具
Android 开发前的设计,Android之内存泄漏调试学习与总结
Android 开发前的设计,Android之内存泄漏调试学习与总结
|
6月前
|
Java Android开发 Dart
50家大厂面试万字精华总结android编程基础学习
50家大厂面试万字精华总结android编程基础学习
|
6月前
|
Java Android开发
Android开发之使用OpenGL实现翻书动画
本文讲述了如何使用OpenGL实现更平滑、逼真的电子书翻页动画,以解决传统贝塞尔曲线方法存在的卡顿和阴影问题。作者分享了一个改造后的外国代码示例,提供了从前往后和从后往前的翻页效果动图。文章附带了`GlTurnActivity`的Java代码片段,展示如何加载和显示书籍图片。完整工程代码可在作者的GitHub找到:https://github.com/aqi00/note/tree/master/ExmOpenGL。
154 1
Android开发之使用OpenGL实现翻书动画