Opengl ES 1.x NDK实例开发之七:旋转的纹理立方体
开发框架介绍请參见:Opengl
ES NDK实例开发之中的一个:搭建开发框架
本章在第六章(Opengl ES 1.x NDK实例开发之六:纹理贴图)的基础上绘制一个旋转的纹理立方体,原理和纹理贴图一样,须要注意的是定好正方体的顶点数组。
【实例解说】
本实例加入了一个显示fps的小功能,在java层实现,原理是统计一分钟内屏幕刷新的次数
【实例源代码】
[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.gljnidemo07.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的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(); // 以一分钟绘制的帧数来统计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) {
//用来绑定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/27
* 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 // 定义顶点坐标
// 一个正方体有8个顶点,6个面
#define one 1.0f
static GLfloat gVertices[] = {
one, one, -one,
-one, one, -one,
one, one, one, -one, one, one,
one, -one,one,
-one, -one, one, one, -one, -one,
-one, -one, -one,
one, one,one, -one, one, one,
one, -one, one,
-one, -one, one, one, -one,-one,
-one, -one, -one,
one, one, -one, -one, one, -one,
-one, one,one,
-one, one, -one, -one, -one, one,
-one, -one, -one,
one, one,-one, one, one, one,
one, -one, -one,
one, -one, one
}; // 定义纹理坐标
// 纹理坐标原点会因不同系统环境而有所不同。
// 比方在iOS以及Android上,纹理坐标原点(0, 0)是在左上角
// 而在OS X上,纹理坐标的原点是在左下角
static GLfloat gTexCoords[] = {
0, one,
one, one,
0, 0,
one, 0, 0, one,
one, one,
0, 0,
one, 0, 0, one,
one, one,
0, 0,
one, 0, 0, one,
one, one,
0, 0,
one, 0, 0, one,
one, one,
0, 0,
one, 0, 0, one,
one, one,
0, 0,
one, 0, }; // 旋转角度
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, gTexCoords); for (int i = 0; i < 6; i++) {
glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
} // 关闭顶点数组
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisableClientState(GL_OLOR_ARRAY); gAngle += 5.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);
}
Opengl ES 1.x NDK实例开发之七:旋转的纹理立方体的更多相关文章
- Opengl ES 1.x NDK实例开发之六:纹理贴图
开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架 本章在第三章(Opengl ES 1.x NDK实例开发之三:多边形的旋转)的基础上演示怎样使用纹理贴图,分别实现了三角 ...
- OpenGL ES 画直线代码实例
http://blog.csdn.net/yexiaozi_007/article/details/7978620 以画xyz坐标轴为例,很多人会遇到用glcolor设置了颜色,但是直线画出来还是黑色 ...
- OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow
1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...
- OpenGL ES教程系列(经典合集)
为了搞透播放器的开发,花了些时间收集这些资料,虽然我已经搞定opengles渲染视频的内容,但是想玩玩opengles,往深里玩,图像处理这块是个好的方向,所以opengles是值得好好学的. O ...
- OpenGL ES 2.0 渲染管线 学习笔记
图中展示整个OpenGL ES 2.0可编程管线 图中Vertex Shader和Fragment Shader 是可编程管线: Vertex Array/Buffer objects 顶点数据来源, ...
- Android OpenGL ES 入门系列(二) --- 环境搭建
转载请注明出处 本文出自Hansion的博客 本章介绍如何使用GLSurfaceView和GLSurfaceView.Renderer完成在Activity中的最简单实现. 1.在AndroidMan ...
- OpenGL ES: (1) OpenGL ES的由来 (转)
1. 电脑是做什么用的? 电脑又被称为计算机,那么最重要的工作就是计算.看过三体的同学都知道, 电脑中有无数纳米级别的计算单元,通过 0 和 1 的转换,完成加减乘除的操作. 2. 是什么使电脑工作? ...
- 详解 OpenGL ES 2.x 渲染流程
khronos官方对OpenGL ES的描述如下: OpenGL ES is a royalty-free, cross-platform API for rendering advanced 2D ...
- 一文详解 OpenGL ES 3.x 渲染管线
OpenGL ES 构建的三维空间,其中的三维实体由许多的三角形拼接构成.如下图左侧所示的三维实体圆锥,其由许多三角形按照一定规律拼接构成.而组成圆锥的每一个三角形,其任意一个顶点由三维空间中 x.y ...
随机推荐
- vim全选复制
网上一堆答案全是ggyG,根本不行, 正确答案应该是 gg"*yG 或者 gg"*+yG 下面是在stack overflow 上找到的答案,亲测有效,在此记录下 stackove ...
- Melancholy(磨懒虫主义)
题目大意:给出n个地点和q个询问.其中每个地点有距离和权值,每个询问给出l,r,k,表示在[l,r]区间内不取最小点的情况下任取k个,求所有情况权值之积之和(n,q<=1e5,k<=6). ...
- [JOYOI] 1096 数字组合
题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...
- 关键css
参考: 掘金-JS和CSS的位置对资源加载顺序的影响 起舞-什么是关键CSS 有兴趣也可以看看这里一篇关于页面加载的文章.以上掘金那篇文章说css的加载不会影响其他资源的下载,但是我测试了一下,发现是 ...
- PHP调用webService WSDL 接口发送邮件
1.什么是 webService WSDL? webService WSDL 暴露一些接口给第三方调用,在底层会转化成一个HTTP请求,主要是不同语言之间为了通讯的一个协议,比如发送邮件的系统是用J ...
- p3386 二分图匹配模板
https://www.luogu.org/problemnew/show/P3386 可以只做一边的匹配 #include <bits/stdc++.h> using namespace ...
- 算法导论 第六章 2 优先队列(python)
优先队列: 物理结构: 顺序表(典型的是数组){python用到list} 逻辑结构:似完全二叉树 使用的特点是:动态的排序..排序的元素会增加,减少#和快速排序对比 快速一次排完 增 ...
- 主题:学习Spring必学的Java基础知识(9)----HTTP报文
转: 引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些 ...
- react 语法细节总结说明
1.当要获取某个数据列表中的某个字段时,用“.”附加的形式.例如:获取user中的balance字段,用this.props.user.balance 来表示. 2.当要打印某个数据或字段结果时,co ...
- POJ 1523 网络连通
题目大意: 给你一个网络组,每台机子与其他机子的关系,让你找到所有的割点,如果没有割点,输出无 这道题目就是最直接的求割点问题,我在这里用的是邻接矩阵来存储机子之间的关系 割点问题的求解需要对深度优先 ...