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 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]
 */

package com.android.gljni;

import java.text.DecimalFormat;

import com.android.gljni.GLJNIView;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;

public class GLJNIActivity extends Activity {
	GLJNIView mView;
	TextView mTextView;

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		mView = new GLJNIView(getApplication());
		setContentView(mView);

		mView.setHandler(new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                // ???fps
                mTextView.setText("fps:"+msg.what);
            }
        }
        );

		mTextView = new TextView(this);
		mTextView.setText("fps:0");
		addContentView(mTextView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
	}

	@Override
	protected void onPause() {
		super.onPause();
		mView.onPause();
	}

	@Override
	protected void onResume() {
		super.onResume();
		mView.onResume();
	}
}

[GLJNIView.java]

/*
 * 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]
 */

package com.android.gljni;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.android.gljni.GLJNILib;
import com.android.gljnidemo08.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Handler;
import android.util.Log;

/**
 * A simple GLSurfaceView sub-class that demonstrate how to perform
 * OpenGL ES 1.x rendering into a GL Surface.
 */
public class GLJNIView extends GLSurfaceView {

	private static final String LOG_TAG = GLJNIView.class.getSimpleName();

	private Renderer renderer;

	public GLJNIView(Context context) {
		super(context);

		// setEGLConfigChooser会对fps产生影响
		setEGLConfigChooser(8, 8, 8, 8, 16, 0);

		renderer = new Renderer(context);
		setRenderer(renderer);
	}

	public void setHandler( Handler handler){
		renderer.setHandler(handler);
	}

	private static class Renderer implements GLSurfaceView.Renderer {
		//用于纹理映射的绑定,并把绑定后的ID传递给C++代码,供其调用
		private int[] mTexture = new int[2];
		//用于加载Bitmap的context
		private Context mContext;

		// 统计fps
		private Handler mHandler;
		private long mStartMili;
		private long mEndMili;
		private int mFps = 0;

		public Renderer(Context ctx) {
			mContext = ctx;
			mStartMili =System.currentTimeMillis();
		}

		public void setHandler( Handler handler){
			mHandler = handler;
		}

		public void onDrawFrame(GL10 gl) {

			GLJNILib.step();

			// 以一分钟绘制的帧数来统计fps
			mEndMili = System.currentTimeMillis();
			if( mEndMili - mStartMili > 1000 ){
				mHandler.sendEmptyMessageDelayed(mFps, 100);
				mStartMili = mEndMili;
				mFps = 0;
			}
			mFps++;
		}

		public void onSurfaceChanged(GL10 gl, int width, int height) {
			GLJNILib.resize(width, height);
		}

		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
			//用来绑定Bitmap纹理
			genTexture(gl, mContext);
			//调用本地setTexture方法,把纹理绑定的ID传递给C++代码,以供其调用
			GLJNILib.setTexture(mTexture);
			GLJNILib.init();
		}

		/**
		 * 加载Bitmap的方法,
		 * 用来从res中加载Bitmap资源
		 * */
		private Bitmap loadBitmap(Context context, int resourceId) {
			InputStream is = context.getResources().openRawResource(resourceId);
			Bitmap bitmap = null;
			try {

				// 利用BitmapFactory生成Bitmap
				bitmap = BitmapFactory.decodeStream(is);
			} finally {
				try {

					// 关闭流
					is.close();
					is = null;
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
			return bitmap;

		}

		/**
		 * 绑定Bitmap纹理
		 * */

		private void genTexture(GL10 gl, Context context) {
			//生成纹理
			gl.glGenTextures(2, mTexture, 0);
			//加载Bitmap
			Bitmap bitmap = loadBitmap(context, R.drawable.logo);
			if (bitmap != null) {
				//如果bitmap加载成功,则生成此bitmap的纹理映射
				gl.glBindTexture(GL10.GL_TEXTURE_2D, mTexture[0]);
				//设置纹理映射的属性
				gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
						GL10.GL_NEAREST);
				gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
						GL10.GL_NEAREST);
				//生成纹理映射
				GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
				//释放bitmap资源
				bitmap.recycle();
			}

		}
	}

}

[GLJNILib.java]

/*
 * 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]
 */

package com.android.gljni;

//Wrapper for native library
public class GLJNILib {

	static {
		System.loadLibrary("gljni");
	}

	/**
     * @param width the current view width
     * @param height the current view height
     */
	public static native void resize(int width, int height); 

	/**
	 * render
	 */
    public static native void step();  

    /**
     * init
     */
    public static native void init();  

    /**
     * set the texture
     * @param texture	texture id
     */
    public static native void setTexture(int[] texture);
}

[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:	2015/01/06
 * purpose:	旋转的纹理金字塔
 */

// 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__)

//初始化纹理数组
GLuint *gTexture = 0;

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

// 定义顶点坐标
#define pos 1.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,

	// 侧面
	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
};

// 定义纹理坐标
// 纹理坐标原点会因不同系统环境而有所不同。
// 比如在iOS以及Android上,纹理坐标原点(0, 0)是在左上角
// 而在OS X上,纹理坐标的原点是在左下角
static GLfloat texCoords[] = {
	// 地面拼接成一张整纹理
	0.0f, 1.0f,
	1.0f, 1.0f,
	1.0f, 0.0f,

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

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

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

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

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

// 旋转角度
static GLfloat gAngle = 0.0f;
/************************************************************************/
/*                             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);	

	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);
	// 重置当前的模型观察矩阵
	glLoadIdentity();

	glTranslatef(0,0,-10.0f);
	glRotatef(gAngle, 0, 1.0F, 0);
	glRotatef(gAngle, 0, 0, 1.0F);

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

	// 启用纹理映射
	glEnable(GL_TEXTURE_2D); 

	// 选择纹理
	glBindTexture(GL_TEXTURE_2D, gTexture[0]); 

	glVertexPointer(3,GL_FLOAT,0,gVertices);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

	glDrawArrays(GL_TRIANGLES, 0, 18);

	// 关闭顶点数组
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	//glDisableClientState(GL_OLOR_ARRAY);

	gAngle += 2.f;
}

/************************************************************************/
/*                          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_setTexture(JNIEnv * env, jclass obj, jintArray tex);
};

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();
}

JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_setTexture(JNIEnv * env, jclass obj, jintArray tex)
{
	gTexture = (GLuint *)env->GetIntArrayElements(tex,0);
}
时间: 2024-10-09 16:59:07

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

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里面不支持直接绘制正方形,所以需要将正方形拆分为两个三角形, 因此金字塔总共需要绘制5个三角形 立方体总共有8个顶点,我们在这里采用顶点索引的方式进行绘制 索引里面的值表示顶点的序号 两个立方体按照各自的中心进行旋转,关键代码如下 // 重

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的数据存放在显卡内存中,能节省从系统内存复制

Develop -- Training(十六) -- 显示绘图和OpenGL ES

Android framework提供了许多标准的工具,来创建有吸引力的.功能丰富的用户图形界面.但是,如果你想要更多的控制权,比如在应用程序的屏幕上绘图,或者冒险进入三维图形,你需要使用不同的工具.通过Android framework提供的OpenGL ES的API提供了一套显示高端的工具,动画图像超出你的想象,许多Android设备的图像处理单元得到了加速(GPUs). 这节课主要开发一个OpenGL应用程序.包括设置.画对象.移动对象元素.响应触摸输入事件. 这节课的示例代码使用的是Op

OpenGL ES 2.0 渲染管线 学习笔记

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

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

Android OpenGL ES 开发教程 从入门到精通

From:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

[转]Android OpenGL ES 开发教程 从入门到精通

本文转自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五