学习OpenGL入门第一步之画三角形详解

OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平台的编程接口的规格,它用于三维图象(二维的亦可)。OpenGL是个专业的图形程序接口,是一个功能强大,调用方便的底层图形库。

打开AndroidStudio新建名为“TrangleDemo”的项目

默认生成的MainActivity的setContentView不再放入layout的xml布局文件,而是GLSurfaceView

public class MainActivity extends Activity {

    private MyGLSurfaceView mGLView;

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

        mGLView = new MyGLSurfaceView(this);
        setContentView(mGLView);
    }
}

构建一个GLSurfaceView对象

新建MyGLSurfaceView类并继承GLSurfaceView

public class MyGLSurfaceView extends GLSurfaceView {
    public MyGLSurfaceView(Context context) {
        super(context);
        // 创建一个OpenGL ES 2.0 context,必须放在下一行代码之前,不然会报错
        setEGLContextClientVersion(2);
        //设置Renderer到GLSurfaceView
        setRenderer(new MyRenderer());
        //设置render模式为只在绘制数据发生改变时才绘制view
        setRenderMode(MyGLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }
}

构建一个渲染器Renderer

新建MyRenderer类并实现GLSurfaceView.Renderer

  • onSurfaceCreated()- 仅调用一次,用于设置view的OpenGLES环境。
  • onSurfaceChanged()- 如果view的几和形状发生变化了就调用,例如当竖屏变为横屏时。
  • onDrawFrame()- 每次View被重绘时被调用。
public class MyRenderer implements GLSurfaceView.Renderer {

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //设置背景色(red,green,blue,alpha透明度)
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //设置视口
        GLES20.glViewport(0, 0, width, height);

    @Override
    public void onDrawFrame(GL10 gl) {
        //重绘背景色
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }
}

启动模拟器,运行效果如图所示

上面的代码只是为我们创建了一块灰色的画布,为我们在上面画三角形做准备

学习OpenGL入门第一步之画三角形详解_第1张图片

定义形状,准备画三角形

新建Triangle类

public class Triangle {
    private FloatBuffer vertexBuffer;//缓冲区

    private int mProgram;//着色程序
    private int mPositionHandle, mColorHandle;

    static final int COORDS_PER_VERTEX = 3;// 数组中每个顶点的坐标数
    static float triangleCoords[] = {      // 按逆时针方向顺序:
             0.0f,  0.622008459f, 0.0f,    //top
            -0.5f, -0.311004243f, 0.0f,    //bottom left
             0.5f, -0.311004243f, 0.0f     //bottom right
    };

    // 设置颜色,分别为red, green, blue 和alpha (opacity)
    float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};

    public Triangle(){
        // 为存放形状的坐标,初始化顶点字节缓冲
        ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
        // 设用设备的本点字节序
        bb.order(ByteOrder.nativeOrder());
        // 从ByteBuffer创建一个浮点缓冲
        vertexBuffer = bb.asFloatBuffer();
        // 把坐标们加入FloatBuffer中
        vertexBuffer.put(triangleCoords);
        // 设置buffer,从第一个坐标开始读
        vertexBuffer.position(0);
    }
}

绘制形状

在MyRenderer类的顶部实例化Triangle类

private Triangle mTriangle;

在MyRenderer类的onSurfaceCreated()方法中初始化形状

mTriangle = new Triangle();

在Triangle 类的顶部声明顶点着色器、片元着色器

private final String vertexShaderCode =
        "attribute vec4 vPosition;" +
        "void main() {" +
        " gl_Position = vPosition;" +
        "}";
private final String fragmentShaderCode =
        "precision mediump float;"+
        "uniform vec4 vColor;"+
        "void main() {"+
        " gl_FragColor = vColor;"+
        "}";

若要编译着色器代码,需在Triangle类中创建一个工具类方法

public static int loadShader(int shaderType, String shaderCode){
        // 创建一个vertex shader类型(GLES20.GL_VERTEX_SHADER)
        // 或fragment shader类型(GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(shaderType);
        // 将源码添加到shader并编译之
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
}

为了绘制你的形状,你必须编译shader代码,添加它们到一个OpenGLES program 对象然后链接这个program。在Triangle类的构造方法中加入如下代码:

int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

mProgram = GLES20.glCreateProgram();            // 创建一个空的OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader);  // 将vertex shader添加到program
GLES20.glAttachShader(mProgram, fragmentShader);// 将fragment shader添加到program
GLES20.glLinkProgram(mProgram);                 // 创建可执行的 OpenGL ES program

创建一个draw()方法来绘制形状

public void draw(){
        // 将program加入OpenGL ES环境中
        GLES20.glUseProgram(mProgram);
        // 获取指向vertex shader的成员vPosition的 handle
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        // 启用一个指向三角形的顶点数组的handle
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        // 准备三角形的坐标数据
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                3 * 4,
                vertexBuffer);
        // 获取指向fragment shader的成员vColor的handle
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        // 设置三角形的颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        //画三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
        // 禁用指向三角形的顶点数组
        GLES20.glDisableVertexAttribArray(mPositionHandle);
}

在Renderer的onDrawFrame()调用draw()方法

@Override
public void onDrawFrame(GL10 gl) {
        ...
        mTriangle.draw();
    }

启动模拟器,运行效果如下

学习OpenGL入门第一步之画三角形详解_第2张图片

你可能感兴趣的:(android)