Android OpenGLES 绘制三角形 ,四边形

时间:2022-06-10
本文章向大家介绍Android OpenGLES 绘制三角形 ,四边形,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
  1. 验证是否支持OpenGLES2.0
//检查设备是否支持OpenGL ES 2.0
final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
final boolean supportES2 = configurationInfo.reqGlEsVersion >= 0x00020000;

确保可用,在manifest里面添加验证

<uses-feature android:glEsVersion="0x00020000" android:required="true" />
  1. 定义vertex_shader.glslfragment_shader.glslres/raw里面

vertex_shader.glsl

attribute vec4 vPosition;
void main(){
    gl_Position = vPosition;
}

fragment_shader.glsl

precision mediump float;
uniform vec4 vColor;
void main(){
    gl_FragColor = vColor;
}

OpenGL ES Shader的三种变量类型uniform,attribute和varying

  1. 定义形状
import android.content.Context;
import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class Triangle {

    //坐标本地内存地址
    private FloatBuffer vertexBuffer;

    //每一次取点的时候取几个点
    static final int COORDS_PER_VERTEX = 3;

    //绘制坐标
    static float triangleCoords[] = {   // in counterclockwise order:
            0.0f, 0.622008459f, 0.0f, // top
            -0.5f, -0.311004243f, 0.0f, // bottom left
            0.5f, -0.311004243f, 0.0f  // bottom right
    };

    // Set color with red, green, blue and alpha (opacity) values
    float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};


    private final int mProgram;

    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

    public Triangle(Context context) {
        //为坐标分配本地内存地址
        vertexBuffer = ByteBuffer
                .allocateDirect(triangleCoords.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(triangleCoords);
        vertexBuffer.position(0);

        //根据shader代码和fragment代码 获取到一个渲染程序
        mProgram = ShaderUtil.createProgram(ShaderUtil.readRawTxt(context, R.raw.vertex_shader),
                ShaderUtil.readRawTxt(context, R.raw.fragment_shader));
        if (mProgram > 0) {
            //获取vertex shader的属性vPosition 的地址
            mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
            //获取fragment shader的属性vColor 的地址
            mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        }
    }


    public void draw() {
        //使用渲染程序
        GLES20.glUseProgram(mProgram);

        // 使顶点属性数组有效
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        // 为顶点属性赋值
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        // 设置颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        // 绘制图形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

        // 禁用顶点数组
        GLES20.glDisableVertexAttribArray(mPositionHandle);

    }
}

ShaderUtil.java


import android.content.Context;
import android.opengl.GLES20;
import android.util.Log;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ShaderUtil {
    private static final String TAG = "ShaderUtil";


    public static String readRawTxt(Context context, int rawId) {
        InputStream inputStream = context.getResources().openRawResource(rawId);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer sb = new StringBuffer();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("n");
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public static int loadShader(int shaderType, String source) {
        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            //添加代码到shader
            GLES20.glShaderSource(shader, source);
            //编译shader
            GLES20.glCompileShader(shader);
            int[] compile = new int[1];
            //检测是否编译成功
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
            if (compile[0] != GLES20.GL_TRUE) {
                Log.d(TAG, "shader compile error");
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }

    public static int createProgram(String vertexSource, String fragmentSource) {
        //获取vertex shader
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }
        //获取fragment shader
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (fragmentShader == 0) {
            return 0;
        }
        //创建一个空的渲染程序
        int program = GLES20.glCreateProgram();
        if (program != 0) {
            //添加vertexShader到渲染程序
            GLES20.glAttachShader(program, vertexShader);
            //添加fragmentShader到渲染程序
            GLES20.glAttachShader(program, fragmentShader);
            //关联为可执行渲染程序
            GLES20.glLinkProgram(program);
            int[] linsStatus = new int[1];
            //检测是否关联成功
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linsStatus, 0);
            if (linsStatus[0] != GLES20.GL_TRUE) {
                Log.d(TAG, "link program error");
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;

    }

}
  1. 定义shader import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MyRender implements GLSurfaceView.Renderer { private Context context; private Triangle triangle; public MyRender(Context context) { this.context = context; } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { triangle = new Triangle(context); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { //宽高 GLES20.glViewport(0, 0, width, height); } @Override public void onDrawFrame(GL10 gl) { //清空颜色 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); //设置背景颜色 // GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); triangle.draw(); } }
  2. 设置shaderGLSurfaceView
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;

public class MyGLSurfaceView extends GLSurfaceView{

    public MyGLSurfaceView(Context context) {
        this(context, null);
    }

    public MyGLSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setEGLContextClientVersion(2);
        setRenderer(new MyRender(context));
    }
}

上述三角形已经绘制成功。

  1. 绘制四边形 绘制四边形的方式是由两个三角形形成一个四边形,所以顶点位置一定要注意。 调用GLES20.glDrawArrays的时候设置flog可以设置为GLES20.GL_TRIANGLE_STRIPGLES20.GL_TRIANGLES,前者复用坐标,后者分别取几个坐标。