Opengles2.0 for android入门笔记(一)
2016-11-16 19:57
393 查看
oepngles2.0 for android的教程少的可怜,有的居然还是opengles 1.0版本的。鄙人刚学opengles,理论也是一知半解,其实android已经帮我们封装了一些内容了,so我直接从最基础的用法开始记录了。
1.oepngles2.0绘图基本流程
图形是绘制在GlSurfaceView中的,也就是画布。而具体绘制什么是由GLSurfaceView.Renderer的实现类绘制的,也就是画笔,简称为render。render在onDrawFrame函数中绘制每一帧图像,具体到每一个像素应该具体绘制什么颜色则由传说中的着色器语言和opengl接口协作完成。
2.最基础的使用,绘制一个矩形。opengles没有接口可以画一个矩形,神马?大安卓居然没有封装?画第一个矩形真是件艰巨的任务。那就老老实实开始画吧,等等,在manifest中加这句话:先,然后:
a.创建画布和画笔呗,也就是GlSurfaceView和GLSurfaceView.Renderer的实现类
TraingleRender类内容如下:
b.编译着色器语言。麻蛋,画个三角形还要介个?还好可以写到static函数里重用。在res下创建raw文件夹,在raw下创建traingle_vertex_shader.glsl和traingle_fragment_shader.glsl文件,两个文件内容如下:
traingle_vertex_shader.glsl:
traingle_fragment_shader.glsl:
然后用用我们的Util编译,此处叫OpenglHelper,内容如下:
c.终于可以画东西了,创建我们的Traingle.java,内容如下:
TraingleDemo下载链接
1.oepngles2.0绘图基本流程
图形是绘制在GlSurfaceView中的,也就是画布。而具体绘制什么是由GLSurfaceView.Renderer的实现类绘制的,也就是画笔,简称为render。render在onDrawFrame函数中绘制每一帧图像,具体到每一个像素应该具体绘制什么颜色则由传说中的着色器语言和opengl接口协作完成。
2.最基础的使用,绘制一个矩形。opengles没有接口可以画一个矩形,神马?大安卓居然没有封装?画第一个矩形真是件艰巨的任务。那就老老实实开始画吧,等等,在manifest中加这句话:先,然后:
a.创建画布和画笔呗,也就是GlSurfaceView和GLSurfaceView.Renderer的实现类
public class MainActivity extends AppCompatActivity { private String TAG = MainActivity.class.getSimpleName(); private GLSurfaceView glSurfaceView; TraingleRender glRender; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FrameLayout mainLayout = (FrameLayout) findViewById(R.id.activity_mainLayout); glSurfaceView = new GLSurfaceView(this); glSurfaceView.setEGLContextClientVersion(2); glRender = new TraingleRender(this); //设置背景透明 glSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT); glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); glSurfaceView.setRenderer(glRender); mainLayout.addView(glSurfaceView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } protected void onResume() { super.onResume(); glSurfaceView.onResume(); } @Override protected void onPause() { super.onPause(); glSurfaceView.onPause(); } }
TraingleRender类内容如下:
public class TraingleRender implements GLSurfaceView.Renderer { private String TAG = TraingleRender.class.getSimpleName(); private int traingleProgramId; private int traingleVerticesId; private int traingleColorId; Context context; Triangle triangle; public TraingleRender(Context context){ this.context = context; } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { triangle = new Triangle(context); initRender(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { glViewport(0,0,width,height); } @Override public void onDrawFrame(GL10 gl) { triangle.draw(traingleProgramId,traingleVerticesId,traingleColorId); } public void initRender(){ String verticesShader = OpenglHelper.readShaderTextFromRaw(context,R.raw.traingle_vertex_shader); String fragmentShader = OpenglHelper.readShaderTextFromRaw(context,R.raw.traingle_fragment_shader); traingleProgramId = OpenglHelper.initProgramFromShaderSrc(verticesShader,fragmentShader); traingleVerticesId = GLES20.glGetAttribLocation(traingleProgramId,"a_Position"); traingleColorId = GLES20.glGetUniformLocation(traingleProgramId,"u_Color"); } }
b.编译着色器语言。麻蛋,画个三角形还要介个?还好可以写到static函数里重用。在res下创建raw文件夹,在raw下创建traingle_vertex_shader.glsl和traingle_fragment_shader.glsl文件,两个文件内容如下:
traingle_vertex_shader.glsl:
attribute vec4 a_Position; void main() { gl_Position = a_Position; }
traingle_fragment_shader.glsl:
precision mediump float; uniform vec4 u_Color; void main() { gl_FragColor = u_Color; }
然后用用我们的Util编译,此处叫OpenglHelper,内容如下:
public class OpenglHelper { private static String TAG = OpenglHelper.class.getSimpleName(); public static String readShaderTextFromRaw(Context context, int resourceId) { StringBuilder body = new StringBuilder(); try { InputStream inputStream = context.getResources().openRawResource(resourceId); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String nextLine; while ((nextLine = bufferedReader.readLine()) != null) { body.append(nextLine); body.append('\n'); } } catch (IOException e) { throw new RuntimeException( "Could not open resource: " + resourceId, e); } catch (Resources.NotFoundException nfe) { throw new RuntimeException("Resource not found: " + resourceId, nfe); } return body.toString(); } private static int compileShader(int type, String shaderCode) { final int shaderId = glCreateShader(type); if (shaderId == 0) { Log.w(TAG, "Could not create new shader."); return 0; } glShaderSource(shaderId, shaderCode); glCompileShader(shaderId); final int[] compileStatus = new int[1]; glGetShaderiv(shaderId, GL_COMPILE_STATUS, compileStatus, 0); if (compileStatus[0] == 0) { // If it failed, delete the shader object. glDeleteShader(shaderId); Log.w(TAG, "Compilation of shader failed."); return 0; } return shaderId; } public static int initProgramFromShaderSrc(String vertexShaderSrc, String fragmentShaderSrc) { int vertShader = compileShader(GL_VERTEX_SHADER, vertexShaderSrc); int fragShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSrc); if (vertShader == 0 || fragShader == 0) return 0; int program = GLES20.glCreateProgram(); if (program != 0) { GLES20.glAttachShader(program, vertShader); checkGLError("glAttchShader(vert)"); GLES20.glAttachShader(program, fragShader); checkGLError("glAttchShader(frag)"); GLES20.glLinkProgram(program); int[] glStatusVar = {GLES20.GL_FALSE}; GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, glStatusVar, 0); if (glStatusVar[0] == GLES20.GL_FALSE) { Log.e( TAG, "Could NOT link program : " + GLES20.glGetProgramInfoLog(program)); GLES20.glDeleteProgram(program); program = 0; } } return program; } public static void checkGLError(String op) { for (int error = GLES20.glGetError(); error != 0; error = GLES20 .glGetError()) Log.e( TAG, "After operation " + op + " got glError 0x" + Integer.toHexString(error)); } public static Buffer fillFloatBuffer(float[] array) { // Convert to floats because OpenGL doesnt work on doubles, and manually // casting each input value would take too much time. ByteBuffer bb = ByteBuffer.allocateDirect(4 * array.length); // each float takes 4 bytes bb.order(ByteOrder.LITTLE_ENDIAN); for (float d : array) bb.putFloat(d); bb.rewind(); return bb; } public static int loadTexture(Context context, int resourceId) { final int[] textureObjectIds = new int[1]; glGenTextures(1, textureObjectIds, 0); if (textureObjectIds[0] == 0) { Log.w(TAG, "Could not generate a new OpenGL texture object."); return 0; } final BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; final Bitmap bitmap = BitmapFactory.decodeResource( context.getResources(), resourceId, options); if (bitmap == null) { Log.w(TAG, "Resource ID " + resourceId + " could not be decoded."); glDeleteTextures(1, textureObjectIds, 0); return 0; } glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); // glGenerateMipmap(GL_TEXTURE_2D); // glBindTexture(GL_TEXTURE_2D, 0); return textureObjectIds[0]; } }
c.终于可以画东西了,创建我们的Traingle.java,内容如下:
public class Triangle { private Context context; private float vertices[] = {0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f}; private Buffer verticesBuffer; public Triangle(Context context) { this.context = context; verticesBuffer = array2Buffer(vertices); } public void draw(int traingleProgramId, int traingleVerticesId, int traingleColorId) { verticesBuffer.position(0); glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glUseProgram(traingleProgramId); GLES20.glVertexAttribPointer(traingleVerticesId, 2, GLES20.GL_FLOAT, false, 0, verticesBuffer); GLES20.glEnableVertexAttribArray(traingleVerticesId); GLES20.glUniform4f(traingleColorId, 0.8f, 0.5f, 1.0f, 1.0f); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); } public static Buffer array2Buffer(float[] array) { // Convert to floats because OpenGL doesn't work on doubles, and manually // casting each input value would take too much time. // Each float takes 4 bytes ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * array.length); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); for (double d : array) byteBuffer.putFloat((float) d); byteBuffer.rewind(); return byteBuffer; } }
TraingleDemo下载链接
相关文章推荐
- OpenglES2.0 for Android:来画个三角形吧
- OpenglES2.0 for Android:来画个球吧
- OpenglES2.0 for Android:来画个矩形吧
- OpenglES2.0 for Android:来画个立方体吧
- OpenglES2.0 for Android:再谈纹理映射
- ArcGIS for Android入门程序之DrawTool2.0
- OpenglES2.0 for Android:各种变换来一波
- OpenglES2.0 for Android:来做个地球吧
- OpenglES2.0 for Android:来画个圆吧
- 【技术直通车】ArcGIS for Android入门程序之DrawTool2.0
- OpenglES2.0 for Android:第一个OpenglES应用
- OpenglES2.0 for Android:纹理映射
- Google.Android开发入门与实践-学习笔记1
- Castle Active Record for .NET2.0快速入门示例
- Android开发入门学习笔记之二
- Castle Active Record for .NET2.0快速入门示例
- Castle Active Record for .NET2.0快速入门示例
- ArcGIS API for Silverlight 入门学习笔记(一):hello world
- Android 开发笔记——环境入门
- ArcGIS API for Silverlight 入门学习笔记(三):基础地图实例