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

来源:互联网 发布:评价李鸿章 知乎 编辑:程序博客网 时间:2024/04/28 22:56

开发框架介绍请参见: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: mnorst@foxmail.com */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;@Overrideprotected 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));}@Overrideprotected void onPause() {super.onPause();mView.onPause();}@Overrideprotected 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: mnorst@foxmail.com */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的contextprivate Context mContext;// 统计fpsprivate 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();// 以一分钟绘制的帧数来统计fpsmEndMili = 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生成Bitmapbitmap = 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);//加载BitmapBitmap 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: mnorst@foxmail.com */package com.android.gljni;//Wrapper for native librarypublic 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 texturetexture 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: mnorst@foxmail.com * 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);}


1 0