Android OpenGl ES2.0编程_相关概念与绘制顶点

前言
前面介绍了使用 Android 编写 OpenGL ES 应用的程序框架,并成功绘制了第一个OpenGL ES 2.0的小程序,本篇介绍 3D 绘图的一些基本构成要素,基本概念,重要的函数,最终将实现一个顶点的绘制。
本文是建立在上一篇文章之上,只修改MyRenderer类,其他部分保持不变,如果你没有看上一篇文章,请先移步Android OpenGl ES2.0编程_第一个OpenGL小程序

▲ 基本概念

Vertex (顶点)
顶点是3D建模时用到的最小构成元素,顶点定义为两条或是多条边交会的地方。在 3D 模型中一个顶点可以为多条边,面或是多边形所共享。一个顶点也可以代表一个点光源或是 Camera 的位置。下图中标识为黄色的点为一个顶点(Vertex)。

Android OpenGl ES2.0编程_相关概念与绘制顶点_第1张图片

三维坐标系

三维笛卡儿坐标系是在二维笛卡儿坐标系的基础上根据右手定则增加第三维坐标(即Z轴)而形成的。同二维坐标系一样,AutoCAD中的三维坐标系有世界坐标系WCS(World Coordinate System)和用户坐标系UCS(User Coordinate System)两种形式。---百度百科

学习OpenGL编程,少不了需要了解坐标系的概念,这里我们不用理解的那么深,简单的知道和了解最基本的就好,推荐阅读三维坐标系介绍

在3D绘图中,坐标轴遵循右手法则。三维坐标系中,Z轴的正轴方向是根据右手定则确定的。右手定则也决定三维空间中任一坐标轴的正旋转方向。
要标注X、Y和Z轴的正轴方向,就将右手背对着屏幕放置,拇指即指向X轴的正方向。伸出食指和中指,如右图所示,食指指向Y轴的正方向,中指所指示的方向即是Z轴的正方向。
要确定轴的正旋转方向,如右图所示,用右手的大拇指指向轴的正方向,弯曲手指。那么手指所指示的方向即是轴的正旋转方向。

Android OpenGl ES2.0编程_相关概念与绘制顶点_第2张图片

▲ 点的构成
有了之前对坐标系的理解,我们知道,在3D绘制中,一个点包含x、y、z坐标。在Android系统中,可以用一个float数组、int数组等来表示一个点。如下:

private float[] mArrayVertex = { 0f, 0f, 0f };

为了提高性能,通常将这些数组存放到 java.io 中定义的 Buffer 类中
新建一个工具类ToolUtils,把获取Buffer数据的代码封装如下

public class ToolUtils {
    /**
     * @param vertexes float 数组
     * @return 获取浮点形缓冲数据
     */
    public static FloatBuffer getFloatBuffer(float[] vertexes) {
        FloatBuffer buffer;
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertexes.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        buffer = vbb.asFloatBuffer();
        //写入数组
        buffer.put(vertexes);
        //设置默认的读取位置
        buffer.position(0);
        return buffer;
    }
}

▲ 绘制一个点
这里只需修改MyRenderer类的代码,其余代码和之前搭建的基础框架一样。MyRenderer.java

public class MyRenderer implements GLSurfaceView.Renderer {
    //顶点数组
    private float[] mArrayVertex = { 0f, 0f, 0f };

    // 缓冲区
    private FloatBuffer mBuffer;

    MyRenderer() {
        //获取浮点形缓冲数据
        mBuffer = ToolUtils.getFloatBuffer(mArrayVertex);
    }

    // Surface创建的时候调用
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 设置清屏颜色为黑色(rgba)
        gl.glClearColor(0f, 0f, 0f, 0f);
    }

    // Surface改变的的时候调用
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // 设置OpenGL场景的大小
        gl.glViewport(width / 4, width / 2, width / 2, height / 2);
    }

    // 在Surface上绘制的时候调用
    @Override
    public void onDrawFrame(GL10 gl) {

        // 清除屏幕
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        // 允许设置顶点 // GL10.GL_VERTEX_ARRAY顶点数组
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        // 设置顶点
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mBuffer);

        //设置点的颜色为红色
        gl.glColor4f(1f, 0f, 0f, 0f);

        //设置点的大小
        gl.glPointSize(100f);

        // 绘制点
        gl.glDrawArrays(GL10.GL_POINTS, 0, 1);

        // 禁止顶点设置
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

▲ 启用相关功能及配置说明
这里讲解部分比较重要的函数,之后还有一些常用API在之后的文章会重点讲到

0. glClearColor()
设置清屏颜色,每次清屏时,使用该颜色填充整个屏幕。里面参数分别代表RGBA,取值范围为[0,1]而不是[0,255]。例如:

gl.glClearColor(0f, 0f, 0f, 0f);

1. glVertexPointer()
设置一个指针,这个指针指向顶点数组,后面绘制三角形(或矩形)根据这里指定的顶点数组来读取数据
函数原型:

void glVertexPointer(int size,int type,int stride,Buffer pointer)

参数解释

size —— 每个顶点的坐标维数,必须是2, 3 或者4,初始值是4。

type —— 指明每个顶点坐标的数据类型,允许的符号常量GL_BYTE, GL_SHORT,GL_FIXED 和GL_FLOAT,初始值为GL_FLOAT。

stride —— 指明连续顶点间的位偏移,如果为0,顶点被认为是紧密压入矩阵,初始值为0。

pointer —— 指明顶点坐标的缓冲区,如果为null,则没有设置缓冲区。

2. glClear()
用来清理缓冲区,并设置为预设值
函数原型:

glClear(int mask)

mask的值有以下三种

GL_COLOR_BUFFER_BIT —— 表明颜色缓冲区

GL_DEPTH_BUFFER_BIT —— 表明深度缓冲

GL_STENCIL_BUFFER_BIT —— 表明模型缓冲区

3. glEnableClientState()
启用客户端的某项功能。glEnableClientState和glDisableClientState启用或禁用客户端的单个功能。默认的,所有客户端功能禁用。 array可以是下列符号常量:

GL_COLOR_ARRAY —— 如果启用,颜色矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glColorPointer。

GL_NORMAL_ARRAY —— 如果启用,法线矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glNormalPointer。

GL_TEXTURE_COORD_ARRAY —— 如果启用,纹理坐标矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glTexCoordPointer。

GL_VERTEX_ARRAY —— 如果启用,顶点矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glVertexPointer。

GL_POINT_SIZE_ARRAY_OES(OES_point_size_arrayextension)——如果启用,点大小矩阵控制大小以渲染点和点sprites。这时由glPointSize定义的点大小将被忽略,由点大小矩阵 提供的大小将被用来渲染点和点sprites。详见glPointSize。

4. glDrawArrays()
绘制数组里面所有点构成的各个三角片
函数原型:

void glDrawArrays(
    int mode,
    int first,
    int count
);

参数解释

mode:有三种取值

  • GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接
  • GL_TRIANGLE_FAN:以V0 V1 V2,V0 V2 V3,V0 V3 V4,……的形式绘制三角形
  • GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。这个方法可以保证从相同的方向上所有三角形均被绘制。以V0 V1 V2 ,V1 V2 V3,V2 V3 V4,……的形式绘制三角形

first:从数组缓存中的哪一位开始绘制,一般都定义为0

count:顶点的数量

▲ 最终效果图
看着虽然是一个正方形,但实际它是一个大小为100f的正方形的点

Android OpenGl ES2.0编程_相关概念与绘制顶点_第3张图片

▲ 完整代码下载:https://github.com/ChenYXin/OpenGL_ES_2.0_Sample

你可能感兴趣的:(Android OpenGl ES2.0编程_相关概念与绘制顶点)