2 提取Program 对象工具类

提取创建 Program 对象的工具类

  • 对外唯一接口

    ShaderUtils.createProgram(this.getResources() , vertexCodePath , fragmentCodePath)
    

实例代码

package com.example.openglstudy.utils;
import android.content.res.Resources;
import android.opengl.GLES20;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;

public class ShaderUtils {
    public static int createProgram(Resources res , String vertexPath ,String fragmentPath){
        String vertexCodeString = compilerSourceToString(res , vertexPath);
        String fragmentCodeString = compilerSourceToString(res , fragmentPath);
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER , vertexCodeString);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER , fragmentCodeString);

        int program = GLES20.glCreateProgram();
        if (program == 0){
            glError("create program failed");
            return 0;
        }

        GLES20.glAttachShader(program , vertexShader);
        GLES20.glAttachShader(program , fragmentShader);
        GLES20.glLinkProgram(program);

        //check  program  status;
        int[] programStatus = new int[1];
        GLES20.glGetProgramiv(program , GLES20.GL_LINK_STATUS ,programStatus , 0 );
        if (programStatus[0] == 0){
            glError("link program  failed");
            glError("link program failed :" + GLES20.glGetProgramInfoLog(program));
            GLES20.glDeleteProgram(program);
            program = 0;
        }

        return program;
    }

    private static int loadShader(int type , String sourceCode){
        int shader = GLES20.glCreateShader(type);
        if (shader == 0){
            glError("create shader failed" + type);
            return 0;
        }
        GLES20.glShaderSource(shader , sourceCode);
        GLES20.glCompileShader(shader);
        int[] compilerStatus = new int[1];
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS,compilerStatus,0);
        if (compilerStatus[0] == 0){
            //编译失败.
            glError("compiler code failed : " + type);
            glError("compiler code failed : " + GLES20.glGetShaderInfoLog(shader) );
            GLES20.glDeleteShader(shader);
            shader = 0;
        }
        return  shader;
    }

    private static String compilerSourceToString(Resources res , String path){
        StringBuffer sb = null;
        InputStream is = null;
        try {
            sb = new StringBuffer();
            is =   res.getAssets().open(path);
            int len;
            byte[] buffer = new byte[1024];
            while(-1 != (len = is.read(buffer))){
                sb.append(new String(buffer , 0 , len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (is!= null){
                        is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        return  sb.toString().replaceAll("\\r\\n" , "\n");
    }

    private static void glError(String error){
        Log.e("ShanderUtils" , error);
    }

}

代码解析

  1. 加载 glsl 文件生成 shaderID 值

加载glsl 一共使用了3 个函数: 创建 ---> 加载源码 --> 编译.

  • int shader = GLES20.glCreateShader(type);

    函数的type一共有两个:

    GLES20.GL_VERTEX_SHADER

    GLES20.GL_FRAGMENT_SHADER

  • GLES20.glShaderSource(shader , sourceCode);

  • GLES20.glCompileShader(shader)

检测错误位置:

  • 创建shader时.判断shader 是否创建成功. 当shader 为0 时,创建失败. 创建失败有几种情况, 包含type不对, 还有就是创建shader时,当前的上下文不在 draw() 过程中.

  • 编译之后, 检测编译是否成功. 在检测到编译失败后, 使用 glGetShaderInfoLog(shader) 函数获取错误信息, 并将信息直接String 返回出来. 并开始清理环境, 将当前错误的 shader 删除. 直接调用 glDeleteShader(shader) 即可, 这个函数也可以在绘制图形完毕后调用.

    int[] compilerStatus = new int[1];
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS,compilerStatus,0);
   private static int loadShader(int type , String sourceCode){
       int shader = GLES20.glCreateShader(type);
       if (shader == 0){
           glError("create shader failed" + type);
           return 0;
       }
       GLES20.glShaderSource(shader , sourceCode);
       GLES20.glCompileShader(shader);
       int[] compilerStatus = new int[1];
       GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS,compilerStatus,0);
       if (compilerStatus[0] == 0){
           //编译失败.
           glError("compiler code failed : " + type);
           glError("compiler code failed : " + GLES20.glGetShaderInfoLog(shader) );
           GLES20.glDeleteShader(shader);
           shader = 0;
       }
       return  shader;
   }
  1. 加载 glsl 文件为String

     private static String compilerSourceToString(Resources res , String path){
            StringBuffer sb = null;
            InputStream is = null;
            try {
                sb = new StringBuffer();
                is =   res.getAssets().open(path);
                int len;
                byte[] buffer = new byte[1024];
                while(-1 != (len = is.read(buffer))){
                    sb.append(new String(buffer , 0 , len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if (is!= null){
                            is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
    
            return  sb.toString().replaceAll("\\r\\n" , "\n");
        }
    
        private static void glError(String error){
            Log.e("ShanderUtils" , error);
        }
    

  2. 创建程序. 附着shader

       int program = GLES20.glCreateProgram();
            if (program == 0){
                glError("create program failed");
                return 0;
            }
    
            GLES20.glAttachShader(program , vertexShader);
            GLES20.glAttachShader(program , fragmentShader);
            GLES20.glLinkProgram(program);
    
            //check  program  status;
            int[] programStatus = new int[1];
            GLES20.glGetProgramiv(program , GLES20.GL_LINK_STATUS ,programStatus , 0 );
            if (programStatus[0] == 0){
                glError("link program  failed");
                glError("link program failed :" + GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
    
            return program;
    

你可能感兴趣的:(2 提取Program 对象工具类)