OpenGL已经成了3D的一个"标准" 因为它能跨平台,接口也比较丰富,几乎大部分的手机3D游戏都和OpenGL有关系。

当然还有微软有direct X 但只能在微软平台上使用。

OpenGL底层是c/c++实现,JAVA中使用都是用封装好的类库。Android提供了以下几个接口包 可使用,基本能达到3D技术的要求。

Android平台用OpenGL ES 这个子集来处理图像,现在OpenGL ES基本用2.0的了,很少再用1.0的,3.0还未流行起来。


首先编写判断Android设备是否支持OpenGL 2.0.

GLHelper.java加入一个判断是否支持2.0版本的代码方法。

public static boolean enableOpenGL2(Activity act) {final ActivityManager mg = (ActivityManager) act.getSystemService(Context.ACTIVITY_SERVICE);ConfigurationInfo configuration = mg.getDeviceConfigurationInfo();boolean b = configuration.reqGlEsVersion >= 0x20000);return b;}

我们需要扩展android.opengl.GLSurfaceView 这个类,让图像绘制在SurfaceView上面,看看源码发现这个类其实是扩展了SurfaceView做了写封装。


public class MyOpenGLView extends GLSurfaceView { //这个类就先空着,这一次没有太多的代码public MyOpenGLView(Context context) {super(context);}public MyOpenGLView(Context context, AttributeSet attrs) {super(context, attrs);}}


我们把处理的各种方法封装一下。

public class GLData {public GLData() {}public static float[] singelTriangles = { //定义了2个三角形,组成了一个正方形,因为openGL ES只能是点,线和三角形-0.3f, -0.3f,  0.3f, 0.3f, -0.3f, 0.3f, -0.3f, -0.3f, 0.3f, -0.3f,  0.3f, 0.3f};}

OpenGL ES在Android的坐标系是 [-1,1]的区间内




编写2个简单的顶点着色器和片段做色器。


public class GLScript {public GLScript() {}public static final String vertex1 = "attribute vec4 mPosition;\n" +"void main()\n" +"{\n" +"gl_Position=mPosition;\n " +"}\n";public static final String fragment1 = "precision mediump float;\n" +"uniform vec4 mColor;\n" +"void main(){ gl_FragColor=mColor;\n}";}

vec4 mPosition 这个表示定义了一个4分量(x,y,z,w)的顶点,然后付给gl_Position 内置的变量中,OpenGL会编译并且自动处理。
vec4 mColor 这个表示定义了一个颜色分量RGBA,最后一个是透明度,即是 红绿蓝.

  

脚本语言是OpenGL ES的核心,很多的渲染效果都需要脚本处理。

GLHelper.java添加编译脚本的代码方法.

public static int compileScript(int type, String script){int objID  = GLES20.glCreateShader(type); //创建一个着色器对象,TYPE表示顶点着色器和片段着色器if (objID == 0) { //0表示有错误    return 0;}GLES20.glShaderSource(objID, script); //把脚本代码传给OpenGL 引擎GLES20.glCompileShader(objID); //开始编译int[] status = new int[1];GLES20.glGetShaderiv(objID, GLES20.GL_COMPILE_STATUS, status, 0); //看看编译结果是否有错误。Log.d("OPENGL","compileScript status info:" + GLES20.glGetShaderInfoLog(objID));if (status[0] == 0) {GLES20.glDeleteShader(objID);//有错误我们删除这个对象。Log.e("OPENGL", "Error Compile Script:" + script);return 0;}return objID;}


如果编译成功我们开始关联OpenGL ES程序。


public static int linkGL(){int programId = GLES20.glCreateProgram();//创建一个程序if (programId == 0) {   Log.e("OPENGL", "Error Create Link Program");   return 0;}return programId;}public static int linkAttach(int vertexsharder,int fragmentsharder){int programId = linkGL();GLES20.glAttachShader(programId, vertexsharder); //和着色器进行关联GLES20.glAttachShader(programId, fragmentsharder);//和着色器进行关联GLES20.glLinkProgram(programId); //把program链接起来int status[] = new int[1];GLES20.glGetProgramiv(programId, GLES20.GL_LINK_STATUS, status, 0); //这地方一样是检查是否有错误发生。Log.d("OPENGL","linkAttach link status is " + GLES20.glGetProgramInfoLog(programId));if (status[0] == 0) {Log.e("OPENGL","link status is error.");GLES20.glDeleteProgram(programId);return 0;}return programId;}


最后我们验证程序是否有错误

public static boolean checkProgram(int programId){GLES20.glValidateProgram(programId);int status[] = new int[1];GLES20.glGetProgramiv(programId,GLES20.GL_VALIDATE_STATUS, status,0);if (status[0] == 0) {Log.e("OPENGL","program is error");return false;}return true;}

以上代码都写在GLHelper.java中,

我们把代码加入到渲染类中Renderer


渲染类

public class MyOpenGLRenderer implements Renderer {public static FloatBuffer verDataBuffer;int colorLocation ;int positionLocation ;public MyOpenGLRenderer() {// 申请直接内存空间,并使用native字节序列verDataBuffer = ByteBuffer.allocateDirect(4 * GLData.singelTriangles.length).order(ByteOrder.nativeOrder()).asFloatBuffer();verDataBuffer.put(GLData.singelTriangles);  //这是一个正方形,等会贴代码。}@Overridepublic void onDrawFrame(GL10 arg0) { //这个方法会不断的重绘GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);GLES20.glUniform4f(colorLocation, 0f, 0f, 0F, 0f); //这里是黑色,颜色将传入给<span style="font-family: Arial, Helvetica, sans-serif;">colorLocation</span>GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);//画三角形,有6个顶点 所以从0,6开始}@Overridepublic void onSurfaceChanged(GL10 arg0, int w, int h) {GLES20.glViewport(0, 0, w, h);}@Overridepublic void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {GLES20.glClearColor(1F, 1F, 1F, 0.0F); //下面的代码都是组织起来用我们编写的GLHelper类.int vertexsharder = GLHelper.compileScript(GLES20.GL_VERTEX_SHADER, GLScript.vertex1);int fragmentsharder = GLHelper.compileScript(GLES20.GL_FRAGMENT_SHADER, GLScript.fragment1);int programId = GLHelper.linkAttach(vertexsharder, fragmentsharder);boolean isOK = GLHelper.checkProgram(programId);if (isOK) {Log.d("","start draw.............."); GLES20.glUseProgram(programId); //我们开始使用这个程序 colorLocation = GLES20.glGetUniformLocation(programId, "mColor");//获得变量位置,可以理解为内存地址,OpenGL 将为在这个地址中取数据 positionLocation = GLES20.glGetAttribLocation(programId, "mPosition"); verDataBuffer.position(0);//数据开始端读取 GLES20.glVertexAttribPointer(positionLocation, 2, GLES20.GL_FLOAT, false, 0, verDataBuffer);//这个地方把顶点数据与变量关联起来 GLES20.glEnableVertexAttribArray(positionLocation);//这地方使得能够使用顶点数组   }}}

最后Activity部分代码.

private MyOpenGLView gLView;private boolean openGLEnable;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (GLHelper.enableOpenGL2(this)) {openGLEnable = true;}Log.d("","OpenGL is Enable:" + openGLEnable);gLView = new MyOpenGLView(this);gLView.setEGLContextClientVersion(2);//可以使用OpenGL ES 2.0gLView.setRenderer(new MyOpenGLRenderer());setContentView(gLView);}




运行结果很简单就是中间一个正方形。

OpenGL ES入门相对还是比较复杂的,因为函数的调用和平时用的JAVA,, C++ 库都不太一样

3D的东西复杂不仅仅是多了一个坐标Z,还有很多的渲染技术。


工程结构:




更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 大约Android远程监控APP源代码
  3. android如何利用基于Http 协议的WebService服务来获取远程数据库
  4. Android实现文章+评论(MVP,RxJava,Dagger2,ButterKnife)
  5. Android(安卓)NDK 中使用C++源文件和使用C文件的不同
  6. Android实现ViewPager无限循环滚动回绕
  7. 重磅来袭!2020 年需要关注的 5 大 Android(安卓)开发技术,抓破脑袋
  8. Android的Linux“心”
  9. Android(安卓)自动点击

随机推荐

  1. android如何实现开机自动启动Service或ap
  2. android中ImageView的ScaleType属性
  3. 【Android布局】在程序中设置android:gra
  4. android wifi
  5. android编程中的琐碎知识点汇总(2)
  6. 【Android(安卓)应用开发】 Android(安卓
  7. Android(安卓)开发问题总结 四
  8. [Android] AsyncTask使用实例---加载网络
  9. 在Android中查看和管理sqlite数据库
  10. Android中launcherMode="singleTask"详解