Opengl ES 1.x NDK实例开发之五:顶点缓存VBO

转自:http://blog.csdn.net/mnorst/article/details/40300191

本章在上一章的基础上讲解顶点缓存数组(Vertex Buffer Object)即VBO的使用,使用VBO来实现金字塔和立方体的绘制,绘制的效果和上一章相同。这个系列教程主要是采用实例演示 Opengl ES 1.x NDK开发,对一些要点进行解释,因此对API的用法和说明较少,建议初学者可以参考Opengl ES 1.x的API手册。


>>>为什么要使用VBO?
   VBO的数据存放在显卡内存中,能节省从系统内存复制到显卡内存中的时间,提高渲染的效率。
>>>VBO顶点缓存的使用范围?
   VBO可以缓存顶点、颜色、纹理坐标、索引。

【实例讲解】


本章示例了VBO缓存顶点、颜色和索引的用法。

【实例源码】

[GLJNIActivity.java]

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright (C) 2007 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  *  
  16.  * author: mnorst@foxmail.com 
  17.  */  
  18.   
  19. package com.android.gljni;  
  20.   
  21. import com.android.gljni.GLJNIView;  
  22.   
  23. import android.app.Activity;  
  24. import android.os.Bundle;  
  25.   
  26. public class GLJNIActivity extends Activity {  
  27.     GLJNIView mView;  
  28.   
  29.     @Override  
  30.     protected void onCreate(Bundle icicle) {  
  31.         super.onCreate(icicle);  
  32.         mView = new GLJNIView(getApplication());  
  33.         setContentView(mView);  
  34.     }  
  35.   
  36.     @Override  
  37.     protected void onPause() {  
  38.         super.onPause();  
  39.         mView.onPause();  
  40.     }  
  41.   
  42.     @Override  
  43.     protected void onResume() {  
  44.         super.onResume();  
  45.         mView.onResume();  
  46.     }  
  47. }  
[GLJNIView.java]

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright (C) 2007 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  *  
  16.  * author: mnorst@foxmail.com 
  17.  */  
  18.   
  19. package com.android.gljni;  
  20.   
  21. import javax.microedition.khronos.egl.EGLConfig;  
  22. import javax.microedition.khronos.opengles.GL10;  
  23.   
  24. import com.android.gljni.GLJNILib;  
  25.   
  26. import android.content.Context;  
  27. import android.opengl.GLSurfaceView;  
  28.   
  29. /** 
  30.  * A simple GLSurfaceView sub-class that demonstrate how to perform 
  31.  * OpenGL ES 1.x rendering into a GL Surface. 
  32.  */  
  33. public class GLJNIView extends GLSurfaceView {  
  34.   
  35.     private static final String LOG_TAG = GLJNIView.class.getSimpleName();  
  36.   
  37.     private Renderer renderer;  
  38.   
  39.     public GLJNIView(Context context) {  
  40.         super(context);  
  41.   
  42.         // setEGLConfigChooser会对fps产生影响  
  43.         setEGLConfigChooser(8888160);  
  44.   
  45.         renderer = new Renderer(context);  
  46.         setRenderer(renderer);  
  47.     }  
  48.   
  49.     private static class Renderer implements GLSurfaceView.Renderer {  
  50.   
  51.         public Renderer(Context ctx) {  
  52.   
  53.         }  
  54.   
  55.         public void onDrawFrame(GL10 gl) {  
  56.             GLJNILib.step();  
  57.         }  
  58.   
  59.         public void onSurfaceChanged(GL10 gl, int width, int height) {  
  60.             GLJNILib.resize(width, height);  
  61.         }  
  62.   
  63.         public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
  64.             GLJNILib.init();  
  65.         }  
  66.     }  
  67.   
  68. }  
[GLJNILib.java]

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright (C) 2007 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  *  
  16.  * author: mnorst@foxmail.com 
  17.  */  
  18.   
  19. package com.android.gljni;  
  20.   
  21. //Wrapper for native library  
  22. public class GLJNILib {  
  23.       
  24.     static {  
  25.         System.loadLibrary("gljni");  
  26.     }  
  27.   
  28.     /** 
  29.      * @param width the current view width 
  30.      * @param height the current view height 
  31.      */  
  32.     public static native void resize(int width, int height);   
  33.       
  34.     public static native void step();    
  35.       
  36.     public static native void init();    
  37. }  
[gl_code.cpp]

  1. /* 
  2.  * Copyright (C) 2007 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  *  
  16.  * author:  mnorst@foxmail.com 
  17.  * created: 2014/10/20 
  18.  * purpose: 顶点缓冲对象(VBO)的使用 
  19.  */  
  20.   
  21. // OpenGL ES 1.x code  
  22.   
  23. #include <jni.h>  
  24. #include <android/log.h>  
  25.   
  26. #include <GLES/gl.h>  
  27. #include <GLES/glext.h>  
  28.   
  29. #include <stdio.h>  
  30. #include <stdlib.h>  
  31. #include <math.h>  
  32.   
  33. /************************************************************************/  
  34. /*                             定义                                     */  
  35. /************************************************************************/  
  36.   
  37. #define  LOG_TAG    "libgljni"  
  38. #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
  39. #define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)  
  40.   
  41. // 定义π  
  42. const GLfloat PI = 3.1415f;  
  43.   
  44. // 旋转角度  
  45. static GLfloat gAngle = 0.0f;   
  46.   
  47. // 金字塔顶点数组  
  48. const GLfloat gVertices[] = {  
  49.   
  50.     // 底面:地面为正方形,拆分为两个三角形  
  51.     -1.0f,-1.0f,1.0f,  
  52.     1.0f,-1.0f,1.0f,  
  53.     1.0f,-1.0f, -1.0f,  
  54.   
  55.     1.0f,-1.0f,-1.0f,  
  56.     -1.0f,-1.0f,-1.0f,  
  57.     -1.0f,-1.0f,1.0f,  
  58.   
  59.     // 侧面:侧面为4个三角形  
  60.     0.0f, 1.0f, 0.0f,  
  61.     -1.0f,-1.0f, 1.0f,  
  62.     1.0f,-1.0f, 1.0f,  
  63.   
  64.     0.0f, 1.0f, 0.0f,  
  65.     1.0f,-1.0f, 1.0f,  
  66.     1.0f,-1.0f, -1.0f,  
  67.   
  68.     0.0f, 1.0f, 0.0f,  
  69.     1.0f,-1.0f, -1.0f,  
  70.     -1.0f,-1.0f, -1.0f,  
  71.   
  72.     0.0f, 1.0f, 0.0f,  
  73.     -1.0f,-1.0f,-1.0f,  
  74.     -1.0f,-1.0f, 1.0f  
  75. };  
  76. // 金字塔颜色数组  
  77. const GLfloat gColors[] = {  
  78.     1.0f,0.0f,0.0f, 1.0f,  
  79.     1.0f,0.0f,0.0f, 1.0f,  
  80.     1.0f,0.0f,0.0f, 1.0f,  
  81.   
  82.     1.0f,0.0f,0.0f, 1.0f,  
  83.     1.0f,0.0f,0.0f, 1.0f,  
  84.     1.0f,0.0f,0.0f, 1.0f,  
  85.   
  86.     1.0f,0.0f,0.0f, 1.0f,  
  87.     0.0f,1.0f,0.0f, 1.0f,  
  88.     0.0f,0.0f,1.0f, 1.0f,  
  89.   
  90.     1.0f,0.0f,0.0f, 1.0f,  
  91.     0.0f,0.0f,1.0f, 1.0f,  
  92.     0.0f,1.0f,0.0f, 1.0f,  
  93.   
  94.     1.0f,0.0f,0.0f, 1.0f,  
  95.     0.0f,0.0f,1.0f, 1.0f,  
  96.     0.0f,1.0f,0.0f, 1.0f,  
  97.   
  98.     1.0f,0.0f,0.0f, 1.0f,  
  99.     0.0f,0.0f,1.0f, 1.0f,  
  100.     0.0f,1.0f,0.0f, 1.0f,  
  101. };  
  102.   
  103.   
  104. // 立方体顶点数组  
  105. #define col 1.0f  
  106. #define pos 1.0f  
  107.   
  108. static GLfloat gVerticesSquare[] = {  
  109.     -pos,-pos,-pos, /*0*/  
  110.     -pos,-pos,pos,  /*1*/  
  111.     pos,-pos,pos,   /*2*/  
  112.     pos,-pos,-pos,  /*3*/  
  113.     -pos,pos,-pos,  /*4*/  
  114.     -pos,pos,pos,   /*5*/  
  115.     pos,pos,pos,    /*6*/  
  116.     pos,pos,-pos,   /*7*/  
  117. };  
  118. // 立方体顶点索引  
  119. static GLubyte gIndexSquare[] = {  
  120.     0,2,1,  0,3,2,  
  121.     5,1,6,  6,1,2,  
  122.     6,2,7,  7,2,3,  
  123.     0,4,3,  4,7,3,  
  124.     4,0,1,  4,1,5,  
  125.     4,5,6,  4,6,7,  
  126. };  
  127. // 立方体颜色数组  
  128. static GLfloat gColorsSquare[] = {  
  129.     col,0,0,col,  
  130.     0,col,0,col,  
  131.     0,0,col,col,  
  132.     col,col,0,col,  
  133.     col,0,col,col,  
  134.     0,col,col,col,  
  135.     0,0,0,col,  
  136.     col,col,col,col,  
  137. };  
  138.   
  139. GLuint gVerticesVBO;  
  140. GLuint gColorsVBO;  
  141. GLuint gVerticesSquareVBO;  
  142. GLuint gColorsSquareVBO;  
  143. GLuint gIndexSquareVBO;  
  144.   
  145. /************************************************************************/  
  146. /*                             C++代码                                  */  
  147. /************************************************************************/  
  148.   
  149. static void printGLString(const char *name, GLenum s) {  
  150.     const char *v = (const char *) glGetString(s);  
  151.     LOGI("GL %s = %s ", name, v);  
  152. }  
  153.   
  154. static void checkGlError(const char* op) {  
  155.     for (GLint error = glGetError(); error; error  
  156.         = glGetError()) {  
  157.             LOGI("after %s() glError (0x%x) ", op, error);  
  158.     }  
  159. }  
  160.   
  161. bool init() {  
  162.     printGLString("Version", GL_VERSION);  
  163.     printGLString("Vendor", GL_VENDOR);  
  164.     printGLString("Renderer", GL_RENDERER);  
  165.     printGLString("Extensions", GL_EXTENSIONS);  
  166.   
  167.     // 启用阴影平滑  
  168.     glShadeModel(GL_SMOOTH);  
  169.   
  170.     // 黑色背景   
  171.     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);     
  172.   
  173.     // 设置深度缓存     
  174.     glClearDepthf(1.0f);  
  175.   
  176.     // 启用深度测试  
  177.     glEnable(GL_DEPTH_TEST);      
  178.   
  179.     // 所作深度测试的类型      
  180.     glDepthFunc(GL_LEQUAL);   
  181.   
  182.     // 对透视进行修正    
  183.     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    
  184.   
  185.     // VBO相关处理  
  186.     // 金字塔  
  187.     glGenBuffers(1, &gVerticesVBO);  
  188.     glBindBuffer(GL_ARRAY_BUFFER, gVerticesVBO);  
  189.     glBufferData(GL_ARRAY_BUFFER, sizeof(gVertices), gVertices, GL_STATIC_DRAW);  
  190.     glGenBuffers(1, &gColorsVBO);  
  191.     glBindBuffer(GL_ARRAY_BUFFER, gColorsVBO);  
  192.     glBufferData(GL_ARRAY_BUFFER, sizeof(gColors), gColors, GL_STATIC_DRAW);  
  193.   
  194.     // 立方体  
  195.     glGenBuffers(1, &gVerticesSquareVBO);  
  196.     glBindBuffer(GL_ARRAY_BUFFER, gVerticesSquareVBO);  
  197.     glBufferData(GL_ARRAY_BUFFER, sizeof(gVerticesSquare), gVerticesSquare, GL_STATIC_DRAW);  
  198.     glGenBuffers(1, &gColorsSquareVBO);  
  199.     glBindBuffer(GL_ARRAY_BUFFER, gColorsSquareVBO);  
  200.     glBufferData(GL_ARRAY_BUFFER, sizeof(gColorsSquare), gColorsSquare, GL_STATIC_DRAW);  
  201.     glGenBuffers(1, &gIndexSquareVBO);  
  202.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIndexSquareVBO);  
  203.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(gIndexSquare), gIndexSquare, GL_STATIC_DRAW);  
  204.   
  205.     return true;  
  206. }  
  207.   
  208. static void _gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)  
  209. {  
  210.     GLfloat top = zNear * ((GLfloat) tan(fovy * PI / 360.0));  
  211.     GLfloat bottom = -top;  
  212.     GLfloat left = bottom * aspect;  
  213.     GLfloat right = top * aspect;  
  214.     glFrustumf(left, right, bottom, top, zNear, zFar);  
  215. }  
  216.   
  217. void resize(int width, int height)  
  218. {  
  219.     // 防止被零除  
  220.     if (height==0)                                
  221.     {  
  222.         height=1;  
  223.     }  
  224.   
  225.     // 重置当前的视口  
  226.     glViewport(0, 0, width, height);      
  227.     // 选择投影矩阵     
  228.     glMatrixMode(GL_PROJECTION);      
  229.     // 重置投影矩阵     
  230.     glLoadIdentity();                             
  231.   
  232.     // 设置视口的大小  
  233.     _gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);  
  234.   
  235.     // 选择模型观察矩阵  
  236.     glMatrixMode(GL_MODELVIEW);   
  237.   
  238.     // 重置模型观察矩阵  
  239.     glLoadIdentity();                             
  240. }  
  241.   
  242. void renderFrame() {  
  243.     // 清除屏幕及深度缓存  
  244.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
  245.     // 设置背景颜色为黑色  
  246.     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  
  247.     // 重置当前的模型观察矩阵  
  248.     glLoadIdentity();         
  249.       
  250.     // 启用顶点数组  
  251.     glEnableClientState(GL_VERTEX_ARRAY);  
  252.     // 启用颜色数组  
  253.     glEnableClientState(GL_COLOR_ARRAY);                  
  254.       
  255.     // 移入屏幕,便于图形显示  
  256.     glTranslatef(0.0f,2.0f,-10.0f);  
  257.   
  258.     // 绘制金字塔,采用VBO进行绘制  
  259.     glRotatef(gAngle,0.0f,1.0f,0.0f);  
  260.     glRotatef(gAngle,1.0f,0.0f,0.0f);  
  261.     ////glColorPointer(4, GL_FLOAT, 0, gColors);  
  262.     ////glVertexPointer(3, GL_FLOAT, 0, gVertices);  
  263.     ////glDrawArrays(GL_TRIANGLES, 0, 20);  
  264.     glBindBuffer(GL_ARRAY_BUFFER, gVerticesVBO);  
  265.     glVertexPointer(3, GL_FLOAT, 0, 0);  
  266.     glBindBuffer(GL_ARRAY_BUFFER, gColorsVBO);  
  267.     glColorPointer(4, GL_FLOAT, 0, 0);  
  268.     glDrawArrays(GL_TRIANGLES, 0, 20);  
  269.   
  270.       
  271.     // 绘制立方形,使用VBO进行绘制  
  272.     // 重置当前的模型观察矩阵  
  273.     glLoadIdentity();  
  274.     glTranslatef(0.0f, -2.0f,-10.0f);  
  275.     glRotatef(gAngle,0.0f,1.0f,0.0f);  
  276.     glRotatef(gAngle,1.0f,0.0f,0.0f);  
  277.   
  278. //  glVertexPointer(3,GL_FLOAT,0,gVerticesSquare);  
  279. //  glColorPointer(4,GL_FLOAT,0,gColorsSquare);  
  280.     glBindBuffer(GL_ARRAY_BUFFER, gVerticesSquareVBO);  
  281.     glVertexPointer(3,GL_FLOAT, 0, 0);  
  282.     glBindBuffer(GL_ARRAY_BUFFER, gColorsSquareVBO);  
  283.     glColorPointer(4, GL_FLOAT, 0, 0);  
  284.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIndexSquareVBO);  
  285.     glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_BYTE,0);  
  286.       
  287.     // 关闭顶点数组  
  288.     glDisableClientState(GL_VERTEX_ARRAY);  
  289.     // 关闭颜色数组  
  290.     glDisableClientState(GL_COLOR_ARRAY);                 
  291.   
  292.     // 增加旋转角度  
  293.     gAngle += 2.0f;  
  294. }  
  295.   
  296. /************************************************************************/  
  297. /*                          JNI代码                                     */  
  298. /************************************************************************/  
  299.   
  300. extern "C" {  
  301.     JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height);  
  302.     JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj);  
  303.     JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj);  
  304. };  
  305.   
  306. JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height)  
  307. {  
  308.     resize(width, height);  
  309. }  
  310.   
  311. JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj)  
  312. {  
  313.     renderFrame();  
  314. }  
  315.   
  316. JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj)  
  317. {  
  318.     init();  
  319. }  

原文地址:https://www.cnblogs.com/SunkingYang/p/11049181.html