Android OpenGL ES 画球体
最近因为兴趣所向,开始学习OpenGL绘图。本文以“画球体”为点,小结一下最近所学。
> 初识OpenGL ES
然后,如果想要实现比较复杂的效果(比如3D),Canvas就很难胜任了。了解了一下,目前大部分Android游戏都是用OpenGL来实现。
OpenGL是何方神圣?实际上,最终图像(不管是2D还是3D)都是显示在显示屏上,所以最终操作肯定是对一个2D的显示内存进行操作的。而OpenGL就是提供了很多方法,帮助我们定义空间立体模型,然后通过我们输入的各种参数,计算出映射矩阵,最终在显示屏幕上体现出效果。
OpenGL ES (OpenGL for Embedded Systems)是专门OpenGL的API子集,专门用于手机等嵌入式平台。简单理解就是,专门开发给“低端”的环境。删减了很多不必要的方法,留下了最基本的。
> 使用OpenGL ES画图
> 使用三角形构成空间球体
> 球面顶点坐标计算
> 源码
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;public class OpenGLRenderer4 implements Renderer {// 环境光private final float[] mat_ambient = { 0.2f, 0.3f, 0.4f, 1.0f };private FloatBuffer mat_ambient_buf;// 平行入射光private final float[] mat_diffuse = { 0.4f, 0.6f, 0.8f, 1.0f };private FloatBuffer mat_diffuse_buf;// 高亮区域private final float[] mat_specular = { 0.2f * 0.4f, 0.2f * 0.6f, 0.2f * 0.8f, 1.0f };private FloatBuffer mat_specular_buf;private Sphere mSphere = new Sphere();public volatile float mLightX = 10f;public volatile float mLightY = 10f;public volatile float mLightZ = 10f;@Overridepublic void onDrawFrame(GL10 gl) {// 清楚屏幕和深度缓存gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 重置当前的模型观察矩阵gl.glLoadIdentity();gl.glEnable(GL10.GL_LIGHTING);gl.glEnable(GL10.GL_LIGHT0);// 材质gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, mat_ambient_buf);gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, mat_diffuse_buf);gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, mat_specular_buf);// 镜面指数 0~128 越小越粗糙gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 96.0f);//光源位置float[] light_position = {mLightX, mLightY, mLightZ, 0.0f};ByteBuffer mpbb = ByteBuffer.allocateDirect(light_position.length*4);mpbb.order(ByteOrder.nativeOrder());FloatBuffer mat_posiBuf = mpbb.asFloatBuffer();mat_posiBuf.put(light_position);mat_posiBuf.position(0);gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, mat_posiBuf);gl.glTranslatef(0.0f, 0.0f, -3.0f);mSphere.draw(gl);}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 设置输出屏幕大小gl.glViewport(0, 0, width, height);// 设置投影矩阵gl.glMatrixMode(GL10.GL_PROJECTION);// 重置投影矩阵gl.glLoadIdentity();// 设置视口大小// gl.glFrustumf(0, width, 0, height, 0.1f, 100.0f);GLU.gluPerspective(gl, 90.0f, (float) width / height, 0.1f, 50.0f);// 选择模型观察矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);// 重置模型观察矩阵gl.glLoadIdentity();}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig arg1) {// 对透视进行修正gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);// 背景:黑色gl.glClearColor(0, 0.0f, 0.0f, 0.0f);// 启动阴影平滑gl.glShadeModel(GL10.GL_SMOOTH);// 复位深度缓存gl.glClearDepthf(1.0f);// 启动深度测试gl.glEnable(GL10.GL_DEPTH_TEST);// 所做深度测试的类型gl.glDepthFunc(GL10.GL_LEQUAL);initBuffers();}private void initBuffers() {ByteBuffer bufTemp = ByteBuffer.allocateDirect(mat_ambient.length * 4);bufTemp.order(ByteOrder.nativeOrder());mat_ambient_buf = bufTemp.asFloatBuffer();mat_ambient_buf.put(mat_ambient);mat_ambient_buf.position(0);bufTemp = ByteBuffer.allocateDirect(mat_diffuse.length * 4);bufTemp.order(ByteOrder.nativeOrder());mat_diffuse_buf = bufTemp.asFloatBuffer();mat_diffuse_buf.put(mat_diffuse);mat_diffuse_buf.position(0);bufTemp = ByteBuffer.allocateDirect(mat_specular.length * 4);bufTemp.order(ByteOrder.nativeOrder());mat_specular_buf = bufTemp.asFloatBuffer();mat_specular_buf.put(mat_specular);mat_specular_buf.position(0);}
}
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;import javax.microedition.khronos.opengles.GL10;// 计算球面顶点
public class Sphere {public void draw(GL10 gl) {float angleA, angleB;float cos, sin;float r1, r2;float h1, h2;float step = 30.0f;float[][] v = new float[32][3];ByteBuffer vbb;FloatBuffer vBuf;vbb = ByteBuffer.allocateDirect(v.length * v[0].length * 4);vbb.order(ByteOrder.nativeOrder());vBuf = vbb.asFloatBuffer();gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);for (angleA = -90.0f; angleA < 90.0f; angleA += step) {int n = 0;r1 = (float)Math.cos(angleA * Math.PI / 180.0);r2 = (float)Math.cos((angleA + step) * Math.PI / 180.0);h1 = (float)Math.sin(angleA * Math.PI / 180.0);h2 = (float)Math.sin((angleA + step) * Math.PI / 180.0);// 固定纬度, 360 度旋转遍历一条纬线for (angleB = 0.0f; angleB <= 360.0f; angleB += step) {cos = (float)Math.cos(angleB * Math.PI / 180.0);sin = -(float)Math.sin(angleB * Math.PI / 180.0);v[n][0] = (r2 * cos);v[n][1] = (h2);v[n][2] = (r2 * sin);v[n + 1][0] = (r1 * cos);v[n + 1][1] = (h1);v[n + 1][2] = (r1 * sin);vBuf.put(v[n]);vBuf.put(v[n + 1]);n += 2; if(n>31){vBuf.position(0);gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf);gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf);gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n);n = 0;angleB -= step;}}vBuf.position(0);gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf);gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf);gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n);}gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);}
}
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;public class OpenGLView extends GLSurfaceView {private OpenGLRenderer4 mRenderer;private float mDownX = 0.0f;private float mDownY = 0.0f;public OpenGLView(Context context) {super(context);mRenderer = new OpenGLRenderer4();this.setRenderer(mRenderer);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getActionMasked();switch (action) {case MotionEvent.ACTION_DOWN:mDownX = event.getX();mDownY = event.getY();return true;case MotionEvent.ACTION_UP:return true;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();mRenderer.mLightX += (mX-mDownX)/10;mRenderer.mLightY -= (mY-mDownY)/10;mDownX = mX;mDownY = mY;return true;default:return super.onTouchEvent(event);}}
}
import android.os.Bundle;
import android.app.Activity;
import android.view.Window;
import android.view.WindowManager;public class MainActivity extends Activity {private OpenGLView mOpenGLView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 去标题栏requestWindowFeature(Window.FEATURE_NO_TITLE);//设置全屏getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);mOpenGLView = new OpenGLView(this);setContentView(mOpenGLView);}
}
> 效果图
Android OpenGL ES 画球体相关推荐
- Android OpenGL ES 画出三棱锥
如今VR这么火,感觉有必要学学OpenGL.什么是OpenGL ES ,OpenGL ES (OpenGL for Embedded System ) 为适用于嵌入式系统的一个免费二维和三维图形库.O ...
- OpenGl文章
Android OpenGL ES 简明开发教程
Android OpenGL ES 简明开发教程 分类:android学习笔记2011-12-14 15:04375人阅读评论(0)收藏举报 ApiDemos 的Graphics示例中含有OpenGL ...
- Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序
OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...
- Android OpenGl Es 学习(二):定义顶点和着色器
概述 这是一个新的系列,学习OpengGl Es,其实是<OpenGl Es 应用开发实践指南 Android卷>的学习笔记,感兴趣的可以直接看这本书,当然这个会记录自己的理解,以下只作为 ...
- Android OpenGL ES 学习(九) – 坐标系统和实现3D效果
OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...
- android自定义美颜相机完整程序,Android OpenGL ES从入门到进阶(一)—— 五分钟开发一款美颜相机...
源码链接:https://github.com/smzhldr/AGLFramework 一.前言 商店里有数十款的美颜相机类产品,其实现原理基本上都是以OpenGL ES为核心的特效处理,大神可以忽 ...
- Android OpenGL ES 开发教程(20):颜色Color
OpenGL ES 支持的颜色格式为RGBA模式(红,绿,蓝,透明度).颜色的定义通常使用Hex格式0xFF00FF 或十进制格式(255,0,255), 在OpenGL 中却是使用0-1之间的浮点数 ...
- Android OpenGL ES 开发教程(16):Viewing和Modeling(MODELVIEW) 变换
Viewing和Modeling 变换关系紧密,对应到相机拍照为放置三角架和调整被拍物体位置及角度,通常将这两个变换使用一个modelview 变换矩阵来定义.对于同一个坐标变换,可以使用不同的方法来 ...
- Android OpenGL ES(六)创建实例应用OpenGLDemos程序框架 .
有了前面关于Android OpenGL ES的介绍,可以开始创建示例程序OpenGLDemos. 使用Eclipse 创建一个Android项目 Project Name: OpenGLDemos ...
最新文章
- 优化营商环境建议个人_优化营商环境的几点建议(三)
- Facebook开源ptr:在Python环境中并行运行单元测试
- URL编码将“&”(&符号)视为“&”HTML实体
- Trie树统计单词前缀
- spring+springMvc+mybatis 调用oracle 存储过程
- 神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(python常量、变量和表达式)
- java向Excel文件写入数据
- HDU1071_数学几何
- 计蒜客挑战难题:简单斐波那契
- 浅谈API测试与UI Auomation一点心得
- My 1st webUI try
- JAVA动态申请数组
- 李白的苏台览古译文赏析
- 打印机后台服务器修复,修复win10出现“本地打印后台处理程序服务没有运行”的方法...
- CSS篇十六——盒子模型之边框
- 一句话点评国内在产主流A级车
- java web 组态,Java:Eclipse中使用WTP开发Web项目
- 在64位计算机上安装MapGuide Studio 2010
- Toasts官方教程
- 零基础该如何学习区块链?
热门文章
- 电视机计算机英语,电视电脑的优缺点英语作文
- 美团点评java开发面试问题
- OpenCV 中的矩(moments)和 Hu不变矩(HuMoments)
- oracle load data用法,Dataload 使用说明
- Uniapp自定义相机界面
- .net借助LumiSoft.dll获取邮件内容和附件
- 警告:计算出的值未被使用warning: value computed is not used [-Wunused-value]
- Python自动获取邮箱验证码【上集】
- 银联电子支付 php chinapay
- 年末小激动!uimou.com终于通过谷歌广告联盟Google