`
yidongkaifa
  • 浏览: 4060256 次
文章分类
社区版块
存档分类
最新评论

【Android开发学习18】Android OpenGL ES 光照glDrawArrays

 
阅读更多

一、基础知识:


1..光照介绍:

环境光:
来自四面八方,所有场景中的对象都处于环境光的照射中。

漫射光:
由特定的光源产生,并在场景中的对象表面产生反射。
处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未被照射到的区域就显示得要暗一些。

2.光照使用:
①设定光源参数:

//环境光
private float[] lightAmbient;
private FloatBuffer AmbientBuffer;
//漫射光
private float[] lightDiffuse;
private FloatBuffer diffuseBuffer;
//光源位置
private float[] lightPosition;
private FloatBuffer positionBuffer;

//灯光
lightAmbient = new float[]{0.5f,0.5f,0.5f,1.0f};
lightDiffuse = new float[]{1.0f,1.0f,1.0f,1.0f};
lightPosition = new float[]{0.0f,0.0f,2.0f,1.0f};

//环境光
ByteBuffer ambientbb = ByteBuffer.allocateDirect(lightAmbient.length * 4 * 6);
ambientbb.order(ByteOrder.nativeOrder());
AmbientBuffer = ambientbb.asFloatBuffer();
AmbientBuffer.put(lightAmbient);
AmbientBuffer.position(0);

//漫射光
ByteBuffer diffusebb = ByteBuffer.allocateDirect(lightDiffuse.length * 4 * 6);
diffusebb.order(ByteOrder.nativeOrder());
diffuseBuffer = diffusebb.asFloatBuffer();
diffuseBuffer.put(lightDiffuse);
diffuseBuffer.position(0);

//灯光位置
ByteBuffer positionbb = ByteBuffer.allocateDirect(lightPosition.length * 4 * 6);
positionbb.order(ByteOrder.nativeOrder());
positionBuffer = positionbb.asFloatBuffer();
positionBuffer.put(lightPosition);
positionBuffer.position(0);

②设置光源:
glLightfv (
int light,// 光源的ID
int pname, // 光源的类型
FloatBuffer params// 光源的数组
)
设定的属性,主要由第二个参数决定:
GL_AMBIENT环境光(光源泛光强度的RGBA值)
GL_DIFFUSE漫射光(光源漫反射强度的RGBA值)
GL_SPECULAR高光(光源镜面反射强度的RGBA值)
GL_POSITION位置(光源的位置)
GL_SPOT_DIRECTION方向(聚光灯的方向)
GL_SPOT_CUTOFF光的角度(聚光灯的截止角度)

// 设置环境光
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, AmbientBuffer);
// 设置漫射光
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseBuffer);
// 设置灯光位置
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionBuffer);

③启用光源:
//启用一号光源
gl.glEnable(GL10.GL_LIGHT1);

二、实现:

1. 界面编辑:
res\layout\main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />

<Button
    android:id="@+id/button1"
    android:layout_width="145dp"
    android:layout_height="wrap_content"
    android:text="演示开始" />

</LinearLayout>


2.代码编辑:
\src\com\yarin\android\Examples\Activity01.java

package com.yarin.android.Examples_12_05;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class Activity01 extends Activity
{
	Renderer render = new GLRender();
	GLSurfaceView glView;
	Button start;			// 演示开始

	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		GLImage.load(this.getResources());
		glView = new GLSurfaceView(this);
		
		
		glView.setRenderer(render);
		setContentView(R.layout.main);
		start=(Button)findViewById(R.id.button1);	// "演示开始"按钮初始化
		start.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				setContentView(glView);
			}
		});
		
		//setContentView(glView);
	}
}

class GLImage
{
	public static Bitmap iBitmap;
	public static Bitmap jBitmap;
	public static Bitmap kBitmap;
	public static Bitmap lBitmap;
	public static Bitmap mBitmap;
	public static Bitmap nBitmap;
	public static Bitmap close_Bitmap;
	
	
	public static void load(Resources resources)
	{
		iBitmap = BitmapFactory.decodeResource(resources, R.drawable.img);
		jBitmap = BitmapFactory.decodeResource(resources, R.drawable.jmg);
		kBitmap = BitmapFactory.decodeResource(resources, R.drawable.kmg);
		lBitmap = BitmapFactory.decodeResource(resources, R.drawable.lmg);
		mBitmap = BitmapFactory.decodeResource(resources, R.drawable.mmg);
		nBitmap = BitmapFactory.decodeResource(resources, R.drawable.nmg);
		close_Bitmap = BitmapFactory.decodeResource(resources, R.drawable.close);
	}
}


\src\com\yarin\android\Examples\GLRender.java

package com.yarin.android.Examples_12_05;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ByteOrder;  
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
import android.content.Context;

public class GLRender implements Renderer
{
	/**
	 * 渲染类
	 * author:pis
	 */

	private int one = 0x10000;

	public boolean mFlag ;
	public boolean bLight = true;//是否开启灯光
	
	private int[] vertices;//顶点数组
	private int[] textCood;//纹理数组
	
	float step = 0.3f;
	float xrot,yrot; //旋转
	float xSpeed,ySpeed; //移动速度
	private int[] textures = new int[1];
	
	private IntBuffer vertexBuffer; //顶点缓冲
	private IntBuffer textCoodBuffer; //纹理缓冲
	/**
	 * 设置灯光
	 * @param context
	 */
	//环境光
	private float[] lightAmbient;
	private FloatBuffer AmbientBuffer;
	//漫射光
	private float[] lightDiffuse;
	private FloatBuffer diffuseBuffer;
	//光源位置
	private float[] lightPosition;
	private FloatBuffer positionBuffer;
	
	/**
	 * 初始化缓冲数据
	 */
	private void initBuffer(){
		//顶点
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
		vbb.order(ByteOrder.nativeOrder());
		vertexBuffer = vbb.asIntBuffer();
		vertexBuffer.put(vertices);
		vertexBuffer.position(0);
		
		//纹理
		ByteBuffer tbb = ByteBuffer.allocateDirect(textCood.length * 4 * 6);
		tbb.order(ByteOrder.nativeOrder());
		textCoodBuffer = tbb.asIntBuffer();
		for (int i = 0; i < 6; i++) {			
			textCoodBuffer.put(textCood);
		}
		textCoodBuffer.position(0);
		
		//环境光
		ByteBuffer ambientbb = ByteBuffer.allocateDirect(lightAmbient.length * 4 * 6);
		ambientbb.order(ByteOrder.nativeOrder());
		AmbientBuffer = ambientbb.asFloatBuffer();
		AmbientBuffer.put(lightAmbient);
		AmbientBuffer.position(0);
		
		//漫射光
		ByteBuffer diffusebb = ByteBuffer.allocateDirect(lightDiffuse.length * 4 * 6);
		diffusebb.order(ByteOrder.nativeOrder());
		diffuseBuffer = diffusebb.asFloatBuffer();
		diffuseBuffer.put(lightDiffuse);
		diffuseBuffer.position(0);
		
		//灯光位置
		ByteBuffer positionbb = ByteBuffer.allocateDirect(lightPosition.length * 4 * 6);
		positionbb.order(ByteOrder.nativeOrder());
		positionBuffer = positionbb.asFloatBuffer();
		positionBuffer.put(lightPosition);
		positionBuffer.position(0);
		
	}
	/**
	 * 初始化顶点、纹理、灯光数据
	 */
	private void initData(){
		//顶点数组
		vertices = new int[] { -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 };

		//纹理数组,贴图时注意android中坐标与OpengGL 中定义的不同,android,y轴是向下的
		textCood = new int[] { 0, 0, one, 0, 0, one, one, one };
		//灯光
		lightAmbient = new float[]{0.5f,0.5f,0.5f,1.0f};
		lightDiffuse = new float[]{1.0f,1.0f,1.0f,1.0f};
		lightPosition = new float[]{0.0f,0.0f,2.0f,1.0f};

		
	}
	public GLRender() {
		mFlag=true;
		initData();
		initBuffer();
	}

	
	@Override
	public void onDrawFrame(GL10 gl) {
		//清除颜色和深度缓存
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		gl.glLoadIdentity();
		
		//启用灯光
		gl.glEnable(GL10.GL_LIGHTING);
		
		//启用顶点和纹理缓存
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		//移动和旋转设置
		gl.glTranslatef(0.0f, 0.0f, -6.0f);
		gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
		gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);
		
		//设置顶点和纹理,经常忘记设置,唉!
		gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertexBuffer);
		gl.glTexCoordPointer(2,GL10.GL_FIXED,0,textCoodBuffer);
		
		//绘制六个面,贴图
		for (int i = 0; i < 6; i++) {
	      	switch(i)
        	{
        	case 0:
    	        // 8.生成纹理
    	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.iBitmap, 0);
    	        break;
        	case 1:
    	        // 生成纹理
    	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.jBitmap, 0);
    	        break;
        	case 2:
    	        // 生成纹理
    	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.kBitmap, 0);
    	        break;
        	case 3:
    	        // 生成纹理
    	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.lBitmap, 0);
    	        break;
        	case 4:
    	        // 生成纹理
    	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);
    	        break;
        	case 5:
    	        // 生成纹理
    	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.nBitmap, 0);
    	        break;    	                		
        	}			
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, i * 4, 4);
		}
		//取消缓存,需我们自己手动
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glLoadIdentity();
		
		if (mFlag) {
			xrot += 0.5f;
			yrot += 0.5f;
		}
		if (!bLight) {
			gl.glDisable(GL10.GL_LIGHT1);
		} else {
			gl.glEnable(GL10.GL_LIGHT1);
		}
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		//场景大小
		gl.glViewport(0, 0, width, height);
		float ratio = (float) width / height;
		//投影矩阵
		gl.glMatrixMode(GL10.GL_PROJECTION);
		//重置下
		gl.glLoadIdentity();
		//视图大小设置
		gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
		//观察模型
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		//透视效果
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
		//清屏
		gl.glClearColor(0, 0, 0, 0);
		//启用阴影平滑
		gl.glShadeModel(GL10.GL_SMOOTH);
		//清除深度缓存
		gl.glClearDepthf(one);
		//启用深度缓存
		gl.glEnable(GL10.GL_DEPTH_TEST);
		//深度缓存模式
		gl.glDepthFunc(GL10.GL_LEQUAL);
		
		/**
		 * 设置纹理
		 */
		//启用纹理
		gl.glEnable(GL10.GL_TEXTURE_2D);
		//创建纹理
		gl.glGenTextures(1, textures, 0);
		//绑定纹理
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
		//生成纹理
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.kBitmap, 0);
		//线性滤波处理
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
				GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
				GL10.GL_LINEAR);
		/**
		 * 设置灯光
		 */
		
		//设置环境光
		gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, AmbientBuffer);
		//设置漫射光
		gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseBuffer);
		//设置灯光位置
		gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionBuffer);
		//启用1号灯光
		gl.glEnable(GL10.GL_LIGHT1);	
		
	}
}


三、效果:

本文博客源地址:http://blog.csdn.net/ypist

分享到:
评论

相关推荐

    openGLES3.0Example_6_VertexBufferObjects.rar

    此数据必须从客户端内存复制到图形内存时 绘制调用,如glDrawArrays或glDrawElements。 和光栅化。” 然而,如果我们不这样做会好得多 在每个绘制调用上复制顶点数据,但可以缓存 图形存储器中的数据。 这种方法...

    10.1.instancing_quads.rar

    一次绘制100个矩形,是一种只调用一次渲染函数却能绘制出很多物体的技术,它节省渲染物体 时从CPU到GPU的通信时间,...将 glDrawArrays 和 glDrawElements 各自改 为 glDrawArraysInstanced 和 glDrawElementsInstanced

    OBJ-Parser:将 3D OBJ 文件转换为矢量和纹理坐标,以使用 glDrawArrays 在 OpenGL 中绘制。 用 Python 编写

    将 OBJ 文件转换为矢量和纹理坐标,以使用 glDrawArrays 在 OpenGL 中绘制。示例 .obj 文件格式解析器当前仅检查以“v”(顶点)、“vt”(顶点纹理)和“f”(面)开头的行。 此外,面应包含 v/vt/n/... 的标准 ....

    安卓日志分析崩溃拦截相关-这个demo主要讲解了怎样使用log查看日志和怎样控制log的等级.zip

    这个demo主要讲解了怎样使用log查看日志和怎样控制log的等级.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。

    基于Springboot+Vue的墙绘产品展示交易平台毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    99-青海大学大数据中心建设分享.pptx

    99-青海大学大数据中心建设分享.pptx

    TD-LTE载波聚合方案.docx

    5G通信行业、网络优化、通信工程建设资料。

    10份网络优化创新案例.zip

    SA语音回落与切换流程冲突解决.pdf 计费模式错误导致SA语音承载建立失败,pdf BSF网元bug导致SA用户VOLTE业务故障,pdf SA基站SCTP偶联IP配置不规范导致切换失败的问题处理,pdf 第一医院SA+NSA双模基站方案保障5G查房车应用,pdf SA未配置互操作场景下终端语音业务研究案例,pdf SA站点天馈隔离度问题导致上行速率不及预期,pdf SA组网下微信小视频卡顿影响感知案例,pdf 基于八步法定位SA掉线问题.pdf SA站点测试宏微切换异常事件,pdf

    施工监理费计算依据.doc

    5G通信行业、网络优化、通信工程建设资料。

    wordpress插件WhatsApp右下角浮动悬浮客服按钮

    1、WhatsApp插件,可轻松实现wordpress后台设置,前台悬浮显示; 2、无缝集成:该插件将WordPress站点与WhatsApp无缝集成; 3、多人员支持:支持显示多个WhatsApp账户,让用户根据需求或偏好选择联系不同的团队成员 4、群组邀请:允许邀请用户加入特定的WhatsApp支持群组,便于群体咨询、公告发布或集体答疑。 5、响应式设计:插件具备响应式布局,确保在各种屏幕尺寸和设备类型上均能良好呈现并顺畅使用。 6、WooCommerce产品查询集成:针对电商网站,支持与WooCommerce产品查询功能结合,方便用户就具体商品提问。 7、带声音的自动弹窗:可设置带有声音提示的自动弹出窗口,提醒用户支持服务的存在 8、定制欢迎消息:设置个性化欢迎信息,向用户传递品牌关怀或引导其使用支持服务。 9、移动端与桌面端开关控制:可根据需要独立开启或关闭移动端或桌面端上的插件功能 10、GDPR合规:遵循欧盟GDPR数据保护法规,保障用户隐私及数据安全。

    基于YOLOv7的芯片表面缺陷检测系统

    目前随着电子领域的快速发展,芯片也已经成为日常生活中不可或缺的一部分。随着市场对芯片的需求不断增大,裸芯片表面缺陷检测任务的压力也越来越大。裸芯片表面的缺陷检测不仅能保证芯片成品的质量,而且有着统计缺陷数量,反馈给生产前道工序的重要意义,但是目前许多生产线对于裸芯片表面依旧采用人工目检的方法进行缺陷检测,不仅实时性差,耗时长,而且结果会受到检测人员主观因素的影响。  目前国内外的芯片表面缺陷检测设备不仅价格昂贵,而且功能比较单一,因此本文提出了一种基于深度学习的裸芯片表面缺陷检测算法,具有高效率,实时性好的特点,与传统人工目检的方式相比具有一定的优势

    基于SpringBoot的“大学生社团活动平台”的设计与实现.zip

    基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现基于SpringBoot的“大学生社团活动平台”的设计与实现

    英飞凌官方ADS库1.9.20版

    英飞凌官方ADS库1.9.20版

    汇编语言-assembly-贪吃蛇游戏-汇编语言期末大作业

    汇编语言——贪吃蛇游戏 GREEDY_SNAKE 是基于8086 汇编语言开发的,汇编语言风格是采用《汇编语言》第二版 王爽著; G_Snake.asm 本贪吃蛇游戏 实现了随机出现食物、统计分数、显示小蛇运动方向、响应键盘中断、指定方向自动移动、游戏结束恢复9h键盘中断和正常退出。 文件说明: 1. 安装DOSBOX:运行DOSBox0.74-win32-installer.exe即可安装; 2. 将Greedy_Snake clone到本地任意盘,eg:d:\Greedy_Snake - mount d:\Greedy_Snake 到一个指定虚拟盘符: - `mount k d:\Greedy_Snake` (why is k? because i like this charactor) 3. 运行G_Snake - 在DOSBOX的DOS提示符下键入: - `Z:\>K:`(回车) - `K:\>cd G_Snake`(回车) - 使用masm 5.0工具编译、链接、运行.asm源程序 - MASM.EXE、LINK.EXE、d

    物联网考试题库答案.doc

    5G通信行业、网络优化、通信工程建设资料

    基于Python的在线学习与推荐系统设计带vue前后端分离毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    考试资料+7、互联网与物联网.docx

    5G通信行业、网络优化、通信工程建设资料

    参考资料-人工智能对劳动力市场的影响机制研究.pdf

    参考资料-人工智能对劳动力市场的影响机制研究.pdf

    99-数据开放平台技术实现方案.pptx

    99-数据开放平台技术实现方案.pptx

    199-IBM数据治理新主张-数据治理及元数据管理.pptx

    199-IBM数据治理新主张-数据治理及元数据管理.pptx

Global site tag (gtag.js) - Google Analytics