您的位置:首页 > 运维架构

Opengl ES 1.x NDK实例开发之六:纹理贴图

2014-10-21 16:33 375 查看
开发框架介绍请参见: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: mnorst@foxmail.com

*/

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

}

}

[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.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: 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:	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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: