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

开发框架介绍请参见:Opengl ES NDK实例开发之一:搭建开发框架

本章在上一章的基础上讲解顶点缓存数组(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
plain
copy

  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: [email protected]
  17. */
  18. package com.android.gljni;
  19. import com.android.gljni.GLJNIView;
  20. import android.app.Activity;
  21. import android.os.Bundle;
  22. public class GLJNIActivity extends Activity {
  23. GLJNIView mView;
  24. @Override
  25. protected void onCreate(Bundle icicle) {
  26. super.onCreate(icicle);
  27. mView = new GLJNIView(getApplication());
  28. setContentView(mView);
  29. }
  30. @Override
  31. protected void onPause() {
  32. super.onPause();
  33. mView.onPause();
  34. }
  35. @Override
  36. protected void onResume() {
  37. super.onResume();
  38. mView.onResume();
  39. }
  40. }

[GLJNIView.java]

[java] view
plain
copy

  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: [email protected]
  17. */
  18. package com.android.gljni;
  19. import javax.microedition.khronos.egl.EGLConfig;
  20. import javax.microedition.khronos.opengles.GL10;
  21. import com.android.gljni.GLJNILib;
  22. import android.content.Context;
  23. import android.opengl.GLSurfaceView;
  24. /**
  25. * A simple GLSurfaceView sub-class that demonstrate how to perform
  26. * OpenGL ES 1.x rendering into a GL Surface.
  27. */
  28. public class GLJNIView extends GLSurfaceView {
  29. private static final String LOG_TAG = GLJNIView.class.getSimpleName();
  30. private Renderer renderer;
  31. public GLJNIView(Context context) {
  32. super(context);
  33. // setEGLConfigChooser会对fps产生影响
  34. setEGLConfigChooser(8, 8, 8, 8, 16, 0);
  35. renderer = new Renderer(context);
  36. setRenderer(renderer);
  37. }
  38. private static class Renderer implements GLSurfaceView.Renderer {
  39. public Renderer(Context ctx) {
  40. }
  41. public void onDrawFrame(GL10 gl) {
  42. GLJNILib.step();
  43. }
  44. public void onSurfaceChanged(GL10 gl, int width, int height) {
  45. GLJNILib.resize(width, height);
  46. }
  47. public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  48. GLJNILib.init();
  49. }
  50. }
  51. }

[GLJNILib.java]

[java] view
plain
copy

  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: [email protected]
  17. */
  18. package com.android.gljni;
  19. //Wrapper for native library
  20. public class GLJNILib {
  21. static {
  22. System.loadLibrary("gljni");
  23. }
  24. /**
  25. * @param width the current view width
  26. * @param height the current view height
  27. */
  28. public static native void resize(int width, int height);
  29. public static native void step();
  30. public static native void init();
  31. }

[gl_code.cpp]

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * author: 	[email protected]
 * created:	2014/10/20
 * purpose:	顶点缓冲对象(VBO)的使用
 */

// OpenGL ES 1.x code

#include <jni.h>
#include <android/log.h>

#include <GLES/gl.h>
#include <GLES/glext.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/************************************************************************/
/*                             定义                                     */
/************************************************************************/

#define  LOG_TAG    "libgljni"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

// 定义π
const GLfloat PI = 3.1415f;

// 旋转角度
static GLfloat gAngle = 0.0f; 

// 金字塔顶点数组
const GLfloat gVertices[] = {

	// 底面:地面为正方形,拆分为两个三角形
	-1.0f,-1.0f,1.0f,
	1.0f,-1.0f,1.0f,
	1.0f,-1.0f, -1.0f,

	1.0f,-1.0f,-1.0f,
	-1.0f,-1.0f,-1.0f,
	-1.0f,-1.0f,1.0f,

	// 侧面:侧面为4个三角形
	0.0f, 1.0f, 0.0f,
	-1.0f,-1.0f, 1.0f,
	1.0f,-1.0f, 1.0f,

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

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

	0.0f, 1.0f, 0.0f,
	-1.0f,-1.0f,-1.0f,
	-1.0f,-1.0f, 1.0f
};
// 金字塔颜色数组
const GLfloat gColors[] = {
	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, 1.0f,
	0.0f,1.0f,0.0f, 1.0f,
	0.0f,0.0f,1.0f, 1.0f,

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

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

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

// 立方体顶点数组
#define col 1.0f
#define pos 1.0f

static GLfloat gVerticesSquare[] = {
	-pos,-pos,-pos,	/*0*/
	-pos,-pos,pos,	/*1*/
	pos,-pos,pos,	/*2*/
	pos,-pos,-pos,	/*3*/
	-pos,pos,-pos,	/*4*/
	-pos,pos,pos,	/*5*/
	pos,pos,pos,	/*6*/
	pos,pos,-pos,	/*7*/
};
// 立方体顶点索引
static GLubyte gIndexSquare[] = {
	0,2,1,	0,3,2,
	5,1,6,	6,1,2,
	6,2,7,	7,2,3,
	0,4,3,	4,7,3,
	4,0,1,	4,1,5,
	4,5,6,	4,6,7,
};
// 立方体颜色数组
static GLfloat gColorsSquare[] = {
	col,0,0,col,
	0,col,0,col,
	0,0,col,col,
	col,col,0,col,
	col,0,col,col,
	0,col,col,col,
	0,0,0,col,
	col,col,col,col,
};

GLuint gVerticesVBO;
GLuint gColorsVBO;
GLuint gVerticesSquareVBO;
GLuint gColorsSquareVBO;
GLuint gIndexSquareVBO;

/************************************************************************/
/*                             C++代码                                  */
/************************************************************************/

static void printGLString(const char *name, GLenum s) {
	const char *v = (const char *) glGetString(s);
	LOGI("GL %s = %s\n", name, v);
}

static void checkGlError(const char* op) {
	for (GLint error = glGetError(); error; error
		= glGetError()) {
			LOGI("after %s() glError (0x%x)\n", op, error);
	}
}

bool init() {
	printGLString("Version", GL_VERSION);
	printGLString("Vendor", GL_VENDOR);
	printGLString("Renderer", GL_RENDERER);
	printGLString("Extensions", GL_EXTENSIONS);

	// 启用阴影平滑
	glShadeModel(GL_SMOOTH);

	// 黑色背景
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	

	// 设置深度缓存
	glClearDepthf(1.0f);

	// 启用深度测试
	glEnable(GL_DEPTH_TEST);	

	// 所作深度测试的类型
	glDepthFunc(GL_LEQUAL);	

	// 对透视进行修正
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	

	// VBO相关处理
	// 金字塔
	glGenBuffers(1, &gVerticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, gVerticesVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(gVertices), gVertices, GL_STATIC_DRAW);
	glGenBuffers(1, &gColorsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, gColorsVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(gColors), gColors, GL_STATIC_DRAW);

	// 立方体
	glGenBuffers(1, &gVerticesSquareVBO);
	glBindBuffer(GL_ARRAY_BUFFER, gVerticesSquareVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(gVerticesSquare), gVerticesSquare, GL_STATIC_DRAW);
	glGenBuffers(1, &gColorsSquareVBO);
	glBindBuffer(GL_ARRAY_BUFFER, gColorsSquareVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(gColorsSquare), gColorsSquare, GL_STATIC_DRAW);
	glGenBuffers(1, &gIndexSquareVBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIndexSquareVBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(gIndexSquare), gIndexSquare, GL_STATIC_DRAW);

	return true;
}

static void _gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
{
	GLfloat top = zNear * ((GLfloat) tan(fovy * PI / 360.0));
	GLfloat bottom = -top;
	GLfloat left = bottom * aspect;
	GLfloat right = top * aspect;
	glFrustumf(left, right, bottom, top, zNear, zFar);
}

void resize(int width, int height)
{
	// 防止被零除
	if (height==0)
	{
		height=1;
	}

	// 重置当前的视口
	glViewport(0, 0, width, height);
	// 选择投影矩阵
	glMatrixMode(GL_PROJECTION);
	// 重置投影矩阵
	glLoadIdentity();							

	// 设置视口的大小
	_gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

	// 选择模型观察矩阵
	glMatrixMode(GL_MODELVIEW);	

	// 重置模型观察矩阵
	glLoadIdentity();
}

void renderFrame() {
	// 清除屏幕及深度缓存
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// 设置背景颜色为黑色
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	// 重置当前的模型观察矩阵
	glLoadIdentity();		

	// 启用顶点数组
	glEnableClientState(GL_VERTEX_ARRAY);
	// 启用颜色数组
	glEnableClientState(GL_COLOR_ARRAY);				

	// 移入屏幕,便于图形显示
	glTranslatef(0.0f,2.0f,-10.0f);

	// 绘制金字塔,采用VBO进行绘制
	glRotatef(gAngle,0.0f,1.0f,0.0f);
	glRotatef(gAngle,1.0f,0.0f,0.0f);
	////glColorPointer(4, GL_FLOAT, 0, gColors);
	////glVertexPointer(3, GL_FLOAT, 0, gVertices);
	////glDrawArrays(GL_TRIANGLES, 0, 20);
	glBindBuffer(GL_ARRAY_BUFFER, gVerticesVBO);
	glVertexPointer(3, GL_FLOAT, 0, 0);
	glBindBuffer(GL_ARRAY_BUFFER, gColorsVBO);
	glColorPointer(4, GL_FLOAT, 0, 0);
	glDrawArrays(GL_TRIANGLES, 0, 20);

	// 绘制立方形,使用VBO进行绘制
	// 重置当前的模型观察矩阵
	glLoadIdentity();
	glTranslatef(0.0f, -2.0f,-10.0f);
	glRotatef(gAngle,0.0f,1.0f,0.0f);
	glRotatef(gAngle,1.0f,0.0f,0.0f);

//	glVertexPointer(3,GL_FLOAT,0,gVerticesSquare);
//	glColorPointer(4,GL_FLOAT,0,gColorsSquare);
	glBindBuffer(GL_ARRAY_BUFFER, gVerticesSquareVBO);
	glVertexPointer(3,GL_FLOAT, 0, 0);
	glBindBuffer(GL_ARRAY_BUFFER, gColorsSquareVBO);
	glColorPointer(4, GL_FLOAT, 0, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIndexSquareVBO);
	glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_BYTE,0);

	// 关闭顶点数组
	glDisableClientState(GL_VERTEX_ARRAY);
	// 关闭颜色数组
	glDisableClientState(GL_COLOR_ARRAY);				

	// 增加旋转角度
	gAngle += 2.0f;
}

/************************************************************************/
/*                          JNI代码                                     */
/************************************************************************/

extern "C" {
	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height);
	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj);
	JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj);
};

JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height)
{
	resize(width, height);
}

JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj)
{
	renderFrame();
}

JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj)
{
	init();
}
时间: 2024-10-07 11:58:09

Opengl ES 1.x NDK实例开发之五:顶点缓存VBO的相关文章

Opengl ES 1.x NDK实例开发之七:旋转的纹理立方体

开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架 本章在第六章(Opengl ES 1.x NDK实例开发之六:纹理贴图)的基础上绘制一个旋转的纹理立方体,原理和纹理贴图一样,须要注意的是定好正方体的顶点数组. [实例解说] 本实例加入了一个显示fps的小功能,在java层实现,原理是统计一分钟内屏幕刷新的次数 [实例源代码] [GLJNIActivity.java] /* * Copyright (C) 2007 The Android Open Source P

Opengl ES 1.x NDK实例开发之六:纹理贴图

开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架 本章在第三章(Opengl ES 1.x NDK实例开发之三:多边形的旋转)的基础上演示怎样使用纹理贴图,分别实现了三角形纹理贴图和正方形纹理贴图. [实例解说] OpenglES要求生成纹理的图片长宽为2的n次方.支持各种格式(BMP, GIF, JPEG, PNG...) 本例中使用的图片为png格式,尺寸为128*128 本例中,在上层GLJNIView.java中生成纹理.将纹理句柄传递给Native层进行绘

Opengl ES 1.x NDK实例开发之八:旋转的纹理金字塔

开发框架介绍请参见:Opengl ES NDK实例开发之一:搭建开发框架 本章在第六章(Opengl ES 1.x NDK实例开发之六:纹理贴图)的基础上绘制一个旋转的纹理金字塔,原理和纹理贴图一样,需要注意的是定好金字塔的顶点数组和纹理数组. [实例讲解] [实例源码] [GLJNIActivity.java] /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache Licens

Opengl ES 1.x NDK实例开发之四:立方体的旋转

开发框架介绍请参见:Opengl ES NDK实例开发之一:搭建开发框架 [实例讲解] 本章在第三章的基础上讲解如何绘制立方体并按照各自的中心进行旋转 绘制立方体实际上是绘制立方体的各个面,其中金字塔包括三个三角形侧面和一个正方形底面, 因为opengl ES里面不支持直接绘制正方形,所以需要将正方形拆分为两个三角形, 因此金字塔总共需要绘制5个三角形 立方体总共有8个顶点,我们在这里采用顶点索引的方式进行绘制 索引里面的值表示顶点的序号 两个立方体按照各自的中心进行旋转,关键代码如下 // 重

iOS开发-OpenGL ES入门教程1

http://www.jianshu.com/p/750fde1d8b6a 这里是一篇新手教程,环境是Xcode7+OpenGL ES 2.0,目标写一个OpenGL ES的hello world.OpenGL ES系列教程在这里.OpenGL ES系列教程的代码地址 你的star和fork是我的源动力,你的意见能让我走得更远. 核心思路 通过GLKit,尽量简单地实现把一张图片绘制到屏幕. 效果展示 具体细节 1.新建OpenGL ES上下文 - (void)setupConfig { //新

OpenGL ES教程系列(经典合集)

为了搞透播放器的开发,花了些时间收集这些资料,虽然我已经搞定opengles渲染视频的内容,但是想玩玩opengles,往深里玩,图像处理这块是个好的方向,所以opengles是值得好好学的. OpenGL ES教程原创系列 2011-12-18[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之二:lib3ds加载模型 2011-12-17[iTyran原创]GLKit 矩阵变换:自转公转 2011-12-02[iTyran原创]Xcode创建的默认iOS OpenGL

[转] iOS OpenGL ES Guide

OpenGL ES 小结 概述 OpenGL ES (Open Graphics Library for Embedded Systems)是访问类似 iPhone 和 iPad 的现代嵌入式系统的 2D 和 3D 图形加速硬件的标准. 把程序提供的几何数据转换为屏幕上的图像的过程叫做渲染. GPU 控制的缓存是高效渲染的关键.容纳几何数据的缓存定义了要渲染的点.线段和三角形. OpenGL ES 3D 的默认坐标系.顶点和矢量为几何数据的描述提供了数学基础. 渲染的结果通常保存在帧缓存中.有两

OpenGL ES 2.0 渲染管线 学习笔记

图中展示整个OpenGL ES 2.0可编程管线 图中Vertex Shader和Fragment Shader 是可编程管线: Vertex Array/Buffer objects 顶点数据来源,这时渲染管线的顶点输入,通常使用 Buffer objects效率更好. Vertex Shader 顶点着色器通过矩阵变换位置.计算照明公式来生成逐顶点颜色已经生成或变换纹理坐标等基于顶点的操作. Primitive Assembly 图元装配经过着色器处理之后的顶点在图片装配阶段被装配为基本图元

Android OpenGL ES(七)基本几何图形定义 .

在前面Android OpenGL ES(六):创建实例应用OpenGLDemos程序框架 我们创建了示例程序的基本框架,并提供了一个“Hello World”示例,将屏幕显示为红色. 本例介绍OpenGL ES 3D图形库支持的几种基本几何图形,通常二维图形库可以绘制点,线,多边形,圆弧,路径等等.OpenGL ES 支持绘制的基本几何图形分为三类:点,线段,三角形.也就是说OpenGL ES 只能绘制这三种基本几何图形.任何复杂的2D或是3D图形都是通过这三种几何图形构造而成的. 比如下图复