android opengl es 2.0 draw circle
16lz
2021-01-26
Android Opengl es 2.0 画圆,网上说原理的文章挺多的,但要么是1.0的实现,要么无法跑起来。发现一个可以跑起来的方案:http://www.java2s.com/Open-Source/Android_Free_Code/OpenGL/Shape/mkabatek_androidOpenGLShapes.htm。在此记录一下。
原文中由于没有进行坐标转换,所以画出来的圆不是正圆,下面的代码对此进行了更正。当然,你也可以用其他方式变换,比如:http://androidblog.reindustries.com/a-real-open-gl-es-2-0-2d-tutorial-part-1/上面的变换方式。
主要类如下:
Circle.java:
import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.opengl.GLES20;import android.util.Log;public class Circle { static final int COORDS_PER_VERTEX = 3; private int mProgram, mPositionHandle, mColorHandle, mMVPMatrixHandle; private FloatBuffer vertexBuffer; private float vertices[]; float color[] = {0.00f, 0.76953125f, 0.22265625f, 1.0f}; private final int vertexCount = 364 * 3 / COORDS_PER_VERTEX; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex private final String vertexShaderCode ="attribute vec4 vPosition;" + "uniform mat4 uMVPMatrix;" + "void main() {" + " gl_Position = uMVPMatrix * vPosition;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; public Circle() { int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); vertices = new float[364 * 3]; vertices[0] = 0; vertices[1] = 0; vertices[2] = 0; for (int i =1; i <364; i++){ vertices[(i * 3)+ 0] = (float) (0.5 * Math.cos((3.14/180) * (float)i )); vertices[(i * 3)+ 1] = (float) (0.5 * Math.sin((3.14/180) * (float)i )); vertices[(i * 3)+ 2] = 0; } Log.v("Thread", "" + vertices[0] + "," + vertices[1] + "," + vertices[2]); ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); vertexByteBuffer.order(ByteOrder.nativeOrder()); vertexBuffer = vertexByteBuffer.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program GLES20.glLinkProgram(mProgram); } public void draw(float[] mvpMatrix) { // Add program to OpenGL ES environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color, 0); mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); // Draw the circle GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); }}
MyGLRenderer.java
import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import android.opengl.Matrix;import android.util.Log;public class MyGLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "MyGLRenderer"; // initialize a circle Circle mCircle; //Our screenresolution float mScreenWidth = 1920; float mScreenHeight = 1080; // mMVPMatrix is an abbreviation for "Model View Projection Matrix" private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16]; public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Set the background frame color GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); mCircle = new Circle(); } public void onDrawFrame(GL10 unused) { // Redraw background color GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); mCircle.draw(mMVPMatrix); } public void onSurfaceChanged(GL10 unused, int width, int height) { mScreenWidth = width; mScreenHeight = height; GLES20.glViewport(0, 0, width, height); // Clear our matrices for (int i = 0; i < 16; i++) { mProjectionMatrix[i] = 0.0f; mViewMatrix[i] = 0.0f; mMVPMatrix[i] = 0.0f; } float ratio = (float) width / height; // 在onDrawFrame()方法中,将投影矩阵应用到对象的坐标 Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); // Set the camera position (View matrix) Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); // Calculate the projection and view transformation Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); } public static int loadShader(int type, String shaderCode) { // create a vertex shader type (GLES20.GL_VERTEX_SHADER) // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) int shader = GLES20.glCreateShader(type); // add the source code to the shader and compile it GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } public static void checkGlError(String glOperation) { int error; while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { Log.e(TAG, glOperation + ": glError " + error); throw new RuntimeException(glOperation + ": glError " + error); } }}
如果坐标变换变为下面这样:
// Setup our screen width and height for normal sprite translation. Matrix.orthoM(mProjectionMatrix, 0, 0f, width, 0.0f, height, 0, 50); // Set the camera position (View matrix) Matrix.setLookAtM(mViewMatrix, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); // Calculate the projection and view transformation Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
则只需将vertices初始化的代码变为下面这样即可:
vertices = new float[364 * 3]; int x = 540,y=960,r=200; for (int i =0; i <364; i++){ vertices[(i * 3)+ 0] = (float) (Math.cos((3.14/180) * (float)i )) * r +x; vertices[(i * 3)+ 1] = (float) (Math.sin((3.14/180) * (float)i )) * r + y; vertices[(i * 3)+ 2] = 0; }
如果要画空心圆,只需将
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount);
变为:
GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, vertexCount);//空心
即可。
更多相关文章
- [置顶] Android百度地图SDK 导航SDK2.0结合定位SDK6.0.5的导航参
- Android-Opengl 实现图片滤镜功能
- DDMS
- view中显示部分区域
- Android(安卓)点击View Rotate旋转带视图动画
- Android(安卓)图片与屏幕坐标点
- android 自动化测试之MonkeyRunner学习(二)
- android 线段与矩形碰撞检测
- android图片的打开和缩放时出现oom处理过程