天天看点

Android OpenGL 从0开始搭建

后面补充,先上代码:

Android OpenGL 从0开始搭建

MainActvity:

public class MainActivity extends AppCompatActivity {

    private GLSurfaceView glSurfaceView;
    private ActivityManager am;
    private boolean rendererSet;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        glSurfaceView = new GLSurfaceView(this);

        am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        boolean supportES2 = am.getDeviceConfigurationInfo().reqGlEsVersion >= 2000;
        if (!supportES2) {
            Toast.makeText(this, "This device does not support ES 2.0"
                    , Toast.LENGTH_SHORT).show();
            return;

        }
        glSurfaceView.setEGLContextClientVersion(2);
        rendererSet = true;
        setContentView(glSurfaceView);

        glSurfaceView.setRenderer(new MyGLRenderer(this));
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (rendererSet) {
            glSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (rendererSet) {
            glSurfaceView.onResume();
        }

    }
}
           
MatrixHelper:
           
public class MatrixHelper {

    public static void perspectiveM(float[] m, float yFovInDegrees, float aspect, float n, float f) {
        float angleInRadians = (float) (yFovInDegrees * Math.PI / 180.0);
        float a = (float) (1.0 / Math.tan(angleInRadians / 2.0));

        //OpenGL是按照列的方式写的,不是行的形式
        m[0] = a / aspect;
        m[1] = 0f;
        m[2] = 0f;
        m[3] = 0f;

        m[4] = 0f;
        m[5] = a;
        m[6] = 0f;
        m[7] = 0f;

        m[8] = 0f;
        m[9] = 0f;
        m[10] = -((f + n) / (f - n));
        m[11] = -1f;

        m[12] = 0f;
        m[13] = 0f;
        m[14] = -((2f * f * n) / (f - n));
        m[15] = 0f;

    }
}
           
MyGLRenderer:
           
public class MyGLRenderer implements GLSurfaceView.Renderer {


    /* private float[] tableVerticesWidthTriangles = {
             //三角形1
             0f, 0f,
             9f, 14f,
             0f, 14f,

             //三角形2
             0f, 0f,
             9f, 0f,
             9f, 14f,

             //直线
             0f, 7f,
             9f, 7f,

             //mallets
             4.5f, 2f,
             4.5f, 12f
     };*/
    private float[] tableVerticesWidthTriangles = {
            //三角形1
//            -0.5f, -0.5f,
//            0.5f, 0.5f,
//            -0.5f, 0.5f,
//
//            //三角形2
//            -0.5f, -0.5f,
//            0.5f, -0.5f,
//            0.5f, 0.5f,

//            三角形扇,带有z和w
//            0f, 0f, 0f, 1.5f, 1f, 1f, 1f,
//            -0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
//            0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
//            0.5f, 0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
//            -0.5f, 0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
//            -0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
//
//            //直线
//            -0.5f, 0f, 0f, 1.5f,  1f, 0f, 0f,
//            0.5f, 0f, 0f,  1.5f, 1f, 0f, 0f,
//
//            //mallets
//            0f, -0.4f, 0f,  1.25f, 0f, 0f, 1f,
//            0f, 0.4f, 0f, 1.75f,  1f, 0f, 0f

            //三角形扇
            0f, 0f, 1f, 1f, 1f,
            -0.5f, -0.8f, 0.7f, 0.7f, 0.7f,
            0.5f, -0.8f, 0.7f, 0.7f, 0.7f,
            0.5f, 0.8f, 0.7f, 0.7f, 0.7f,
            -0.5f, 0.8f, 0.7f, 0.7f, 0.7f,
            -0.5f, -0.8f, 0.7f, 0.7f, 0.7f,

            //直线
            -0.5f, 0f, 1f, 0f, 0f,
            0.5f, 0f, 1f, 0f, 0f,

            //mallets
            0f, -0.4f, 0f, 0f, 1f,
            0f, 0.4f, 1f, 0f, 0f
    };

    private static final int BYTES_PER_FLOAT = 4;
    private FloatBuffer vertexData;
    private final Context mContext;
    private int program;
    //    private static final String U_COLOR = "u_Color";
//    private int uColorLocation;
    private static final String A_POSITION = "a_Position";
    private int aPositionLocation;
    private static final int POSITION_COMPONENT_COUNT = 2;
//    private static final int POSITION_COMPONENT_COUNT = 4;

    private static final String A_COLOR = "a_Color";
    private static final int COLOR_COMPONENT_COUNT = 3;
    private static final int STRIDE = (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;
    private int aColorLocation;

    private static final String U_MATRIX = "u_Matrix";
    private final float[] projectionMatrix = new float[16];
    private int uMatrixLocation;

    private final float[] modelMatrix = new float[16];


    public MyGLRenderer(Context context) {
        mContext = context;
        vertexData = ByteBuffer
                .allocateDirect(tableVerticesWidthTriangles.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexData.put(tableVerticesWidthTriangles);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        String vertexShaderSource = TextResourceReader.readTextFileFromResource(mContext, R.raw.simple_vertex_shader);
        String fragmentShaderSource = TextResourceReader.readTextFileFromResource(mContext, R.raw.simple_fragment_shader);
        int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);
        int fragmentShader = ShaderHelper.compileFragmentShader(fragmentShaderSource);

        program = ShaderHelper.linkProgram(vertexShader, fragmentShader);

        ShaderHelper.validateProgram(program);//验证program

        glUseProgram(program);

//        uColorLocation = glGetUniformLocation(program, U_COLOR);//获取uniform位置
        aColorLocation = glGetAttribLocation(program, A_COLOR);//获取新属性位置
        aPositionLocation = glGetAttribLocation(program, A_POSITION);
        uMatrixLocation = glGetUniformLocation(program, U_MATRIX);

        //关联属性与顶点数据的数组
        vertexData.position(0);//从数据开头读取位置
//        glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0, vertexData);//
        glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, vertexData);//

        glEnableVertexAttribArray(aPositionLocation);// 使顶点数组可用

        vertexData.position(POSITION_COMPONENT_COUNT);//从第三位开始读取颜色
        glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, vertexData);//
        glEnableVertexAttribArray(aColorLocation);// 使顶点数组可用

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        glViewport(0, 0, width, height);//设置视图尺寸
//        final float aspectRatio = width > height ?
//                (float) width / (float) height :
//                (float) height / (float) width;
//        if (width > height) {
//            Matrix.orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1f, 1f, -1f, 1f);
//        } else {
//            Matrix.orthoM(projectionMatrix, 0, -1f, 1f, -aspectRatio, aspectRatio, -1f, 1f);
//        }

//        Matrix.perspectiveM(projectionMatrix, 0, 45, (float) width / (float) height, 1f, 10f);
        MatrixHelper.perspectiveM(projectionMatrix, 45f, (float) width / (float) height, 1f, 10f);

        //        利用模型矩阵平移物体
        Matrix.setIdentityM(modelMatrix, 0);
        Matrix.translateM(modelMatrix, 0, 0f, 0f, -2f);

        //绕X轴旋转桌子
        Matrix.translateM(modelMatrix, 0, 0f, 0f, -2.5f);
        Matrix.rotateM(modelMatrix, 0, -60f, 1f, 0f, 0f);

        final float[] temp = new float[16];//用来存矩阵相乘临时结果
        Matrix.multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
        System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);//将计算结果拷贝回projectionMatrix



    }

    @Override
    public void onDrawFrame(GL10 gl) {
        glClear(GL_COLOR_BUFFER_BIT);
        glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);

//        //绘制桌子
//        glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
//        glDrawArrays(GL_TRIANGLES, 0, 6);

        //三角形扇的形式绘制桌子
//        glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

        //绘制直线
//        glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
        glDrawArrays(GL_LINES, 6, 2);

        //绘制木槌1
//        glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
        glDrawArrays(GL_POINTS, 8, 1);

        //绘制木槌2
//        glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
        glDrawArrays(GL_POINTS, 9, 1);
    }


}
           
ShaderHelper:
           
public class ShaderHelper {

    private static String TAG = "ShaderHelper";

    public static int compileVertexShader(String shaderCode) {
        return compileShader(GL_VERTEX_SHADER, shaderCode);
    }

    public static int compileFragmentShader(String shaderCode) {
        return compileShader(GL_FRAGMENT_SHADER, shaderCode);
    }

    public static int compileShader(int type, String shaderCode) {
        int shaderObjectId = glCreateShader(type);
        if (shaderObjectId == 0) {
            Log.w(TAG, "could not create new shader! ");
            return 0;
        }

        glShaderSource(shaderObjectId, shaderCode);
        glCompileShader(shaderObjectId);

        final int[] compileStatus = new int[1];
        glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0);

        Log.w(TAG, "Results of compile source: \n" + shaderCode + "\n"
                + glGetShaderInfoLog(shaderObjectId));

        if (compileStatus[0] == 0) {
            Log.w(TAG, "compilation of shader failed!");

            //if it failed, delete the shader object.
            glDeleteShader(shaderObjectId);
            return 0;
        }
        return shaderObjectId;
    }

    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
        int programObjectId = glCreateProgram();
        if (programObjectId == 0) {
            Log.w(TAG, "Could not create a new program!");
            return 0;
        }

        glAttachShader(programObjectId, vertexShaderId);
        glAttachShader(programObjectId, fragmentShaderId);
        glLinkProgram(programObjectId);

        final int[] linkStatus = new int[1];
        glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0);

        Log.w(TAG, "Results of link program: \n"
                + glGetProgramInfoLog(programObjectId));

        if (linkStatus[0] == 0) {
            Log.w(TAG, "linking of program failed!");

            //if it failed, delete the program object.
            glDeleteProgram(programObjectId);
            return 0;
        }
        return programObjectId;
    }

    public static boolean validateProgram(int programObjectId) {
        glValidateProgram(programObjectId);

        final int[] validateStatus = new int[1];
        glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0);

        Log.w(TAG, "Results of validating program: " + validateStatus[0]
                + "\nLog: " + glGetProgramInfoLog(programObjectId));

        return validateStatus[0] != 0;

    }

}
           
TextResourceReader:
           
public class TextResourceReader {
    public static String readTextFileFromResource(Context context, int resId) {
        StringBuffer body = new StringBuffer();
        try {
            InputStream inputStream = context.getResources().openRawResource(resId);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                body.append(line);
                body.append("\n");
            }
        } catch (IOException e) {
            throw new RuntimeException("could not open resource: " + resId, e);
        } catch (Resources.NotFoundException e) {
            throw new RuntimeException("resource not found: " + resId, e);
        }
        return body.toString();
    }
}
           

simple_fragment_shader.glsl:

precision mediump float;
uniform vec4 u_Color;
varying vec4 v_Color;
void main()
{
    //    gl_FragColor = u_Color;
    gl_FragColor = v_Color;
}
           

simple_vertex_shader.glsl:

uniform mat4 u_Matrix;

attribute vec4 a_Position;
attribute vec4 a_Color;

varying vec4 v_Color;
void main()
{
    v_Color = a_Color;

    //    gl_Position = a_Position;
    gl_Position = u_Matrix * a_Position;
    gl_PointSize = 10.0;//指定点的大小
}
           

继续阅读