OpenGL ES 2.0結合着色器開發

1.步驟
1.1創建GLSurfaceView實例
1.2檢查系統是否支持opengl es2.0
1.3爲opengl es2.0配置渲染表面(即創建自定義渲染器,主要的相關操作都在此處進行)
1.4.顯示GLSurfaceView
1.5.Acticity生命週期與GLSurfaceView同步
2.eclipse設置靜態導入(static import)
因爲調用2.0版本相關函數都是採用靜態方式,使用靜態導入可以減少了冗長的代碼。設置如圖所示
這裏寫圖片描述
3.引入Opengl管道
我們操作的數據(頂點數據或顏色數據)複製到了OpenGL可以存取的本地內存;在顯示到屏幕上之前,它需要在OpenGL的管道中傳遞,這就需要使用着色器(shader)的子例程。這些着色器會告訴圖形處理單元(GPU)如何繪製數據。
3.1頂點着色器(vertex shader)生成每個頂點的最終位置,針對每個頂點,它都會執行一次;一旦最終位置確定了,OpenGL就可以把這些可見頂點的集合組裝成點、直線、以及三角形。
3.2片段着色器(fragment shader)爲組成點、直線或者三角形的每個片段生成最終的顏色,針對每個片段,它都會執行一次;一個片段是一個小的、單一顏色的長方形區域,類似於計算機屏幕上的一個像素。
一旦最後的顏色生成了,OpenGL就會把他們寫到一塊稱爲幀緩衝區(frame buffer)的內存中,然後,android會把這個幀緩衝區顯示在屏幕上。
3.3OpenGL管道概述:讀取頂點數據->執行頂點着色器->組裝圖元->光柵化圖元->執行片段着色器->寫入幀緩衝區->顯示在屏幕上
4.着色器源碼

//頂點着色器/res/raw/simple_vertex_shader.glsl
attribute vec4 a_Position;

void main()
{
    gl_Position = a_Position;
    gl_PointSize = 10.0;
}
//片段着色器/res/raw/simple_fragment_shader.glsl
//precision爲精度限定符:可以選擇lowp、mediump、highp;頂點着色器默認爲hitghp
precision mediump float;

uniform vec4 u_Color;

void main()
{
    gl_FragColor = u_Color;
}

5.自定義渲染器源碼

package com.example.firstopengl;

import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_LINES;
import static android.opengl.GLES20.GL_POINTS;
import static android.opengl.GLES20.GL_TRIANGLES;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUniform4f;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import static android.opengl.GLES20.glViewport;

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

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;

public class MyRenderer implements Renderer {
    private final Context context;
    private static final int POSITION_COMPINENT_COUNT = 2;// 座標xy2個值
    private static final int BYTES_PER_FLOAT = 4;// float類型由4個byte構成
    private final FloatBuffer vertexData;// 本地系統存儲點的數據
    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;

    public MyRenderer(Context context) {
        // TODO Auto-generated constructor stub
        this.context = context;
        // 三角形的捲曲順序:逆時針描點,指出物體前後區分(即前面物體會擋住後面物體)
        //屏幕座標:左下角(-1,-1),右下角(1,-1),右上角(1,1),左上角(-1,1),中心點(0,0)
        float[] datas = {
                // table
                -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,

                -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,

                // line
                -0.5f, 0.0f, 0.5f, 0.0f,

                // mallets
                0.0f, -0.25f, 0.0f, 0.25f };

        //吧內存從java堆複製到本地堆,因爲opengl是在本地系統操作的
        //申請本地系統內存
        vertexData = ByteBuffer.allocateDirect(datas.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //賦值
        vertexData.put(datas);
    }

    // 繪製每一幀時,GLSurfaceView調用(suface創建後)
    @Override
    public void onDrawFrame(GL10 gl) {
        // TODO Auto-generated method stub
        // 清除屏幕顏色
        glClear(GL_COLOR_BUFFER_BIT);

        // 繪製table
        glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        // 繪製分割線
        glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
        glDrawArrays(GL_LINES, 6, 2);
        // 繪製藍色的mallet
        glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
        glDrawArrays(GL_POINTS, 8, 1);
        // 繪製紅色的mallet
        glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
        glDrawArrays(GL_POINTS, 9, 1);

    }

    // suface視圖大小改變時,GLSurfaceView調用(suface創建後)
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // TODO Auto-generated method stub
        // 設置視圖大小
        glViewport(0, 0, width, height);
    }

    // suface創建時,GLSurfaceView調用
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // TODO Auto-generated method stub
        // 清空屏幕的顏色
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        // 頂點着色器與片段着色器代碼
        String vertexShaderSoure = TRReader.readTFfromRes(context, R.raw.simple_vertex_shader);
        String fragmentShaderSoure = TRReader.readTFfromRes(context, R.raw.simple_fragment_shader);
        // 獲取對對應着色器
        int vertexShader = ShaderHelper.conpileVertexShader(vertexShaderSoure);
        int fragmentShader = ShaderHelper.conpileFragmentShader(fragmentShaderSoure);
        program = ShaderHelper.linkProgram(vertexShader, fragmentShader);
        if (LoggerConfig.ON) {
            ShaderHelper.validateProgram(program);
        }
        //使用自定義的程序
        glUseProgram(program);
        // 獲得uniform與attribute位置
        uColorLocation = glGetUniformLocation(program, U_COLOR);
        aPositionLocation = glGetAttribLocation(program, A_POSITION);
        // 關聯頂點屬性
        vertexData.position(0);
        glVertexAttribPointer(aPositionLocation, // 屬性位置
                POSITION_COMPINENT_COUNT, // 頂點參數個數
                GL_FLOAT, // 頂點數據類型
                false, // 整型數據纔有意義
                0, // 多餘一個屬性纔有意義
                vertexData);// 數據內存
        // 使能頂點數組
        glEnableVertexAttribArray(aPositionLocation);

    }

}

6.工程源碼:https://github.com/HQlin/ShaderOpenGL

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章