1. 程式人生 > >Opengl ES 1.x NDK例項開發之六:紋理貼圖

Opengl ES 1.x 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]

  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. publicclass GLJNIActivity extends Activity {  
  23.     GLJNIView mView;  
  24.     @Override
  25.     protectedvoid onCreate(Bundle icicle) {  
  26.         super.onCreate(icicle);  
  27.         mView = new GLJNIView(getApplication());  
  28.         setContentView(mView);  
  29.     }  
  30.     @Override
  31.     protectedvoid onPause() {  
  32.         super.onPause();  
  33.         mView.onPause();  
  34.     }  
  35.     @Override
  36.     protectedvoid onResume() {  
  37.         super.onResume();  
  38.         mView.onResume();  
  39.     }  
  40. }  
[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.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例項開發:紋理

本章在第三章(Opengl ES 1.x NDK例項開發之三:多邊形的旋轉)的基礎上演示如何使用紋理貼圖,分別實現了三角形紋理貼圖和正方形紋理貼圖。 【例項講解】 OpenglES要求生成紋理的圖片長寬為2的n次方,支援各種格式(BMP, GIF, JPEG, PNG..

Opengl ES 1.x NDK例項開發三:多邊形的旋轉

【例項講解】 本章在第二章的基礎上講解多邊形的旋轉 上圖中的三角形和四邊形沿著Y軸旋轉 【例項原始碼】 [GLJNIActivity.java] /*   * Copyright (C) 2007 The Android Open Source Proje

Opengl ES 1.x NDK實例開發:紋理

otto absolute decode super rep mit his viewport 一個 開發框架介紹請參見:Opengl ES NDK實例開發之中的一個:搭建開發框架 本章在第三章(Opengl ES 1.x NDK實例開發之三:多邊形的旋轉)的基礎

OpenGL ES OpenGL ES 1.X的渲染管線

本文圖片和內容來自 <Android 3D 遊戲開發技術寶典> OpenGL ES 是OpenGL三維圖形API的子集,主要針對手機等嵌入式裝置。 OpenGL ES主要分為兩個版本 一個是Ope

OpenGL ES (1): OPenGL-ES介紹

1.OPenGL簡述 OPenGL(Open Graphics Library):開放圖形介面,是一套跨程式語言,跨平臺的程式設計介面規範,主要用於三維圖形程式設計(二維也可以)。 但是三維圖形的計算需要處理大量的資料,所以OpenGL不適於應用在小型裝置上如手機。 O

Ext Net 1 x Ext Net GridPanel 鎖定列

                在EXCEL表中經常有需要鎖定列的在GIRDPANEL中如何實現呢? 一:列屬性增加LOCKED="TRUE"            <Columns>                <ext:RowNumbererColumn  Locked="true"

【COCOS2DX-LUA 指令碼開發】利用Lua強轉函式解決使用CCNode報錯或無法正常使用以及簡單介紹 quick-cocos2d-x 與 OpenQuick 兩款Lua免費開源框架

Him 的Cocos2dx-Lua群中有童鞋出現一個問題,問題是當他在Lua專案中利用Lua建立一個區域性變數CCSprite或者CCLayer等CCNode,然後在其他的函式中通過其索引取出之前建立過的CCSprite或CCLayer等,取出後進行設定設定透明、座標、縮放、

angularjs 1.x自定義指令控制器與指令間的通訊

一、在指令中呼叫控制器裡定義的方法 //html <div ng-controller="MyCtrl"> <loader howToLoad="loadData

2.x終於照著教程,成功使用OpenGL ES 繪製紋理,增加了灰度

在之前成功繪製變色的幾何圖形之後,今天利用Openg ES的可程式設計管線繪製出第一張紋理。學校時候不知道OpenGL的重要性,怕晦澀的語法,沒有跟老師學習OpenGL的環境配置,如今只能利用cocos2dx 2.2.3 配置好的環境學習OpenGL ES。原始碼來自《co

asp.net core 3.x 模組化開發HostingStartup

我們希望將一個專案(dll)看做一個模組/外掛,一個模組往往需要在應用啟動時做一些初始化工作,比如向IOC容器新增一些服務,為應用配置物件新增自己的資料來源;也希望在應用關閉時做一些收尾工作,asp.net core為我們提供了這種機制,先來看看如何使用,再講講原理。 如何使用? 1、建立asp.net

swift開發 -- 自動輪播(UIScrollView+UIPageControl+Timer)

mode nal uipage logs swift es2017 ida lin true 比較簡單,原理就不說了,這裏只做記錄: 代碼如下: 1,準備 var pageControl:UIPageControl? var myscrollView:UIScro

ios開發 -- 自動輪播創建

ide targe info self spl enabled static repeat display 這裏是oc版本的,簡單記錄下: 具體代碼如下: 1,準備 #define FRAME [[UIScreen mainScreen] bounds] #define

Unity遊戲開發“屏幕截

texture apt 項目 一個 art error topn details camera2 下面是我總結的、在u3d中的,三種截屏方法:1、使用Application類下的CaptureScreenshot方法。void CaptureScreen() { Ap

python網頁爬蟲開發-Selenium使用

scrip python ref ges 加載圖片 browser 網頁加載 content 很慢 chromedriver禁用圖片,禁用js,切換UA selenium 模擬chrome瀏覽器,此時就是一個真實的瀏覽器,一個瀏覽器該加載的該渲染的它都加載都渲染,所以爬取

android平臺下OpenGL ES 3.0實現2D紋理顯示bitmap

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

OpenGL ES (3):平面圖形-表面紋理

1.簡介 上一篇已經將一個平面圖形繪製出來了,這一次我們將在上一次繪製出來的圖形的表面上進行紋理貼圖。 圖片準備:(寬高須為2的N次方) 最終圖片是以Bitmap形式。現在考慮如何把這張圖片對映到繪製的平面上? 所以這裡也需要一個數組float[] 用於設定紋理座

OpenGL ES (16): 紋理

1.前言 圖片如下:紋理座標為 左上角為(0,0),右下角為(1,1) 我們繪製一個正方形,頂點座標資料如下: 此次程式碼不包含z軸,預設為0。 要做的事就是把圖片貼到正方形的表面,並繪製出正方形。 所以上面的紋理座標和頂點座標的順序要一致。這樣繪製的圖片才

Web前端—前端高效開發“一鍵切”教程

            作為一名Web前端人員,工作中難免都會要接觸切圖這一塊,那麼如何把圖快速切好且又不浪費時間呢?相信很多人切圖都是先把圖片放大再使用矩形工具或切片工具來切圖,這樣其實好麻煩且有時

Ambari 2.1安裝HDP2.3.2 、安裝部署HDP叢集 詳細步驟

六、安裝部署HDP叢集 瀏覽器訪問 http://master:8080,進入amabri登入頁面,使用者名稱:admin,密碼: admin 選擇 Launch Install Wizard: 1. Get started 給叢集起個名字

Android OpenGL ES正方體紋理(每個面一張)

正方體的紋理貼圖步驟如下: 1.陣列 1.1:頂點陣列 1.2:三角形 1.3:貼圖陣列 2.onSurfaceChanged:與3D的一樣 3.onSurfaceCreated:需要新增東西 3.1允許2D貼圖gl.glEnable(GL10.GL_TEXTURE_2D