package com.opengles.sample3_1;import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.opengl.GLES30;
import android.util.Log;import java.io.ByteArrayOutputStream;
import java.io.InputStream;//其功能将着色器(shader)脚本加载进显卡并编译
public class ShaderUtil {private static final String TAG = "ShaderUtil";public static int loadShader(int shaderType, //shader的类型 GLES30.GL_VERTEX_SHADER(顶点) GLES30.GL_FRAGMENT_SHADER(片元)String source //shader的脚本字符串){//创建一个新的shaderint shader = GLES30.glCreateShader(shaderType);//创建成功if(shader != 0){//加载shader的源代码GLES30.glShaderSource(shader,source);//编译shaderGLES30.glCompileShader(shader);//存放编译成功shader数量的数字int[] compiled = new int[1];//获取shader的编译情况GLES30.glGetShaderiv(shader,GLES30.GL_COMPILE_STATUS,compiled,0);if(compiled[0] == 0){Log.e(TAG,"Could not compile shader " +shaderType + ":");Log.e(TAG,GLES30.glGetShaderInfoLog(shader));GLES30.glDeleteShader(shader);shader = 0;}}return shader;}//创建shader程序的方法public static int createProgram(String vertexSource, String fragmentSource){//加载顶点着色器int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexSource);if (vertexShader == 0){return 0;}//加载片元着色器int pixelShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentSource);if (pixelShader == 0){return 0;}//创建程序int program = GLES30.glCreateProgram();//若程序创建成功则向程序中加入顶点着色器与片元着色器if (program != 0){//向程序中加入顶点着色器GLES30.glAttachShader(program, vertexShader);checkGlError("glAttachShader");//向程序中加入片元着色器GLES30.glAttachShader(program, pixelShader);checkGlError("glAttachShader");//链接程序GLES30.glLinkProgram(program);//存放链接成功program数量的数组int[] linkStatus = new int[1];//获取program的链接情况GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkStatus, 0);//若链接失败则报错并删除程序if (linkStatus[0] != GLES30.GL_TRUE){Log.e("ES20_ERROR", "Could not link program: ");Log.e("ES20_ERROR", GLES30.glGetProgramInfoLog(program));GLES30.glDeleteProgram(program);program = 0;}}return program;}//检查每一步操作是否有错误的方法@SuppressLint("NewApi")public static void checkGlError(String op){int error;while ((error = GLES30.glGetError()) != GLES30.GL_NO_ERROR){Log.e("ES20_ERROR", op + ": glError " + error);throw new RuntimeException(op + ": glError " + error);}}//从sh脚本中加载shader内容的方法public static String loadFromAssetsFile(String fname, Resources r){Log.e(TAG, "loadFromAssetsFile: "+r);String result=null;try{InputStream in=r.getAssets().open(fname);int ch=0;ByteArrayOutputStream baos = new ByteArrayOutputStream();while((ch=in.read())!=-1){baos.write(ch);}byte[] buff=baos.toByteArray();baos.close();in.close();result=new String(buff,"UTF-8");result=result.replaceAll("\\r\\n","\n");}catch(Exception e){e.printStackTrace();}return result;}
}