OpenglES1.xNDK實例開發之(zhī)八:旋轉的(de)紋理金字塔
發表時(shí)間:2020-11-21
發布人(rén):融晨科技
浏覽次數:63
開發框架介紹請參見:Opengl ES NDK實例開發之(zhī)一:搭建開發框架
本章在(zài)第六章(Opengl ES 1.x NDK實例開發之(zhī)六:紋理貼圖)的(de)基礎上(shàng)繪制一個(gè)旋轉的(de)紋理金字塔,原理和(hé / huò)紋理貼圖一樣,需要(yào / yāo)注意的(de)是(shì)定好金字塔的(de)頂點數組和(hé / huò)紋理數組。
【實例講解】
[img]http://img.blog.csdn.net/20150107114535933?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW5vcnN0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
【實例源碼】
[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; @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: 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 { //用于(yú)紋理映射的(de)綁定,并把綁定後的(de)ID傳遞給C++代碼,供其調用 private int[] mTexture = new int[2]; //用于(yú)加載Bitmap的(de)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(); // 以(yǐ)一分鍾繪制的(de)幀數來(lái)統計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) { //用來(lái)綁定Bitmap紋理 genTexture(gl, mContext); //調用本地(dì / de)setTexture方法,把紋理綁定的(de)ID傳遞給C++代碼,以(yǐ)供其調用 GLJNILib.setTexture(mTexture); GLJNILib.init(); } /** * 加載Bitmap的(de)方法, * 用來(lái)從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的(de)紋理映射 gl.glBindTexture(GL10.GL_TEXTURE_2D, mTexture[0]); //設置紋理映射的(de)屬性 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 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: mnorst@foxmail.com * created: 2015/01/06 * purpose: 旋轉的(de)紋理金字塔 */ // 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 }; // 定義紋理坐标 // 紋理坐标原點會因不(bù)同系統環境而(ér)有所不(bù)同。 // 比如在(zài)iOS以(yǐ)及Android上(shàng),紋理坐标原點(0, 0)是(shì)在(zài)左上(shàng)角 // 而(ér)在(zài)OS X上(shàng),紋理坐标的(de)原點是(shì)在(zài)左下角 static GLfloat texCoords[] = { // 地(dì / de)面拼接成一張整紋理 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); // 所作深度測試的(de)類型 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; } // 重置當前的(de)視口 glViewport(0, 0, width, height); // 選擇投影矩陣 glMatrixMode(GL_PROJECTION); // 重置投影矩陣 glLoadIdentity(); // 設置視口的(de)大(dà)小 _gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); // 選擇模型觀察矩陣 glMatrixMode(GL_MODELVIEW); // 重置模型觀察矩陣 glLoadIdentity(); } void renderFrame() { // 清除屏幕和(hé / huò)深度緩存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 重置當前的(de)模型觀察矩陣 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); }