栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android Studio + OpenGL ES 学习记录

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android Studio + OpenGL ES 学习记录

Android Studio + OpenGL ES 学习记录

OpenGL是一种应用程序编程接口,它是一种可以对图形硬件设备特性进行访问的软件库,而OpenGL ES是OpenGL的子集,针对手机、PDA和游戏主机嵌入式设备而设计。OpenGL ES 是从 OpenGL 裁剪定制而来的,去除了 glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性,剩下最核心有用的部分。

简介

OpenGL是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API),而在嵌入式和移动平台的版本是OpenGL ES。Android最初就支持OpenGL ES的1.0版本,到现在已经支持到最新的3.2版本,下面的支持变化图:

版本支持声明

可以在AndroidManifet.xml中加入下面这行使用特性的声明,Google Play将会过滤掉不支持指定OpenGL ES版本的用户,拒绝他们安装。

  
  

也可以在代码中判断gles的版本,version同样传入版本号即可(例如0x20000)

   public static boolean checkOpenGL(Activity activity, int version) {
      ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
      if (am != null) {
          return am.getDeviceConfigurationInfo().reqGlEsVersion >= version;
      }
      return false;
  }

OpenGL ES的名词解释
图元
官方的解释是图形软件用来描述各种图形的函数,可以理解为图元就是组成图像的基本单元。

顶点数据
在计算机中图元的位置是通过x,y,z,w来存储或颜色数据是通过RGBA的数组格式存储的,然后通过多个点来进行图元装配和光栅化出图形。

片元
元是光栅化过程的产物,光栅化是将一个图元转变为一个二维图象。

光栅化
光栅化是处理区域内的图元并生成片元数据。

OpenGL渲染管线
是显卡芯片内部处理图形信号相互独立的并行处理单元。也就是把数据转化到openGL并且生成最终图像的一个过程。

GLSL是什么
GLSL是一门专门为图形开发设计的编程语言。

可编程管线的编程阶段

基础

两个基本的类GLSurfaceView和GLSurfaceView.Renderer。
GLSurfaceView:继承自SurfaceView,用来显示渲染的图像。如果想操作你的图像,需要扩展触摸监听事件来处理。
GLSurfaceView.Renderer:GLSurfaceView的内部接口类,主要负责渲染图像。

GLSurfaceView主要方法:
setEGLContextClientVersion:设置OpenGL ES的版本,只能设置主要版本(例如:1,2,3),不能设置次要版本。
setEGLContextFactory:设置OpenGL ES的版本构建器,默认的构建器是根据版本设置的,可以自定义成版本自适应。
setRenderer:设置Renderer,如果不设置,那么界面显示的就是一片空白。
setRenderMode:设置Renderer的模式,有这么两种:1、RENDERMODE_WHEN_DIRTY(仅在创建时或调用requestRender时才会渲染内容);RENDERMODE_CONTINUOUSLY(不停的渲染)。
onPause:暂停渲染,在页面不再显示时可以调用,减少性能开销,例如在Activity的onStop时。
onResume:恢复渲染,类似onPause。 requestRender:请求渲染,通常是RENDERMODE_WHEN_DIRTY模式时使用,必须在setRenderer后才能使用。
queueEvent:插入一个Runnable任务到后台渲染线程上执行,必须在setRenderer后才能使用。 setDebugFlags:设置debug模式,主要有两种:1、DEBUG_CHECK_GL_ERROR(当GL调用glError()方法后如果发生异常会打印。主要用来跟踪OpenGL错误。);2、DEBUG_LOG_GL_CALLS(打印所有GL的verbose级别的日志)
2.GLSurfaceView.Renderer的主要方法:

onSurfaceCreated(GL10 gl, EGLConfig config):当Surface创建或重新创建时,这时可以进行初始化。
onSurfaceChanged(GL10 gl, int width, int height):Surface尺寸改变时,返回当前surface宽高,可以进行下一步操作。
onDrawframe(GL10 gl):渲染绘制当前一帧时会调用。
OpenGL类:在包android.opengl下,主要有GLES20(OpenGL ES 2.0版本),GLES30,GLES31,GLES32和。

  public class baseGLView extends GLSurfaceView {
      public baseGLView(Context context) {
          this(context, null);
      }
 
      public baseGLView(Context context, AttributeSet attrs) {
          super(context, attrs);
          setDebug();
          init();
      }
 
      protected void setDebug() {
          setDebugFlags(BuildConfig.DEBUG ? DEBUG_LOG_GL_CALLS : DEBUG_CHECK_GL_ERROR);
      }
 
      protected void init() {
          // 设置版本
          setEGLContextClientVersion(2);
          // 设置Renderer
          setRenderer(new baseRenderer());
          // 设置渲染模式(默认RENDERMODE_CONTINUOUSLY)
          setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
      }
  }

新建一个自定义的Renderer类

 public class baseRenderer implements GLSurfaceView.Renderer {
      private int bg = Color.BLACK;
 
      public baseRenderer() {
      }
 
      public baseRenderer(int bg) {
          this.bg = bg;
      }
 
 
      @Override
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
          // 设置背景色
          GLES20.glClearColor(Color.red(bg) / 255.0f, Color.green(bg) / 255.0f,
                  Color.blue(bg) / 255.0f, Color.alpha(bg) / 255.0f);
      }
 
      @Override
      public void onSurfaceChanged(GL10 gl, int width, int height) {
          // 设置显示范围
          GLES20.glViewport(0, 0, width, height);
      }
 
      @Override
      public void onDrawframe(GL10 gl) {
          // 清屏
          GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
      }
  }
安卓手机下的坐标系


三维坐标系,原点在中间,x 轴向右,y 轴向上,z 轴朝向我们,x y z 取值范围都是 [-1, 1]:


OpenGL 纹理(texture)坐标系
二维坐标系,原点在左下角,s(x)轴向右,t(y)轴向上,x y 取值范围都是 [0, 1]:

绘制一个最简单的三角形

主程序:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GLSurfaceView glSurfaceView =
                (android.opengl.GLSurfaceView) findViewById(R.id.mGLSurfaceView);

        glSurfaceView.setEGLContextClientVersion(2);
        glSurfaceView.setRenderer(new MyRenderer());
        glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }

    static class MyRenderer implements GLSurfaceView.Renderer {
        private static final String VERTEX_SHADER = "attribute vec4 vPosition;n"
                + "void main() {n"
                + "  gl_Position = vPosition;n"
                + "}";
        private static final String FRAGMENT_SHADER = "precision mediump float;n"
                + "void main() {n"
                + "  gl_FragColor = vec4(0.5,0,0,1);n"
                + "}";
        private static final float[] VERTEX = {   // in counterclockwise order:
                0, 1, 0.0f, // top
                -0.5f, -1, 0.0f, // bottom left
                1f, -1, 0.0f,  // bottom right
        };

        private final FloatBuffer mVertexBuffer;

        private int mProgram;
        private int mPositionHandle;

        MyRenderer() {
            mVertexBuffer = ByteBuffer.allocateDirect(VERTEX.length * 4)
                    .order(ByteOrder.nativeOrder())
                    .asFloatBuffer()
                    .put(VERTEX);
            mVertexBuffer.position(0);
        }

        @Override
        public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        }

        @Override
        public void onSurfaceChanged(GL10 unused, int width, int height) {
            mProgram = GLES20.glCreateProgram();
            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER);
            int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
            GLES20.glAttachShader(mProgram, vertexShader);
            GLES20.glAttachShader(mProgram, fragmentShader);
            GLES20.gllinkProgram(mProgram);
            
            mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        }

        @Override
        public void onDrawframe(GL10 unused) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    
            GLES20.glUseProgram(mProgram);

            GLES20.glEnableVertexAttribArray(mPositionHandle);
            GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false,
                    12, mVertexBuffer);

            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

            GLES20.glDisableVertexAttribArray(mPositionHandle);
        }

        static int loadShader(int type, String shaderCode) {
            int shader = GLES20.glCreateShader(type);
            GLES20.glShaderSource(shader, shaderCode);
            GLES20.glCompileShader(shader);
            return shader;
        }
    }
}

运行效果:

原文链接

fjnu 116052019030 huangyuxuan

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/657670.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号