OpenGL_ES_三角形

OpenGL ES2.0 绘制三角形

效果

这里写图片描述

public class Demo2Activity extends AppCompatActivity {
boolean isRenderSet = false;
private GLSurfaceView glSurfaceView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //判断是否支持ES2.0
    if (!isSupportES()) {
        //不支持
        Toast.makeText(this, "当前设备不支持OpenGL ES2.0", Toast.LENGTH_SHORT).show();
        LogUtil.log_d("=============当前设备不支持2.0==");
        return;
    }
    glSurfaceView = new GLSurfaceView(this);
    //必须要设置OpenGL ES的版本 否则无法使用 当然也可以在清单文件中声明
    glSurfaceView.setEGLContextClientVersion(2);
    glSurfaceView.setRenderer(new MyRender());
    isRenderSet = true;
    setContentView(glSurfaceView);

}

/**
 * 判断是否支持 Es2.0
 *
 * @return true 支持2.0
 */
public boolean isSupportES() {
    ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    ConfigurationInfo deviceConfigurationInfo = activityManager.getDeviceConfigurationInfo();
//        return deviceConfigurationInfo.reqGlEsVersion>=0x20000; 这段代码只能在真机上运行不能在模拟器上运行,为了兼容模拟器,应该写如下的代码
    return deviceConfigurationInfo.reqGlEsVersion >= 0x20000
            || (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1 && (Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.startsWith("unknown")
            || Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.MODEL.contains("Android SDK built for x86")));

}

/**
 * 绘制一个三角形
 */
class MyRender implements GLSurfaceView.Renderer {
    //记录当前顶点数据一个是有2个数据组成
    private final int VERTEX_COMPONMENT_COUNT = 2;
    private final String A_POSITION = "a_Position";
    private final String U_COLOR = "u_Color";
    //每一个float数所占的字节数量
    private final int FLOAT_PER_BYTE = 4;
    private final FloatBuffer vertexBuffer;
    private int uColorLocation;

    public MyRender() {
        //绘制三角形
        //首先定义三角形的顶点
        float[] vertexs = new float[]{
                -0.5f, -0.5f,
                0.5f, -0.5f,
                0f, 0.5f
        };
        //将float数据 转换为gpu可以读取的本地floatbuffer
        vertexBuffer = ByteBuffer.allocateDirect(vertexs.length * FLOAT_PER_BYTE)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexBuffer.put(vertexs);

    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
            //设置清屏颜色 1.0 1.0 1.0 白色
        GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
        //读取顶点着色器程序代码,
        String stringVertex = TextResourceRead.readTextFileFromResource(Demo2Activity.this, R.raw.demo2_vertex);
        //读取片段着色器程序
        String stringFragment = TextResourceRead.readTextFileFromResource(Demo2Activity.this,R.raw.demo2_fragment);
        //获取顶点着色器id
        int vertexShaderID = ShaderHelp.compileVertexShader(stringVertex);
        ///获取片段着色器ID
        int fragmentShaderID = ShaderHelp.compileFragmentShader(stringFragment);
        //链接顶点着色器和片段着色器程序
        int programID = ShaderHelp.linkProgram(vertexShaderID, fragmentShaderID);
        //判断链接得到的程序是否有效
        if (programID==0){
            return;
        }
        //设置OpenGL ES2.0 使用前面生成的程序
        GLES20.glUseProgram(programID);

        //获取在着色器程序中设置的各个变量的位置
        int aPositionLocation = GLES20.glGetAttribLocation(programID,A_POSITION);
        uColorLocation = GLES20.glGetUniformLocation(programID,U_COLOR);

        //将顶点数据和订单属性绑定在一起
        vertexBuffer.position(0);
        GLES20.glVertexAttribPointer(aPositionLocation,VERTEX_COMPONMENT_COUNT,GLES20.GL_FLOAT,false,0,vertexBuffer);
        GLES20.glEnableVertexAttribArray(aPositionLocation);
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int i, int i1) {

    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        //给片段着色器设置uniform值
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glUniform4f(uColorLocation,1.0f,0f,0f,1.0f);
        vertexBuffer.position(0);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3);
    }
}

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

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

shaderHelp 类

public class ShaderHelp {
/**
 * 编译顶点着色器
 * @param shaderCode 着色器代码
 * @return
 */
public static int compileVertexShader(String shaderCode){
   return compileShader(GLES20.GL_VERTEX_SHADER,shaderCode);
}

/**
 * 编译片段着色器
 * @param shaderCode 着色器代码
 * @return
 */
public static int compileFragmentShader(String shaderCode){
    return compileShader(GLES20.GL_FRAGMENT_SHADER,shaderCode);
}

/**
 * 编译着色器
 * @param type 着色器类型
 * @param shaderCode 着色器代码
 * @return 成功创建的着色器对象的引用或者0代表着创建或者编译失败
 */
public static int compileShader(int type,String shaderCode){
    //根据着色器类型  创建着色器 返回着色器的引用ID
    int shaderID = GLES20.glCreateShader(type);
    if (shaderID==0){
        //0代表着创建失败
        LogUtil.log_d("着色器创建失败");
        return 0;
    }
    //如果创建着色器成功的话,将传入的着色器代码传入到创建的着色器中
    GLES20.glShaderSource(shaderID,shaderCode);
    //编译着色器
    GLES20.glCompileShader(shaderID);
    //获取编译状态 判断编译结果是否正确
    int[] compileStatus = new int[1];
    GLES20.glGetShaderiv(shaderID, GLES20.GL_COMPILE_STATUS,compileStatus,0);
    //打印编译结果
    LogUtil.log_d("编译结果是:shadercode==\n"+shaderCode+"\n"+"结果:"+GLES20.glGetShaderInfoLog(shaderID)+"\n");
    //判断编译结果
    if (compileStatus[0]==0){
        //删除着色器对象
        GLES20.glDeleteShader(shaderID);
        LogUtil.log_d("编译失败");
        return 0;
    }
    //此时代表着编译成功
    return shaderID;
}

/**
 * 连接片段着色器和顶点着色器 成为一个程序program
 * @param vertexShaderID 顶点的着色器id
 * @param fragmentShaderID 片段着色器id
 * @return 返回程序id 0代表着程序创建或者连接失败
 */
public static int linkProgram(int vertexShaderID,int fragmentShaderID){
    //创建程序
    int programID = GLES20.glCreateProgram();
    if (programID==0){
        LogUtil.log_d("着色器程序创建失败");
        return 0;
    }
    //创建成功
    //将顶点着色器和片段着色器连接到程序上
    GLES20.glAttachShader(programID,vertexShaderID);
    GLES20.glAttachShader(programID,fragmentShaderID);
    //链接程序
    GLES20.glLinkProgram(programID);
    //获取着色器链接程序的结果
    int[] linkstatus = new int[1];
    GLES20.glGetProgramiv(programID, GLES20.GL_LINK_STATUS,linkstatus,0);
    if (linkstatus[0]==0){
        //链接失败
        LogUtil.log_d("程序链接失败:"+GLES20.glGetProgramInfoLog(programID)+"\n");
        return 0;
    }
    //链接成功
    return programID;
}

/**
 * 通过顶点着色器代码和片段着色器代码 建立程序
 * @param vertexShaderSource 顶点着色器
 * @param fragmentShaderSource 片段着色器
 * @return  建立代码的id
 */
public static int buildProgram(String vertexShaderSource,String fragmentShaderSource){
    int vertexShaderID = compileVertexShader(vertexShaderSource);
    int fragmentShaderID = compileFragmentShader(fragmentShaderSource);
    int programID;
    programID = linkProgram(vertexShaderID,fragmentShaderID);
    validateProgram(programID);
    return programID;
}

/**
 * 验证该程序是否是高效的
 * @param programID
 * @return
 */
public static boolean validateProgram(int programID){
    GLES20.glValidateProgram(programID);
    int[] validateStatus = new int[1];
    GLES20.glGetProgramiv(programID, GLES20.GL_VALIDATE_STATUS,validateStatus,0);
    LogUtil.log_d("程序是否高效的验证结果是:"+validateStatus[0]+"\n返回信息是"+GLES20.glGetProgramInfoLog(programID));
    return validateStatus[0]!=0;
}
}

TextResourceRead类

/**

* Created by WangKunKun on 2018/7/16
* 注解:读取资源文件中的着色器
**/

public class TextResourceRead {

public static String readTextFileFromResource(Context context, int resourceID) {
    StringBuilder stringBuilder = new StringBuilder();
    try {
        InputStream inputStream = context.getResources().openRawResource(resourceID);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String nextLine;
        while ((nextLine = bufferedReader.readLine()) != null) {
            stringBuilder.append(nextLine);
            stringBuilder.append("\n");
        }
    } catch (IOException e) {
        throw new RuntimeException("无法打开资源:"+resourceID,e);
    } catch (Resources.NotFoundException r) {
        throw new RuntimeException("找不到资源:"+resourceID,r);
    }
    return stringBuilder.toString();
}

}

顶点着色器 demo2_vertex.glsl

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

片段着色器 demo2_fragment.glsl

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

猜你喜欢

转载自blog.csdn.net/wkk_ly/article/details/81171845