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

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