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;@Overrideprotected void onCreate(Bundle icicle) {super.onCreate(icicle);mView = new GLJNIView(getApplication());setContentView(mView);mView.setHandler(new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);// 显示fpsmTextView.setText("fps:"+msg.what);}});mTextView = new TextView(this);mTextView.setText("fps:0");addContentView(mTextView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));}@Overrideprotected void onPause() {super.onPause();mView.onPause();}@Overrideprotected 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的contextprivate Context mContext;// 统计fpsprivate 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();// 以一分钟绘制的帧数来统计fpsmEndMili = 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生成Bitmapbitmap = 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);//加载BitmapBitmap 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);
}
源码工程: http://download.csdn.net/detail/mnorst/8123375
Opengl ES 1.x NDK实例开发之七:旋转的纹理立方体相关推荐
- Opengl ES 1.x NDK实例开发之八:旋转的纹理金字塔
开发框架介绍请参见:Opengl ES NDK实例开发之一:搭建开发框架 本章在第六章(Opengl ES 1.x NDK实例开发之六:纹理贴图)的基础上绘制一个旋转的纹理金字塔,原理和纹理贴图一样, ...
- Android opengl es 3.0 + ndk 绘画涂鸦项目
前言 写一个opengl es 3.0 + ndk 的绘画涂鸦项目,命名为白板哈哈哈,记录自己遇到的问题,顺便学到的知识整合一遍,算是对自己一段时间的总结. 项目地址:Whiteboard 如果对你有 ...
- OpenGl文章
Android OpenGL ES 简明开发教程
Android OpenGL ES 简明开发教程 分类:android学习笔记2011-12-14 15:04375人阅读评论(0)收藏举报 ApiDemos 的Graphics示例中含有OpenGL ...
- Android项目开发教程之OpenGL ES
视频课:[免费]跨平台APP JQuery Mobile开发-1-初探移动开发-张晨光的在线视频教程-CSDN程序员研修院 学习内容 OpenGL ES的基本概念 Android下3D开发的基本知识 ...
- OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow
1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...
- 借助 OpenGL* ES 2.0 实现动态分辨率渲染
作者:omar-a-rodrigue 下载 借助 OpenGL* ES 2.0 实现动态分辨率渲染[PDF 677KB] 代码样本: dynamic-resolution.zip[ZIP 4MB] 像 ...
- Android OpenGL ES 从入门到精通系统性学习教程
1 为什么要写这个教程 目前这个 OpenGL ES 极简教程的更新暂时告一段落,在此之前,很荣幸获得了阮一峰老师的推荐. 因为在工作中频繁使用 OpenGL ES 做一些特效.滤镜之类的效果,加上平 ...
- 【我的OpenGL学习进阶之旅】OpenGL ES 3.0新功能
目录 1.1 纹理 1.2 着色器 1.3 几何形状 1.4 缓冲区对象 1.5 帧缓冲区 OpenGL ES 2.0 开创了手持设备可编程着色器的时代,在驱动大量设备的游戏.应用程序和用户接口中获得 ...
- android opengl es 2.0 编程指南,Android OpenGL ES 2.0 初次体验
本文目录 一. OpenGL ES是什么? 二. OpenGL ES的版本 三. EGL是什么? 四. 需要知道的两个方法 五. 在Android中使用OpenGL ES的步骤 六. 例子1:简单的程 ...
最新文章
- 视+AR获近亿元A+轮融资,汽车之家领投
- 曲线抽稀 java_Python实现曲线点抽稀算法
- C#中Lambda表达式类型Expression不接受lambda函数
- 《CDN 之我见》原理篇——CDN的由来与调度
- 存储引擎:engine
- android node编码,android studio中的Node.js
- 【先到先得】这款课程版 iPhone XR 免费送给你!
- CVPR2022 Oral | CosFace、ArcFace的大统一升级,AdaFace解决低质量图像人脸识
- OPenDDS程序 的 实现+运行
- 【JY】反应谱的详解与介绍
- 谷歌开源 Embedding Projector 高维数据可视化--转自开源中国
- 数据库导出数据字典(MySQL)
- 万网域名绑定阿里云服务器
- 成为UiBot Store推广员,解锁全新赚钱方式
- 论文笔记 EMNLP 2021|Modeling Document-Level Context for Event Detection via Important Context Selection
- SpringMVC-转换器与格式化
- 特征工程-使用随机森林进行缺失值填补
- mysql命令行安装教程_MySQL命令行教程
- 寒假算法训练1-J(分棍子,求最长棍子的数量,另外学习map的排序方法)
- 思博伦报告:伴随运营商寻求差异化优势,5G发展不断加速
热门文章
- halcon灰度积分投影/垂直积分投影
- 又是一年“云智”时,我们是ABC,将与人类对话!
- 聊聊 ES6 解构(下)
- linux图形界面鼠标变成小手_Linux 的成长之路:试用 1993-2003 年之间的 Linux 老版本系统...
- 鸿蒙之境浩然溟涬攻略,神都夜行录鸿蒙之境80级古都凶煞怎么打 神都夜行录鸿蒙之境80级古都凶煞打法_游戏堡...
- 一篇带你了解BIM+GIS,倾斜摄影,3Ds Max模型数据处理
- AI - 主流深度学习框架简介
- python bytearray转为byte_python:将bytearray转换为ctypes Struct
- PushBack Animation View
- 不能篡改内容的pushBack——BufferedInputStream深入解析