Android下使用OpenGL绘制三角形
16lz
2022-05-03
在Android下图像渲染基本都用的是OpenGL ES,在使用opengl过程中需要注意几个关键点:
1、顶点着色器
2、色彩着色器
3、坐标
特别提到坐标,是因为opengl中的坐标与手机屏幕的坐标是不一致的,在使用opengl坐标时需要自己进行转换一下:
这里使用OpenGL来绘制一个三角形:
项目地址:https://github.com/tong123/OpenGLTriangle
1、使用opengl 2.0版本:
2、MainActivity.java文件:
package com.example.tongjiangsong.opengltriangle;import android.opengl.GLSurfaceView;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;public class MainActivity extends AppCompatActivity { private GLSurfaceView mGLView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGLView = new MyGLSurfaceView(this); setContentView(mGLView); }}
3、MyGLRenderer.java文件:
package com.example.tongjiangsong.opengltriangle;import android.opengl.EGLConfig;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import javax.microedition.khronos.opengles.GL10;public class MyGLRenderer implements GLSurfaceView.Renderer { private Triangle mTriangle; @Override public void onSurfaceCreated(GL10 gl, javax.microedition.khronos.egl.EGLConfig config) { GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//白色不透明 mTriangle = new Triangle(); } @Override public void onSurfaceChanged(GL10 unused, int width, int height) {//当view的几何形状发生变化时调用,比如设备屏幕方向改变时 //绘制窗口 GLES20.glViewport(0, 0, width, height); } public void onDrawFrame(GL10 unused) {//每次重绘view时调用 //重绘背景色 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); mTriangle.draw(); } public static int loadShader(int type, String shaderCode){ //创建一个vertex shader类型(GLES20.GL_VERTEX_SHADER) //或一个fragment shader类型(GLES20.GL_FRAGMENT_SHADER) int shader = GLES20.glCreateShader(type); // 将源码添加到shader并编译它 GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; }}
4、MyGLSurfaceView.java文件:
package com.example.tongjiangsong.opengltriangle;import android.content.Context;import android.opengl.EGLConfig;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import javax.microedition.khronos.opengles.GL10;class MyGLSurfaceView extends GLSurfaceView { private final MyGLRenderer mRenderer; public MyGLSurfaceView(Context context){ super(context); // 创建OpenGL ES 2.0的上下文 setEGLContextClientVersion(2); mRenderer = new MyGLRenderer(); //设置Renderer用于绘图 setRenderer(mRenderer); //只有在绘制数据改变时才绘制view,可以防止GLSurfaceView帧重绘 setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); }}
5、Triangle.java文件:
package com.example.tongjiangsong.opengltriangle;import android.opengl.GLES20;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;public class Triangle { private final String vertexShaderCode = "attribute vec4 vPosition;" + "void main() {" + " gl_Position = vPosition;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; private FloatBuffer vertexBuffer; //设置每个顶点的坐标数 static final int COORDS_PER_VERTEX = 3; //设置三角形顶点数组 static float triangleCoords[] = { //默认按逆时针方向绘制 0.0f, 1.0f, 0.0f, // 顶点 -1.0f, -0.5f, 0.0f, // 左下角 1.0f, -0.5f, 0.0f // 右下角 }; // 设置三角形颜色和透明度(r,g,b,a) float color[] = {1.0f, 1.0f, 0f, 1.0f};//绿色不透明 private int mPositionHandle; private int mColorHandle; private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex private int mProgram; public void draw() { // 添加program到OpenGL ES环境中 GLES20.glUseProgram(mProgram); // 获取指向vertex shader的成员vPosition的handle mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // 启用一个指向三角形的顶点数组的handle GLES20.glEnableVertexAttribArray(mPositionHandle); //准备三角形的坐标数据 GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // 获取指向fragment shader的成员vColor的handle mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // 绘制三角形 GLES20.glUniform4fv(mColorHandle, 1, color, 0); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // 禁用指向三角形的顶点数组 GLES20.glDisableVertexAttribArray(mPositionHandle); } public Triangle() { // 初始化顶点字节缓冲区,用于存放形状的坐标 ByteBuffer bb = ByteBuffer.allocateDirect(//(每个浮点数占用4个字节 triangleCoords.length * 4); //设置使用设备硬件的原生字节序 bb.order(ByteOrder.nativeOrder()); //从ByteBuffer中创建一个浮点缓冲区 vertexBuffer = bb.asFloatBuffer(); // 把坐标都添加到FloatBuffer中 vertexBuffer.put(triangleCoords); //设置buffer从第一个坐标开始读 vertexBuffer.position(0); // 编译shader代码 int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); // 创建空的OpenGL ES Program mProgram = GLES20.glCreateProgram(); // 将vertex shader添加到program GLES20.glAttachShader(mProgram, vertexShader); // 将fragment shader添加到program GLES20.glAttachShader(mProgram, fragmentShader); // 创建可执行的 OpenGL ES program GLES20.glLinkProgram(mProgram); }}
运行结果如下:
更多相关文章
- [原创]Android中LocationManager的简单使用,获取当前位置
- Android绘图机制与处理技巧——Android图像处理之图形特效处理
- Android(安卓)Matrix
- Android(安卓)3D 游戏开发教程– Part I-VI
- Android(安卓)svg 绘制三角形
- Android中LocationManager的简单使用,获取当前位置
- 2014-11-6Android学习------Android(安卓)仿真翻页效果实现-----
- Android中LocationManager的简单使用,获取当前位置
- Android(安卓)OpenGLES2.0(十七)——球形天空盒VR效果实现