从零开始之OpenGL ES 2.0【0】

215 篇文章 4 订阅

https://blog.csdn.net/linghuaqian521/article/details/79852343

 

从零开始之OpenGL ES 2.0【0】

2018年04月09日 08:44:06 总是人生愁 阅读数:1016

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linghuaqian521/article/details/79852343

        刚刚接触OpenGL ES一头雾水,完全不知道从什么地方入手。本文的OpenGL ES 为 OpenGL ES2.0,为什么要从2.0开始学习呢,因为后续的3.0版本兼容2.0语法基本相同,1.0已经成为过去式,2.0及以后版本不兼容1.0了。

        为了方便学习与记忆。决定脚踏实地从浅入深的了解OpenGL ES,而不是直接从一个完整的项目一点一点讲解。既然是从浅入深的了解那么就要从最简单的例子开始了。

在开始之前还要简单做一些说明:

一、OpenGL ES的构成

        OpenGL ES所有只有 点、线、三角形。所有图形都是由以上三种构成的。如果需要复杂的3D图形可以使用3D图形工具生成后使用。

二、OpenGL ES的坐标系

    OpenGL ES坐标系有顶点坐标和纹理坐标看下图

    

                            顶点坐标

    

                            纹理坐标

三、OpenGL ES的着色器

    OpenGL ES有两个着色器:顶点着色器、片元着色器。

    最简单的着色器代码

 
  1.     //顶点着色器代码

  2. private final String vertex = "" +

  3. "attribute vec4 vPosition;" +

  4. "void main(){" +

  5. "gl_Position=vPosition;"+

  6. "}";

 
  1.     //片元着色器代码

  2. private final String fragment = "" +

  3. "precision mediump float;" +

  4. "uniform vec4 vColor;" +

  5. "void main(){" +

  6. "gl_FragColor=vColor;"+

  7. "}";

着色器代码可以放在代码内部也可以定义在外部储存设备上的文件中,读取文件内容设置也可以。它们使用GLSL语言撰写,具体语法后面会详细说明。

下面开始一个简单的例子,使用OpenGL画三角形。

1、创建一个View命名为DGLView继承GLSurfaceView实现Renderer接口;

2、创建一个Renderer命名为DGLRender实现Renderer接口。

3、在activity_main.xml内增加

 
  1. package pers.wtt.opengles10.view;

  2.  
  3. import android.content.Context;

  4. import android.opengl.GLSurfaceView;

  5. import android.util.AttributeSet;

  6.  
  7. import javax.microedition.khronos.egl.EGLConfig;

  8. import javax.microedition.khronos.opengles.GL10;

  9.  
  10. import pers.wtt.opengles10.render.DGLRender;

  11.  
  12. /**

  13. * Created by WT on 2018/4/8.

  14. */

  15. public class DGLView extends GLSurfaceView implements GLSurfaceView.Renderer{

  16.  
  17. private DGLRender dglRender;

  18.  
  19. public DGLView(Context context) {

  20. super(context);

  21. init();

  22. }

  23.  
  24. public DGLView(Context context, AttributeSet attrs) {

  25. super(context, attrs);

  26. init();

  27. }

  28.  
  29. private void init() {

  30. //初始化Renderer

  31. dglRender = new DGLRender();

  32. //设置EGLContext为2.0

  33. setEGLContextClientVersion(2);

  34. //设置render,绘制全靠它

  35. setRenderer(this);

  36. //设置render模式为只在绘制数据发生改变时才绘制view

  37. //此设置会阻止绘制GLSurfaceView的帧,直到你调用了requestRender(),这样会非常高效。

  38. setRenderMode(RENDERMODE_WHEN_DIRTY);

  39. }

  40.  
  41. @Override

  42. public void onSurfaceCreated(GL10 gl, EGLConfig config) {

  43. dglRender.onSurfaceCreated(gl, config);

  44. }

  45.  
  46. @Override

  47. public void onSurfaceChanged(GL10 gl, int width, int height) {

  48. dglRender.onSurfaceChanged(gl, width, height);

  49. }

  50.  
  51. @Override

  52. public void onDrawFrame(GL10 gl) {

  53. dglRender.onDrawFrame(gl);

  54. }

  55. }

 
  1. package pers.wtt.opengles10.render;

  2.  
  3. import android.opengl.GLES20;

  4. import android.opengl.GLSurfaceView;

  5. import java.nio.ByteBuffer;

  6. import java.nio.ByteOrder;

  7. import java.nio.FloatBuffer;

  8.  
  9. import javax.microedition.khronos.egl.EGLConfig;

  10. import javax.microedition.khronos.opengles.GL10;

  11.  
  12. /**

  13. * Created by WT on 2018/4/8.

  14. */

  15. public class DGLRender implements GLSurfaceView.Renderer {

  16.  
  17. //顶点着色器代码

  18. private final String vertex = "" +

  19. "attribute vec4 vPosition;" +

  20. "void main(){" +

  21. "gl_Position=vPosition;"+

  22. "}";

  23.  
  24. //片元着色器代码

  25. private final String fragment = "" +

  26. "precision mediump float;" +

  27. "uniform vec4 vColor;" +

  28. "void main(){" +

  29. "gl_FragColor=vColor;"+

  30. "}";

  31.  
  32. //顶点坐标

  33. private final float[] pos = {

  34. -0.5f,-0.5f,0.0f,

  35. 0.5f,0.5f,0.0f,

  36. 0.5f,-0.5f,0.0f,

  37. };

  38.  
  39. //颜色值

  40. private final float[] colors = {

  41. 1.0f,0.0f,0.0f,1.0f

  42. };

  43.  
  44. //GL程序

  45. int program;

  46. // 顶点坐标Buffer

  47. FloatBuffer vertexBuffer;

  48.  
  49. @Override

  50. public void onSurfaceCreated(GL10 gl, EGLConfig config) {

  51. //将背景设置为灰色,这里只是设置,并没有立即生效

  52. GLES20.glClearColor(0.5f,0.5f,0.5f,1.0f);

  53. //创建一个顶点坐标Buffer,一个float为4字节所以这里需要

  54. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(pos.length*4);

  55. byteBuffer.order(ByteOrder.nativeOrder());

  56. vertexBuffer = byteBuffer.asFloatBuffer();

  57. vertexBuffer .put(pos);

  58. vertexBuffer .position(0);

  59. //装载顶点着色器和片元着色器,从source

  60. int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertex);

  61. int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragment);

  62. //创建Opengl程序,获取程序句柄,为了方便onDrawFrame方法使用所以声明为成员变量

  63. program = GLES20.glCreateProgram();

  64. //激活着色器

  65. GLES20.glAttachShader(program, vertexShader);

  66. GLES20.glAttachShader(program, fragmentShader);

  67. //链接程序

  68. GLES20.glLinkProgram(program);

  69. }

  70.  
  71. /**

  72. * 装载着色器从资源代码,需要检测是否生成成功,暂时不检测

  73. * @param type 着色器类型

  74. * @param source 着色器代码源

  75. * @return 返回着色器句柄

  76. */

  77. private int loadShader(int type, String source) {

  78. int shader = 0;

  79. shader = GLES20.glCreateShader(type);

  80. GLES20.glShaderSource(shader, source);

  81. GLES20.glCompileShader(shader);

  82. return shader;

  83. }

  84.  
  85. @Override

  86. public void onSurfaceChanged(GL10 gl, int width, int height) {

  87. //当大小改变时重置视区大小

  88. GLES20.glViewport(0,0, width, height);

  89. }

  90.  
  91. @Override

  92. public void onDrawFrame(GL10 gl) {

  93. //清空缓冲区,与 GLES20.glClearColor(0.5f,0.5f,0.5f,1.0f);对应

  94. GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);

  95. //使用OpenGL程序

  96. GLES20.glUseProgram(program);

  97. //获取顶点着色器变量vPosition

  98. int vPositionHandler = GLES20.glGetAttribLocation(program, "vPosition");

  99. //允许使用顶点坐标数组

  100. GLES20.glEnableVertexAttribArray(vPositionHandler);

  101. //第一个参数顶点属性的索引值

  102. // 第二个参数顶点属性的组件数量。必须为1、2、3或者4,如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))

  103. // 第三个参数数组中每个组件的数据类型

  104. // 第四个参数指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)

  105. // 第五个参数指定连续顶点属性之间的偏移量,这里由于是三个点 每个点4字节(float) 所以就是 3*4

  106. // 第六个参数前面的顶点坐标数组

  107. GLES20.glVertexAttribPointer(vPositionHandler, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer);

  108. //获取片元着色器变量vColor

  109. int vColor = GLES20.glGetUniformLocation(program, "vColor");

  110. GLES20.glUniform4fv(vColor, 1, colors, 0);

  111. //三角形绘制方式

  112. GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3);

  113. //禁止使用顶点坐标数组

  114. GLES20.glDisableVertexAttribArray(vPositionHandler);

  115. }

  116.  
  117. }

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <LinearLayout

  3. xmlns:android="http://schemas.android.com/apk/res/android"

  4. android:layout_width="match_parent"

  5. android:layout_height="match_parent"

  6. android:orientation="vertical"

  7. >

  8.  
  9. <TextView

  10. android:id="@+id/sample_text"

  11. android:layout_width="wrap_content"

  12. android:layout_height="wrap_content"

  13. android:text="Hello World!"/>

  14.  
  15. <pers.wtt.opengles10.view.DGLView

  16. android:id="@+id/dglView"

  17. android:layout_width="match_parent"

  18. android:layout_height="match_parent"

  19. >

  20.  
  21. </pers.wtt.opengles10.view.DGLView>

  22.  
  23. </LinearLayout>

到这里就可以运行一下app看看效果了。运行结果图如下。

下一篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值