欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL_ES_三角形

程序员文章站 2023-12-24 22:08:45
...

OpenGL ES2.0 绘制三角形

效果

OpenGL_ES_三角形

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;
}

上一篇:

下一篇: