Opengl ES 1.x NDK實例開發之六:紋理貼圖
阿新 • • 發佈:2017-08-04
otto absolute decode super rep mit his viewport 一個
[[gl_code.cpp]
開發框架介紹請參見:Opengl ES NDK實例開發之中的一個:搭建開發框架
本章在第三章(Opengl ES 1.x NDK實例開發之三:多邊形的旋轉)的基礎上演示怎樣使用紋理貼圖,分別實現了三角形紋理貼圖和正方形紋理貼圖。
【實例解說】
OpenglES要求生成紋理的圖片長寬為2的n次方。支持各種格式(BMP, GIF, JPEG, PNG...)
本例中使用的圖片為png格式,尺寸為128*128
本例中,在上層GLJNIView.java中生成紋理。將紋理句柄傳遞給Native層進行繪制。詳見
private void genTexture(GL10 gl, Context context)
【實例源代碼】
[GLJNIActivity.java]
[java] view plaincopy
- /*
- * 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 com.android.gljni.GLJNIView;
- import android.app.Activity;
- import android.os.Bundle;
- public class GLJNIActivity extends Activity {
- GLJNIView mView;
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mView = new GLJNIView(getApplication());
- setContentView(mView);
- }
- @Override
- protected void onPause() {
- super.onPause();
- mView.onPause();
- }
- @Override
- protected void onResume() {
- super.onResume();
- mView.onResume();
- }
- }
/* * 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.gljnidemo06.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLSurfaceView; import android.opengl.GLUtils; 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); } private static class Renderer implements GLSurfaceView.Renderer { //用於紋理映射的綁定,並把綁定後的ID傳遞給C++代碼。供其調用 private int[] mTexture = new int[2]; //用於載入Bitmap的context private Context mContext; public Renderer(Context ctx) { mContext = ctx; } public void onDrawFrame(GL10 gl) { GLJNILib.step(); } 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: 2014/10/20 * 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; // 旋轉角度 static GLfloat gAngle = 0.0f; // 頂點數組 const GLfloat gVertices[] = { 0.0f, 1.0f, 0.0f, // 上 -1.0f,-1.0f, 0.0f, // 左下 1.0f,-1.0f, 0.0f, // 右下 }; const GLfloat gVerticesSquare[] = { -1.0f, -1.0f, 0.0f, // 左下 1.0f, -1.0f, 0.0f, // 右下 -1.0f, 1.0f, 0.0f, // 左上 1.0f, 1.0f, 0.0f // 右上 }; // 紋理坐標 // 紋理坐標原點會因不同系統環境而有所不同。 // 比方在iOS以及Android上,紋理坐標原點(0, 0)是在左上角 // 而在OS X上,紋理坐標的原點是在左下角 const GLfloat gTextureCoord[] = { 0.5f,0.0f, 0.0f,1.0f, 1.0f,1.0f, }; const GLfloat gTextureSquareCoord[] = { 0.0f,1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f,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); // 設置背景顏色為黑色 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 重置當前的模型觀察矩陣 glLoadIdentity(); // 啟用頂點數組 glEnableClientState(GL_VERTEX_ARRAY); glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // 紋理設置 glEnable(GL_TEXTURE_2D); // 啟用紋理映射 glBindTexture(GL_TEXTURE_2D, gTexture[0]); // 選擇紋理 glEnableClientState(GL_TEXTURE_COORD_ARRAY); // 啟用紋理坐標數組 // 繪制三角形 glTranslatef(0.0f,2.0f,-10.0f); // 設置三角形位置 glRotatef(gAngle,0.0f,1.0f,0.0f); // 旋轉三角形 glVertexPointer(3, GL_FLOAT, 0, gVertices); // 指定頂點數組 glTexCoordPointer(2, GL_FLOAT, 0, gTextureCoord); // 設置紋理坐標 glDrawArrays(GL_TRIANGLES, 0, 3); // 繪制三角形 // 繪制正方形 glTranslatef(0.0f,-4.0f,0.0f); // 設置正方形位置 glRotatef(-gAngle*2,0.0f,1.0f,0.0f); // 旋轉正方形 glVertexPointer(3, GL_FLOAT, 0, gVerticesSquare); // 指定頂點數組 glTexCoordPointer(2, GL_FLOAT, 0, gTextureSquareCoord); // 設置紋理坐標 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // 繪制正方形 // 關閉頂點數組 glDisableClientState(GL_VERTEX_ARRAY); // 關閉紋理數組 glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); // 添加旋轉角度 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_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); }
Opengl ES 1.x NDK實例開發之六:紋理貼圖