当前位置:网站首页>First knowledge of OpenGL es learning (1)

First knowledge of OpenGL es learning (1)

2022-07-06 07:05:00 Unlimited exchange

1. know OpenGL ES

OpenGL It's cross platform 2D/3D graphics API, and OpenGL ES It is an extended version based on the former , Suitable for embedded devices such as mobile phones . It has the following versions :

edition explain
OpenGL ES 1.02003 Released in
OpenGL ES 1.1 Supports multiple textures , Vertex buffer object, etc
OpenGL ES 2.02007 Released in , be based on OpenGL 2.0, Deleted 1.x Fixed pipeline in (pipeline), Provide programmable pipelines
OpenGL ES 3.02012 Released in , Backward compatibility 2.x
OpenGL ES 3.12014 Released in
OpenGL ES 3.22015 Released in

OpenGL ES 1.x and OpenGL ES2.0 Incompatible , Are two completely different implementations .

  • OpenGL EX 1.x Only fixed pipeline rendering is supported , It can be firmware support or software emulation , But the rendering ability is limited .

  • OpenGL EX 2.X Using programmable rendering pipeline , Improved rendering ability . But the difficulty of programming has also increased , And it is required that there must be corresponding GPU Hardware support .
     Picture source Android3D Game development technology dictionary  Picture source Android3D Game development technology dictionary
    The above figure 3-16 Sum graph 3-21 Namely OpenGL 1.x and OpenGL 2.x Rendering pipeline process diagram .

  • “ Transform and lighting ”---->“ Vertex shader ”

  • “ Texture environment and color summation ”、“ Fog ”、“Alpha velocity measurement ”---->“ Chip shader ”

This series will focus on OpenGL ES2.x

2. First time to know OpenGL ES2.x Program appearance

I'm getting to know you OpenGL ES After the foundation , Here is an entry level Demo( The official website of this program also has similar learning ). Comments have been added to the code , It can better help you get started .

2.1 design sketch

 Insert picture description here

2.2 Tool class ShaderUtil.java

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

    /**
     *  Load shaders encoded into GPU And compile 
     *
     * @param shaderType  Shader type 
     * @param source      Shader script string 
     * @return
     */
    public static int loadShader(int shaderType, String source) {
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            GLES20.glShaderSource(shader, source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                Log.e(TAG, "loadShader: ES20_ERROR,Could not compile shader " + shaderType + ";");
                Log.e(TAG, "loadShader: ES20_ERROR,shader = " + GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }

    /**
     *  Create shader program 
     *
     * @param vertexSource
     * @param fragmentSource
     * @return
     */
    public static int createProgram(String vertexSource, String fragmentSource) {
        // Load vertex shaders 
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }

        // Load the slice shader 
        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (pixelShader == 0) {
            return 0;
        }
        int program = GLES20.glCreateProgram();
        if (program != 0) {
            GLES20.glAttachShader(program, vertexShader);
            checkGLError("glAttachShader");
            GLES20.glAttachShader(program, pixelShader);
            checkGLError("glAttachShader");
            GLES20.glLinkProgram(program);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                Log.e(TAG, "createProgram: ES20_ERROR,Could not link program");
                Log.e(TAG, "createProgram: ES20_ERROR,program = " + GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }

    /**
     *  Check whether there is a wrong method in each operation 
     *
     * @param op
     */
    public static void checkGLError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.d(TAG, ">>>>>> " + op + " :glError " + error);
            throw new RuntimeException(op + ":glError " + error);
        }
    }

    /**
     *  from sh Load shader contents in the script 
     *
     * @param fname
     * @param resources
     * @return
     */
    public static String loadFromAssetsFile(String fname, Resources resources) {
        String result = null;
        try {
            InputStream in = resources.getAssets().open(fname);
            int ch = 0;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((ch = in.read()) != -1) {
                baos.write(ch);// The obtained information is written to the stream 
            }
            byte[] buffer = baos.toByteArray();
            baos.close();
            in.close();
            result = new String(buffer, "UTF-8");
            result = result.replaceAll("\\r\\n", "\n");


        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "loadFromAssetsFile: result = " + result);
        return result;
    }


}

2.3 triangle Triangle

public class Triangle {
    public static float[] mProjMatrix = new float[16];//4x4 Projection matrix 
    public static float[] mVMatrix = new float[16];// Parameter matrix of camera position orientation 
    public static float[] mMvPMatrix;// Total transformation matrix 
    private int program;// Custom render pipeline shader program id
    private int muMVPMatrixHandle;// Total transformation matrix reference 
    private int maPositionHandle;// Vertex position attribute reference 
    private int maColorHandle;// Vertex color attribute reference 
    private String mVertexShader;// Vertex shader code script 
    private String mFragmentShader;// Fragment shader code script 
    private static float[] mMMatrix = new float[16];// Specific objects 3D Transformation matrix , Including rotation 、 translation 、 The zoom 
    private FloatBuffer mVertexBuffer;// Vertex coordinate data buffer 
    private FloatBuffer mColorBuffer;// Vertex shading data buffer 
    private int vCount = 0;// Number of vertices 
    public float xAngle = 0;// Around the X Angle of axis rotation 

    public Triangle(MyTDView myTDView) {
        initVertexData();
        initShader(myTDView);
    }

    /**
     *  Initialize shaders 
     * @param myTDView
     */
    private void initShader(MyTDView myTDView) {
        mVertexShader = ShaderUtil.loadFromAssetsFile("vertex.sh", myTDView.getResources());
        mFragmentShader = ShaderUtil.loadFromAssetsFile("frag.sh", myTDView.getResources());
        program = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
        maPositionHandle = GLES20.glGetAttribLocation(program, "aPosition");
        maColorHandle = GLES20.glGetAttribLocation(program, "aColor");
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
    }

    /**
     *  Draw triangle 
     */
    public void drawSelf() {
        GLES20.glUseProgram(program);
        Matrix.setRotateM(mMMatrix, 0, 0, 0, 1, 0);// Initialize the transformation matrix 
        Matrix.translateM(mMMatrix, 0, 0, 0, 1);// Set along Z Positive displacement of shaft 
        Matrix.rotateM(mMMatrix, 0, xAngle, 1, 0, 0);// Set winding X Shaft rotation 
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, Triangle.getFinalMatrix(mMMatrix), 0);
        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, mVertexBuffer);
        GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4 * 4, mColorBuffer);
        GLES20.glEnableVertexAttribArray(maPositionHandle);
        GLES20.glEnableVertexAttribArray(maColorHandle);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
    }

    /**
     *  Initialize vertex data 
     */
    private void initVertexData() {
        vCount = 3;
        final float UNIT_SIZE = 0.2f;// Set unit length 
        // An array of vertex coordinates 
        float vertices[] = new float[]{
                -4 * UNIT_SIZE, 0, 0,
                0, -4 * UNIT_SIZE, 0,
                4 * UNIT_SIZE, 0, 0
        };
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder());// Set byte order to local operating system order 
        mVertexBuffer = vbb.asFloatBuffer();// Convert to floating-point buffer 
        mVertexBuffer.put(vertices);// Write data in the buffer 
        mVertexBuffer.position(0);// Set buffer start position 

        // Vertex color array 
        float colors[] = new float[]{
                1, 1, 1, 0,
                0, 0, 1, 0,
                0, 1, 0, 0
        };
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
        cbb.order(ByteOrder.nativeOrder());
        mColorBuffer = cbb.asFloatBuffer();
        mColorBuffer.put(colors);
        mColorBuffer.position(0);
    }

    /**
     *  The final transformation matrix 
     *
     * @param spec
     * @return
     */
    public static float[] getFinalMatrix(float[] spec) {
        // Initialize the total transformation matrix 
        mMvPMatrix = new float[16];
        Matrix.multiplyMM(mMvPMatrix, 0, mVMatrix, 0, spec, 0);
        Matrix.multiplyMM(mMvPMatrix, 0, mProjMatrix, 0, mMvPMatrix, 0);
        return mMvPMatrix;
    }
}

2.4 Rendering class MyTDView

GLSurfaceView and GLSurfaceView.Render Use

public class MyTDView extends GLSurfaceView {
    private static final String TAG = "MyTDView";
    // The angle of each triangle rotation 
    private final float ANGLE_SPAN = 0.375f;
    // Threads 
    private RotateThread mRotateThread;
    // Custom renderer 
    private SceneRenderer mSceneRenderer;


    public MyTDView(Context context) {
        super(context);
        // Use OpenGLES2.0
        this.setEGLContextClientVersion(2);
        mSceneRenderer = new SceneRenderer();
        this.setRenderer(mSceneRenderer);
        this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }


    private class SceneRenderer implements GLSurfaceView.Renderer {
        Triangle mTriangle;

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            GLES20.glClearColor(0, 0, 0, 1.0f);// Set the screen background color 
            mTriangle = new Triangle(MyTDView.this);
            GLES20.glEnable(GLES20.GL_DEPTH_TEST);
            mRotateThread = new RotateThread();
            mRotateThread.start();

        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GLES20.glViewport(0, 0, width, height);// Set up the viewport 
            float ratio = width / height;
            // Set perspective projection 
            Matrix.frustumM(Triangle.mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 10);
            // Set up the camera 
            Matrix.setLookAtM(Triangle.mVMatrix, 0, 0, 0, 3,
                    0f, 0f, 0f, 0f, 1.0f, 0.0f);


        }

        @Override
        public void onDrawFrame(GL10 gl) {
            GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
            mTriangle.drawSelf();
        }
    }

    private class RotateThread extends Thread {
        // Set the cycle identification bit 
        public boolean flag = true;

        @Override
        public void run() {
            super.run();
            while (flag) {
                mSceneRenderer.mTriangle.xAngle = mSceneRenderer.mTriangle.xAngle + ANGLE_SPAN;
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

2.5 Vertex shader and slice shader code

Vertex shader and slice shader resources are placed in assets Under the table of contents . The following is used in this case :

2.5.1 frag.sh

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

2.5.2 vertex.sh Vertex shader

uniform mat4 uMVPMatrix;// Total transformation matrix 
attribute vec3 aPosition;// Vertex Position 
attribute vec4 aColor;// Vertex color 
varying vec4 vColor;// Mutable variables passed to the slice shader 
void main(){
    gl_Position = uMVPMatrix * vec4(aPosition,1);// Calculate the position of the vertex drawn this time according to the total transformation matrix 
    vColor = aColor;
}

2.6 other

public class MainActivity extends AppCompatActivity {
    private MyTDView mTDView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        mTDView = new MyTDView(this);
        mTDView.requestFocus();
        mTDView.setFocusableInTouchMode(true);
        setContentView(mTDView);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mTDView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mTDView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

    }
}

This sample program can be run directly , See the effect .

【 Reference resources 】

  1. https://www.khronos.org/opengles/
  2. 《OpenGL ES Application development practice guide Android volume Kevin Brothaler》
  3. https://en.wikipedia.org/wiki/OpenGL_ES
  4. https://developer.android.google.cn/guide/topics/graphics/opengl
  5. https://developer.android.google.cn/training/graphics/opengl
  6. Android3D Game development technology dictionary OpenGL ES 2.0
原网站

版权声明
本文为[Unlimited exchange]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060701338365.html