Android openGL ES 2.0入门--画三角形、正方形

因为最近的项目需要用到openGL ES 2.0,折腾了半天,查了网上一大堆资料,都没找到系统的openGL ES 2.0的学习资料。经过这半天,总算自己写了一个可以画出三角形和正方形的代码,顺便对网上一堆的代码封装了下。嗯,开始说吧。

首先感谢这篇教程:

http://hukai.me/android-training-course-in-chinese/graphics/opengl/environment.html

以及它的android官方原文:https://developer.android.com/training/graphics/opengl/shapes.html


不想往下看的同学,源码在这里:

http://download.csdn.net/detail/code_better/9592177


其他的我就不多说了,想说的都在注释里:

项目结构图:


先在manifest.xml里加上:

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />


MainActivity:

/**
 * GLSurfaceView相当于画布
 * 主要绘画工作都在Renderer里
 */
public class MainActivity extends AppCompatActivity {

    private GLSurfaceView glSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //创建一个GLSurfaceView实例
        glSurfaceView = new MyGLSurfaceView(this);
        //将glSurfaceView设置为activity的ContentView.
        setContentView(glSurfaceView);
    }
    @Override
    protected void onPause() {
        super.onPause();
        if (glSurfaceView != null) {
            glSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (glSurfaceView != null) {
            glSurfaceView.onResume();
        }
    }
}



MyGLSurfaceView:

class MyGLSurfaceView extends GLSurfaceView {

    public MyGLSurfaceView(Context context) {
        super(context);
        // 创建一个OpenGL ES 2.0 context,非常重要
        setEGLContextClientVersion(2);
        //设置Renderer到GLSurfaceView
        setRenderer(new MyGL20Renderer());
        // 只有在绘制数据改变时才绘制view
        //此设置会阻止绘制GLSurfaceView的帧,直到你调用了requestRender(),这样会非常高效
//        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }
}

MyGL20Renderer:

public class MyGL20Renderer implements GLSurfaceView.Renderer {

    //声明一个三角形对象
    Triangle triangle = null;
    //声明一个正方形对象
    Square square = null;

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        //设置背景的颜色
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        triangle = new Triangle();
        square = new Square();
    }

    public void onDrawFrame(GL10 unused) {
        // 重绘背景色
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        //绘制三角形
//        triangle.draw();
        //绘制矩形
        square.draw();
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
}



Util:

/**
 * Created by 炜贤 on 2016/8/1.
 * <p/>
 * 画一个图形:需要至少一个顶点着色器来绘制一个形状,以及一个片段着色器为该形状上色。
 * 这些着色器必须被编译然后添加到一个OpenGL ES Program当中,并利用它来绘制形状。
 */
public class Util {

    /**
     * float类型大小为4个字节
     */
    private static final int LENGTH = 4;

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


    public int loadShader(int type, String shaderCode) {

        // 创建一个vertex shader类型(GLES20.GL_VERTEX_SHADER)
        // 或一个fragment shader类型(GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(type);

        // 将源码添加到shader并编译它
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;
    }

    /**
     * 顶点着色器(Vertex Shader):用来渲染形状顶点的OpenGL ES代码
     *
     * @return 顶点着色器
     */
    public int getVertexShader() {
        return loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    }

    /**
     * 片段着色器(Fragment Shader):使用颜色或纹理渲染形状表面的OpenGL ES代码。
     *
     * @return 片段着色器
     */
    public int getFragmentShader() {
        return loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
    }

    /**
     * 程式(Program):一个OpenGL ES对象,包含了你希望用来绘制一个或更多图形所要用到的着色器
     * 程式(program)是用来装配着色器的(个人理解)
     *
     * @return 程式
     */
    public int getProgram() {
        //获取顶点着色器
        int vertexShader = getVertexShader();
        //获取片段着色器
        int fragmentShader = getFragmentShader();

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

        // 添加program到OpenGL ES环境中
        GLES20.glUseProgram(program);
        return program;
    }


    /**
     * @param coords_per_vertex 每个顶点的坐标数
     * @param vertexBuffer      浮点缓冲区
     * @param color             颜色数组,数组的四个数分别为图形的RGB值和透明度
     */
    public void draw(int coords_per_vertex, FloatBuffer vertexBuffer, float color[]) {
        //获取程式
        int program = getProgram();

        //得到处理到顶点着色器的vPosition成员
        int vPositionHandler = GLES20.glGetAttribLocation(program, "vPosition");

        // 启用一个指向图形的顶点数组的handle
        GLES20.glEnableVertexAttribArray(vPositionHandler);

        // 准备坐标数据
        GLES20.glVertexAttribPointer(vPositionHandler, coords_per_vertex,
                GLES20.GL_FLOAT, false,
                LENGTH * coords_per_vertex, vertexBuffer);

        // 得到处理到片段着色器的vPosition成员
        int mColorHandle = GLES20.glGetUniformLocation(program, "vColor");

        // 设置颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        // 绘制三角形比较简单,这里采用glDrawArrays方法(默认是逆时针方向)
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

        // 禁用指向图形的顶点数组
        GLES20.glDisableVertexAttribArray(vPositionHandler);
    }

    /**
     *
     * @param coords_per_vertex 每个顶点的坐标数
     * @param vertexBuffer      浮点缓冲区
     * @param color             颜色数组,数组的四个数分别为图形的RGB值和透明度
     * @param drawOrder         绘制顶点的顺序(按逆时针方向)
     * @param drawListBuffer    绘图顺序顶点的缓冲区
     */
    public void draw(int coords_per_vertex, FloatBuffer vertexBuffer, float color[], short drawOrder[], ShortBuffer drawListBuffer) {
        //获取程式
        int program = getProgram();

        //得到处理到顶点着色器的vPosition成员
        int vPositionHandler = GLES20.glGetAttribLocation(program, "vPosition");

        // 启用一个指向图形的顶点数组的handle
        GLES20.glEnableVertexAttribArray(vPositionHandler);

        // 准备坐标数据
        GLES20.glVertexAttribPointer(vPositionHandler, coords_per_vertex,
                GLES20.GL_FLOAT, false,
                LENGTH * coords_per_vertex, vertexBuffer);

        // 得到处理到片段着色器的vPosition成员
        int mColorHandle = GLES20.glGetUniformLocation(program, "vColor");

        // 设置颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        // 绘制图形
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        // 禁用指向图形的顶点数组
        GLES20.glDisableVertexAttribArray(vPositionHandler);
    }
}

Triangle:

/**
 * 三角形
 */
public class Triangle {

    private FloatBuffer vertexBuffer;

    // 设置每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    // 设置三角形顶点数组
    static float triangleCoords[] = { // 默认按逆时针方向顺序绘制
            0.0f, 0.622008459f, 0.0f,   // 顶
            -0.5f, -0.311004243f, 0.0f,   // 左底
            0.5f, -0.311004243f, 0.0f    // 右底
    };

    // 设置图形的RGB值和透明度
    float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};

    /**
     * 初始化
     * 流程:创建一个顶点的缓冲区空间,然后将其作为一个浮点的缓冲区,
     * 然后将坐标加到这个缓冲区中,然后将读指针指向第一个位置
     */
    public Triangle() {
        // 初始化顶点字节缓冲区,用于存放形状的坐标,
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (每个浮点数占用4个字节)
                triangleCoords.length * 4);
        // 设置使用设备硬件的原生字节序
        bb.order(ByteOrder.nativeOrder());

        // 将ByteBuffer作为一个浮点缓冲区
        vertexBuffer = bb.asFloatBuffer();
        // 把坐标都添加到FloatBuffer中
        vertexBuffer.put(triangleCoords);
        // 设置buffer从第一个坐标开始读
        vertexBuffer.position(0);
    }

    /**
     * 绘图
     */
    public void draw(){
        new Util().draw(COORDS_PER_VERTEX,vertexBuffer,color);
    }
}



Square:

/**
 * 正方形
 */
public class Square {

    //顶点缓冲区
    private FloatBuffer vertexBuffer;
    //绘图顺序顶点缓冲区
    private ShortBuffer drawListBuffer;

    // 每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    //正方形四个顶点的坐标
    static float squareCoords[] = {-0.5f, 0.5f, 0.0f,   // top left
            -0.5f, -0.5f, 0.0f,   // bottom left
            0.5f, -0.5f, 0.0f,   // bottom right
            0.5f, 0.5f, 0.0f}; // top right

    private short drawOrder[] = {0, 1, 2, 0, 2, 3}; // 顶点的绘制顺序
    // 设置图形的RGB值和透明度
    float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};

    public Square() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (坐标数 * 4)
                squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);

        // 为绘制列表初始化字节缓冲
        ByteBuffer dlb = ByteBuffer.allocateDirect(
                // (对应顺序的坐标数 * 2)short是2字节
                drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);
    }

    /**
     * 绘图
     */
    public void draw() {
        new Util().draw(COORDS_PER_VERTEX, vertexBuffer, color, drawOrder, drawListBuffer);
    }
}


这个画出来的三角形和正方形的效果并不是我们预想的的那样,那是因为投影的问题,请看我之后的博客吧,谢谢!



  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android OpenGL ES 2.0是一种用于在Android设备上进行图形渲染的API。它提供了一组功能强大的工具和函数,可以实现各种图形效果,包括线。 要在Android上使用OpenGL ES 2.0线,你需要以下步骤: 1. 初始化OpenGL ES环境:在你的Android应用程序中,你需要创建一个OpenGL ES上下文,并设置相关的配置参数。 2. 创建顶点数据:线需要定义线的起点和终点坐标。你可以创建一个顶点数组来存储这些坐标。 3. 创建着色器程序:OpenGL ES 2.0使用着色器来处理图形渲染。你需要编写顶点着色器和片段着色器,并将它们编译链接成一个着色器程序。 4. 加载顶点数据:将顶点数据加载到OpenGL ES的缓冲区中。 5. 绘制线段:使用绘制命令告诉OpenGL ES如何绘制线段。你可以使用glDrawArrays或glDrawElements函数来执行绘制操作。 下面是一个简单的示例代码,演示如何使用OpenGL ES 2.0Android一条线: ```java // 初始化OpenGL ES环境 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 创建顶点数据 float[] vertices = { -0.5f, 0.0f, 0.0f, // 线的起点坐标 0.5f, 0.0f, 0.0f // 线的终点坐标 }; // 创建着色器程序 int program = createProgram(vertexShaderCode, fragmentShaderCode); // 加载顶点数据 FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); // 绘制线段 GLES20.glUseProgram(program); GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glLineWidth(5.0f); // 设置线的宽度 GLES20.glDrawArrays(GLES20.GL_LINES, 0, vertices.length / COORDS_PER_VERTEX); GLES20.glDisableVertexAttribArray(positionHandle); ``` 这是一个简单的示例,你可以根据自己的需求进行扩展和修改。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值