Android OpenGL ES基本用法(2),绘制三角图形


目录


OpenGL的坐标系

Android OpenGL ES基本用法(2),绘制三角图形_第1张图片

顶点着色器,片元着色器

Android OpenGL ES基本用法(2),绘制三角图形_第2张图片

vertex_shader.glsl

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

注: attribute 只能在vertex中使用

fragment_shader.glsl

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

注: uniform 用于在application中向vertex和fragment中传递值。

ShaderUtil.java

package com.jianji.delogo.Test.MediaCodec;

import android.content.Context;
import android.opengl.GLES20;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ShaderUtil {
    private static final String TAG = "ShaderUtil";

    /**
     * 读取shader
     *
     * @param context
     * @param rawId
     * @return
     */
    public static String readRawTxt(Context context, int rawId) {
        InputStream inputStream = context.getResources().openRawResource(rawId);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer sb = new StringBuffer();
        String line;

        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 加载shader
     *
     * @param shaderType
     * @param source
     * @return
     */
    private static int loadShader(int shaderType, String source) {
        //创建shader
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            //关联source
            GLES20.glShaderSource(shader, source);
            //编译
            GLES20.glCompileShader(shader);
            //获取编译状态
            int[] compile = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
            if (compile[0] != GLES20.GL_TRUE) {
                //失败
                Log.e(TAG, "loadShader: shader compile error");
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }

    /**
     * 生成程序
     *
     * @param vertexSource
     * @param fragmentSource
     * @return
     */
    public static int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (fragmentShader == 0) {
            return 0;
        }
        //创建
        int program = GLES20.glCreateProgram();
        if (program != 0) {
            //附加着色器
            GLES20.glAttachShader(program, vertexShader);
            GLES20.glAttachShader(program, fragmentShader);
            //连接
            GLES20.glLinkProgram(program);
            //检查连接是否成功
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                //出错
                Log.e(TAG, "createProgram: link program error");
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }
}

GLTestView.java

package com.jianji.delogo.Test.MediaCodec;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;

import com.jianji.delogo.R;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;


public class GLTestView extends GLSurfaceView implements GLSurfaceView.Renderer {

    private Context context;

    //绘制坐标范围
    float[] vertexData = {
            -1f, 0.0f,
            0.0f, 1.0f,
            1.0f, 0.0f
    };
    //为坐标分配本地内存地址,不受jvm的影响
    FloatBuffer vertexBuffer;

    public GLTestView(Context context) {
        this(context, null);
    }

    public GLTestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        //设置OpenGL的版本
        setEGLContextClientVersion(2);
        setRenderer(this);
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())//对齐,加快处理速度
                .asFloatBuffer()
                .put(vertexData);
        //指向0的位置
        vertexBuffer.position(0);
    }

    private int program;
    private int avPosition;
    private int afColor;

    /**
     * Called when the surface is created or recreated.
     */
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        String vertexSource = ShaderUtil.readRawTxt(context, R.raw.vertex_shader);
        String fragmentSource = ShaderUtil.readRawTxt(context,R.raw.fragment_shader);

        program = ShaderUtil.createProgram(vertexSource,fragmentSource);
        if (program > 0) {
            avPosition = GLES20.glGetAttribLocation(program,"av_Position");
            afColor = GLES20.glGetUniformLocation(program,"af_Color");
        }
    }

    /**
     * Called when the surface changed size.
     */
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //设置大小位置
        GLES20.glViewport(0, 0, width, height);
    }

    /**
     * Called to draw the current frame.
     */
    @Override
    public void onDrawFrame(GL10 gl) {
        //清屏,清理掉颜色的缓冲区
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //设置清屏的颜色,这里是float颜色的取值范围的[0,1]
        GLES20.glClearColor(1.0f, 0f, 0f, 1.0f);

        //使用program
        GLES20.glUseProgram(program);

        //设置颜色,和颜色的色值
        GLES20.glUniform4f(afColor,1f,1f,0f,1f);

        //设置为可用的状态
        GLES20.glEnableVertexAttribArray(avPosition);
        //size 指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
        //stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
        GLES20.glVertexAttribPointer(avPosition,2,GLES20.GL_FLOAT,false,8, vertexBuffer);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3);
    }
}

Android OpenGL ES基本用法(2),绘制三角图形_第3张图片

你可能感兴趣的:(OpenGL)