NDK开发OpenGL ES 3.0(五)——一个立方体

NDK开发OpenGL ES 3.0(五)——一个立方体

标签(空格分隔): OpenGL-ES 0

版本:2
作者:陈小默
声明:禁止商用,禁止转载

文章仅发布于 作业部落、、开源中国


上一篇:NDK开发OpenGL ES 3.0(四)——旋转的彩色方块


本章参考书:
[1]Dan Ginsburg,Budirjanto Purnomo.OpenGL ES 3.0 编程指南 第二版(姚军 译).北京:机械工业出版社


本篇主要介绍OpenGL ES中的图元装配和一些光栅化过程。学完本篇内容之后我们将会建造一个简单的旋转的立方体,就像下图所示。


NDK开发OpenGL ES 3.0(五)——一个立方体_第1张图片
最终效果图

[toc]

九、图元装配和光栅化

本章主要内容是介绍基本图元,以及图元的装配和最终显示之前的光栅化。


9.1 基本图元

图元是由一组顶点描述的几何形状对象。在OpenGL中,任何图元都可以被绘制,但是在OpenGL ES中,由于其性能被精简(毕竟移动端CPU和GPU不比桌面设备),所以只能绘制三种最基本的图元,但所有的图形都可以使用这三个基本图元来表示:

  • 点精灵
  • 直线
  • 三角形

9.1.1 点精灵

在OpenGL中,点精灵是指定位置和半径的屏幕对其的正方形,常用作粒子效果。

图元枚举GL_POINTS
注意:默认情况下,点精灵的坐标原点是屏幕左上角。当我们决定绘制点的时候,需要在着色器中设置点的尺寸,否则,可能会造成绘图错误。在着色器中表示点精灵尺寸的变量是gl_PointSize

9.1.2 直线

图元枚举GL_LINESGL_LINE_STRIPGL_LINE_LOOP

说明:假设现在有[0,1,2,3,4]共5个点组成的数组,我们使用下列类型绘制的结果:

  • GL_LINES:绘制出[0,1]和[2,3]两条线,第五个点由于没有匹配点而被忽略。
  • GL_LINE_STRIP:绘制出[0,1],[1,2],[2,3],[3,4]两两相连的四条线组成的折现。
  • GL_LINE_LOOP:绘制出[0,1],[1,2],[2,3],[3,4],[4,1]首尾相连的封闭图形。

其他函数

void glLineWidth(GLfloat width);

  • width:指定线宽,默认为1.0

9.1.3 三角形

将一个图形分解为若干三角形是几何渲染最常用的方式

图元枚举GL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FAN

说明:假设有[0,1,2,3,4,5,6]共7个点组成的数组,我们使用下列类型的绘制结果:

  • GL_TRIANGLES:绘制出[0,1,2]和[3,4,5]两个三角形,第7个点由于没有匹配点而被忽略。
  • GL_TRIANGLE_STRIP:绘制出[0,1,2],[2,1,3],[2,3,4],[4,3,5],[4,5,6]共5个三角形(绘制出偶数下标[n,n+1,n+2]和奇数下标[n+1,n,n+2]共n-2个三角形)
  • GL_TRIANGLE_FAN:绘制出[0,1,2],[0,2,3],[0,3,4],[0,4,5],[0,5,6]等共享顶点的5个三角形(绘制出[0,n+1,n+2]共n-2个三角形)

9.2 绘制图元

OpenGL ES提供了五种绘制图元的函数,分别是glDrawArrays、glDrawElements、glDrawRangeElement、glDrawArraysInstanced和glDrawElementsInstanced。接下来分别介绍这几种方法。

9.2.1 glDrawArrays

void glDrawArrays (GLenum mode, GLint first, GLsizei count);

  • mode:指定图元枚举,9.1节中的任意一个。
  • first:指定从顶点数组中的何处开始绘制。
  • count:需要绘制的顶点数量。

示例代码:

    #define VERTEX_IND 0

    GLfloat VERTICES[]={...};
    glEnableVertexAttribArray(VERTEX_IND);
    glVertexAttribPointer(VERTEX_IND,3,GL_FLOAT,GL_FALSE,0,VERTICES);
    
    glDrawArrays(GL_TRIANGLES,0,3);

9.2.2 glDrawElements

该函数用来绘制图元,使用前需要创建图元索引列表。

void glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);

  • mode:指定图元枚举,9.1节中的任意一个。
  • count:指定要绘制的索引数量。
  • type:指定索引类型。
  • indices:索引数组。

示例代码:

    #define VERTEX_IND 0
    GLfloat VERTICES[]={
            0.1f,0.3f,0.4f,//0
            0.2f,0.5f,0.7f,//1
            0.9f,-0.3f,0.8f,//2
            0.4f,0.5f,-0.2f//3
    };
    GLubyte INDICES[]={
            0,1,2,
            3,2,1
    };
    glEnableVertexAttribArray(VERTEX_IND);
    glVertexAttribPointer(VERTEX_IND,3,GL_FLOAT,GL_FALSE,0,VERTICES);

    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_BYTE,INDICES);

9.2.3 glDrawRangeElement

void glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);

  • mode:指定图元枚举,9.1节中的任意一个。
  • start:指定图元索引列表中最小值(从顶点数组何处开始)。
  • end:指定图元索引列表中的最大值(从顶点数组何处结束)。
  • count:指定要绘制的索引数量。
  • type:指定索引类型。
  • indices:索引数组。

示例代码(本例限定了仅顶点坐标中1-6有效,那么此次就只会绘制[3,4,5]这个三角形):

    #define VERTEX_IND 0
    GLfloat VERTICES[] = {};//10个顶点
    GLubyte INDICES[] = {
            0, 1, 2,
            0, 2, 3,
            3, 4, 5,
            7, 8, 9
    };
    glEnableVertexAttribArray(VERTEX_IND);
    glVertexAttribPointer(VERTEX_IND, 3, GL_FLOAT, GL_FALSE, 0, VERTICES);

    glDrawRangeElements(GL_TRIANGLES, 1, 6, 12, GL_UNSIGNED_BYTE, INDICES);
}

9.3 图元装配光栅化过程

在图形经过顶点着色器处理之后,便进入了图元装配和光栅化的过程。其流程如下:

st=>start: 顶点着色器输出
cut=>inputoutput: 裁剪
split=>inputoutput: 透视分割
tran=>inputoutput: 窗口变换
culling=>inputoutput: 剔除
e=>end: 片元着色器输入

st->cut->split->tran->culling->e

9.3.1 裁剪

在某些时候,我们的图元肯能超出了屏幕能够显示的范围。这时候,就需要对这些图元进行裁剪。

  • 点精灵裁剪:如果整个点都位于视图之外,则放弃这个点,否则保留。
  • 直线裁剪:如果直线完全位于视图之外,则放弃全部。如果直线完全位于视图内,则全部保留。如果直线部分位置视图内,则重新计算并生成新的顶点。
  • 三角形裁剪:如果三角形全部位于视图之外,放弃全部顶点。如果三角形完全位于视图内,则保留全部顶点。如果三角形部分位于视图内,则重新计算并产生若干新的三角形顶点

9.3.2 透视分割

透视分割取得裁剪坐标指定的点,并将其投影到屏幕或者是视图上。在过程中坐标将被转换为规范化坐标,即[-1.0..1.0]区间。

9.3.3 视口变换

视口是一个二维矩形窗口区域,是所有OpenGL ES渲染操作最终显示的地方。
void glViewport(GLint x,GLint y,GLsizei w,GLsizei h);
这个常用的方法指定了一个视口的区域。

9.4 剔除

在图形被光栅化之前,我们需要确定它是正面或者反面,这样可以剔除掉不需要显示的图形,仅保留可见部分。在剔除之前我们需要告诉OpenGL正反面的标准是什么。对于三角形图元,我们仅仅需要注明当前已逆时针为正还是逆时针。

void glFrontFace (GLenum mode);

  • mode:旋转方向GL_CW顺时针,GL_CCW逆时针

当我们指定了区分正反的方法之后,接下来可以调用下列方法剔除特定的面。

void glCullFace (GLenum mode);

  • mode:指定我们需要剔除的方向GL_FRONT剔除正面、GL_BACK剔除背面、GL_FRONT_AND_BACK剔除正面和背面

9.5 光栅化

在进行完以上操作之后,光栅化管线取得了单独的图元,并为该图元生成相应的片元(具体的像素点)。然后每个像素点都会经过片元着色器处理。

10、绘制一个旋转立方体

本章内容为绘制一个旋转的立方体的教程。本章只展示JNI部分的编写(暂不详解),其他部分和之前相同,请自行实现。示例改编自OpenGL ES 3.0 编程指南 第七章示例代码目录结构如下:

NDK开发OpenGL ES 3.0(五)——一个立方体_第2张图片
10-1 目录部分


#define LOG_TAG "cube-lib"

#include "esUtil.h"
#include 
#include 

#define PI 3.14

#define POSITION_IND    0
#define COLOR_IND       1
#define MVP_IND         2
#define VERTEX_NUM      108
#define INDICES_NUM     36
#define MATRIX_COLUMN   4
#define MATRIX_ROW      4

GLuint program;
GLuint positionVBO;
GLuint colorVBO;
GLuint mvpVBO;
GLuint indicesIBO;
GLfloat aspect;
uint64_t lastFrameNs;
GLfloat angle;

const char VERTEX_SHADER[] =
        "#version 300 es\n"
                "layout(location = " STRV(POSITION_IND) ") in vec4 a_position;\n"
                "layout(location = " STRV(COLOR_IND) ") in vec4 a_color;\n"
                "layout(location = " STRV(MVP_IND) ") in mat4 a_mvpMatrix;\n"
                "out vec4 v_color;\n"
                "void main()\n"
                "{\n"
                "   v_color = a_color;\n"
                "   gl_Position = a_mvpMatrix * a_position;\n"
                "}\n";

const char FRAGMENT_SHADER[] =
        "#version 300 es\n"
                "precision mediump float;\n"
                "in vec4 v_color;\n"
                "layout(location = 0) out vec4 outColor;\n"
                "void main()\n"
                "{\n"
                "  outColor = v_color;\n"
                "}\n";

GLfloat VERTEX_POS[VERTEX_NUM] =
        {
                -0.5f, -0.5f, -0.5f,//0
                0.5f, -0.5f, 0.5f,//2
                -0.5f, -0.5f, 0.5f,//1
                -0.5f, -0.5f, -0.5f,//0
                0.5f, -0.5f, -0.5f,//3
                0.5f, -0.5f, 0.5f,//2
                -0.5f, 0.5f, -0.5f,//4
                -0.5f, 0.5f, 0.5f,//5
                0.5f, 0.5f, 0.5f,//6
                -0.5f, 0.5f, -0.5f,//4
                0.5f, 0.5f, 0.5f,//6
                0.5f, 0.5f, -0.5f,//7
                -0.5f, -0.5f, -0.5f,//0
                -0.5f, 0.5f, -0.5f,//4
                0.5f, 0.5f, -0.5f,//7
                -0.5f, -0.5f, -0.5f,//0
                0.5f, 0.5f, -0.5f,//7
                0.5f, -0.5f, -0.5f,//3
                -0.5f, -0.5f, 0.5f,//1
                0.5f, -0.5f, 0.5f,//2
                0.5f, 0.5f, 0.5f,//6
                -0.5f, -0.5f, 0.5f,//1
                0.5f, 0.5f, 0.5f,//6
                -0.5f, 0.5f, 0.5f,//5
                -0.5f, -0.5f, -0.5f,//0
                -0.5f, -0.5f, 0.5f,//1
                -0.5f, 0.5f, 0.5f,//5
                -0.5f, -0.5f, -0.5f,//0
                -0.5f, 0.5f, 0.5f,//5
                -0.5f, 0.5f, -0.5f,//4
                0.5f, -0.5f, -0.5f,//3
                0.5f, 0.5f, -0.5f,//7
                0.5f, 0.5f, 0.5f,//6
                0.5f, -0.5f, -0.5f,//3
                0.5f, 0.5f, 0.5f,//6
                0.5f, -0.5f, 0.5f//2
        };

const GLfloat cubeColor[] =
        {
                1.0f, 0.0f, 0.0f, 0.0f,
                1.0f, 0.0f, 0.0f, 0.0f,
                1.0f, 0.0f, 0.0f, 0.0f,
                1.0f, 0.0f, 0.0f, 0.0f,
                1.0f, 0.0f, 0.0f, 0.0f,
                1.0f, 0.0f, 0.0f, 0.0f,

                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,

                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,

                1.0f, 1.0f, 0.0f, 0.0f,
                1.0f, 1.0f, 0.0f, 0.0f,
                1.0f, 1.0f, 0.0f, 0.0f,
                1.0f, 1.0f, 0.0f, 0.0f,
                1.0f, 1.0f, 0.0f, 0.0f,
                1.0f, 1.0f, 0.0f, 0.0f,

                0.0f, 1.0f, 1.0f, 0.0f,
                0.0f, 1.0f, 1.0f, 0.0f,
                0.0f, 1.0f, 1.0f, 0.0f,
                0.0f, 1.0f, 1.0f, 0.0f,
                0.0f, 1.0f, 1.0f, 0.0f,
                0.0f, 1.0f, 1.0f, 0.0f,

                1.0f, 0.0f, 1.0f, 0.0f,
                1.0f, 0.0f, 1.0f, 0.0f,
                1.0f, 0.0f, 1.0f, 0.0f,
                1.0f, 0.0f, 1.0f, 0.0f,
                1.0f, 0.0f, 1.0f, 0.0f,
                1.0f, 0.0f, 1.0f, 0.0f
        };


typedef struct {
    GLfloat m[MATRIX_ROW][MATRIX_COLUMN];
} Matrix;

bool
init() {
    program = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
    if (!program)
        return false;

    glGenBuffers(1, &positionVBO);
    glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
    glBufferData(GL_ARRAY_BUFFER, VERTEX_NUM * sizeof(GLfloat), VERTEX_POS, GL_STATIC_DRAW);

    glGenBuffers(1, &colorVBO);
    glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
    glBufferData(GL_ARRAY_BUFFER, INDICES_NUM * 4 * sizeof(GLfloat), cubeColor, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
    glVertexAttribPointer(COLOR_IND, 4, GL_FLOAT,
                          GL_FALSE, 0, (const void *) NULL);
    glEnableVertexAttribArray(COLOR_IND);

    angle = float(drand48() * 360.0f);
    glGenBuffers(1, &mvpVBO);
    glBindBuffer(GL_ARRAY_BUFFER, mvpVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Matrix), NULL, GL_DYNAMIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

    glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
    glVertexAttribPointer(POSITION_IND, 3, GL_FLOAT,
                          GL_FALSE, 3 * sizeof(GLfloat), (const void *) NULL);
    glEnableVertexAttribArray(POSITION_IND);

    glBindBuffer(GL_ARRAY_BUFFER, mvpVBO);

    glVertexAttribPointer(MVP_IND + 0, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix),
                          (const void *) NULL);
    glVertexAttribPointer(MVP_IND + 1, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix),
                          (const void *) (sizeof(GLfloat) * 4));
    glVertexAttribPointer(MVP_IND + 2, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix),
                          (const void *) (sizeof(GLfloat) * 8));
    glVertexAttribPointer(MVP_IND + 3, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix),
                          (const void *) (sizeof(GLfloat) * 12));
    glEnableVertexAttribArray(MVP_IND + 0);
    glEnableVertexAttribArray(MVP_IND + 1);
    glEnableVertexAttribArray(MVP_IND + 2);
    glEnableVertexAttribArray(MVP_IND + 3);

    glVertexAttribDivisor(MVP_IND + 0, 1);
    glVertexAttribDivisor(MVP_IND + 1, 1);
    glVertexAttribDivisor(MVP_IND + 2, 1);
    glVertexAttribDivisor(MVP_IND + 3, 1);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesIBO);

    glUseProgram(program);

    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);

    return true;
}

void
matrixLoadIdentity(Matrix *result) {
    memset(result, 0, sizeof(Matrix));
    result->m[0][0] = 1.0f;
    result->m[1][1] = 1.0f;
    result->m[2][2] = 1.0f;
    result->m[3][3] = 1.0f;
}

void
matrixMultiply(Matrix *result, Matrix *srcA, Matrix *srcB) {
    Matrix tmp;
    int i;

    for (i = 0; i < 4; i++) {
        tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
                      (srcA->m[i][1] * srcB->m[1][0]) +
                      (srcA->m[i][2] * srcB->m[2][0]) +
                      (srcA->m[i][3] * srcB->m[3][0]);

        tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
                      (srcA->m[i][1] * srcB->m[1][1]) +
                      (srcA->m[i][2] * srcB->m[2][1]) +
                      (srcA->m[i][3] * srcB->m[3][1]);

        tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
                      (srcA->m[i][1] * srcB->m[1][2]) +
                      (srcA->m[i][2] * srcB->m[2][2]) +
                      (srcA->m[i][3] * srcB->m[3][2]);

        tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
                      (srcA->m[i][1] * srcB->m[1][3]) +
                      (srcA->m[i][2] * srcB->m[2][3]) +
                      (srcA->m[i][3] * srcB->m[3][3]);
    }

    memcpy(result, &tmp, sizeof(Matrix));
}

void
frustum(Matrix *result, float w, float h, float nearZ,
        float farZ) {
    float left = -w;
    float right = w;
    float bottom = -h;
    float top = h;
    float deltaX = right - left;
    float deltaY = top - bottom;
    float deltaZ = farZ - nearZ;
    Matrix frust;

    if ((nearZ <= 0.0f) || (farZ <= 0.0f) ||
        (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f)) {
        return;
    }

    frust.m[0][0] = 2.0f * nearZ / deltaX;
    frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;

    frust.m[1][1] = 2.0f * nearZ / deltaY;
    frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;

    frust.m[2][0] = (right + left) / deltaX;
    frust.m[2][1] = (top + bottom) / deltaY;
    frust.m[2][2] = -(nearZ + farZ) / deltaZ;
    frust.m[2][3] = -1.0f;

    frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
    frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;

    matrixMultiply(result, &frust, result);
}

void
translate(Matrix *result, GLfloat tx, GLfloat ty, GLfloat tz) {
    result->m[3][0] += (result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz);
    result->m[3][1] += (result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz);
    result->m[3][2] += (result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz);
    result->m[3][3] += (result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz);
}

void
rotate(Matrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
    GLfloat sinAngle, cosAngle;
    GLfloat mag = sqrtf(x * x + y * y + z * z);

    sinAngle = sinf(float(angle * PI / 180.0f));
    cosAngle = cosf(float(angle * PI / 180.0f));

    if (mag > 0.0f) {
        GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
        GLfloat oneMinusCos;
        Matrix rotMat;

        x /= mag;
        y /= mag;
        z /= mag;

        xx = x * x;
        yy = y * y;
        zz = z * z;
        xy = x * y;
        yz = y * z;
        zx = z * x;
        xs = x * sinAngle;
        ys = y * sinAngle;
        zs = z * sinAngle;
        oneMinusCos = 1.0f - cosAngle;

        rotMat.m[0][0] = (oneMinusCos * xx) + cosAngle;
        rotMat.m[0][1] = (oneMinusCos * xy) - zs;
        rotMat.m[0][2] = (oneMinusCos * zx) + ys;
        rotMat.m[0][3] = 0.0F;

        rotMat.m[1][0] = (oneMinusCos * xy) + zs;
        rotMat.m[1][1] = (oneMinusCos * yy) + cosAngle;
        rotMat.m[1][2] = (oneMinusCos * yz) - xs;
        rotMat.m[1][3] = 0.0F;

        rotMat.m[2][0] = (oneMinusCos * zx) - ys;
        rotMat.m[2][1] = (oneMinusCos * yz) + xs;
        rotMat.m[2][2] = (oneMinusCos * zz) + cosAngle;
        rotMat.m[2][3] = 0.0F;

        rotMat.m[3][0] = 0.0F;
        rotMat.m[3][1] = 0.0F;
        rotMat.m[3][2] = 0.0F;
        rotMat.m[3][3] = 1.0F;

        matrixMultiply(result, &rotMat, result);
    }
}

void
update(float deltaTime) {
    Matrix *matrixBuf;
    Matrix perspective;

    matrixLoadIdentity(&perspective);
    GLfloat frustumW, frustumH;

    frustumH = tanf(float(60.0f / 360.0f * PI)) * 1.5f;
    frustumW = frustumH * aspect;

    frustum(&perspective, frustumW, frustumH, 1.0f, 20.0f);

    glBindBuffer(GL_ARRAY_BUFFER, mvpVBO);
    matrixBuf = (Matrix *) glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(Matrix),
                                            GL_MAP_WRITE_BIT);

    Matrix modelview;

    matrixLoadIdentity(&modelview);

    translate(&modelview, 0, 0, -2.0f);

    angle += (deltaTime * 40.0f);
    if (angle >= 360.0f) {
        angle -= 360.0f;
    }

    rotate(&modelview, angle, 1.0, 0.0, 1.0);

    matrixMultiply(&matrixBuf[0], &modelview, &perspective);

    glUnmapBuffer(GL_ARRAY_BUFFER);
}

extern "C" {
JNIEXPORT jboolean JNICALL Java_com_github_cccxm_gles_model_CubeLib_init(JNIEnv *env, jclass type);
JNIEXPORT void JNICALL Java_com_github_cccxm_gles_model_CubeLib_resize(JNIEnv *env, jclass type,
                                                                       jint width, jint height);
JNIEXPORT void JNICALL Java_com_github_cccxm_gles_model_CubeLib_render(JNIEnv *env, jclass type);
JNIEXPORT void JNICALL Java_com_github_cccxm_gles_model_CubeLib_destroy(JNIEnv *env, jclass type);
}

jboolean
Java_com_github_cccxm_gles_model_CubeLib_init(JNIEnv *env, jclass type) {
    if (init())return JNI_TRUE;
    return JNI_FALSE;
}


void
Java_com_github_cccxm_gles_model_CubeLib_resize(JNIEnv *env, jclass type,
                                                jint width, jint height) {
    aspect = (GLfloat) width / (GLfloat) height;
    glViewport(0, 0, width, height);
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void
Java_com_github_cccxm_gles_model_CubeLib_render(JNIEnv *env, jclass type) {
    timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);
    auto nowNs = now.tv_sec * 1000000000ull + now.tv_nsec;
    if (lastFrameNs > 0) {
        float dt = float(nowNs - lastFrameNs) * 0.000000001f;
        update(dt);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    lastFrameNs = nowNs;
}

void
Java_com_github_cccxm_gles_model_CubeLib_destroy(JNIEnv *env, jclass type) {
    glDeleteBuffers(1, &positionVBO);
    glDeleteBuffers(1, &colorVBO);
    glDeleteBuffers(1, &mvpVBO);
    glDeleteBuffers(1, &indicesIBO);
    glDeleteProgram(program);
}

#undef LOG_TAG

下一篇:NDK开发OpenGL ES 3.0(六)——2D纹理贴图

你可能感兴趣的:(NDK开发OpenGL ES 3.0(五)——一个立方体)