android opengl es 粒子系统

OpenGL ES2.0粒子系统(附有源码) 刚学OpenGL 2个多星期,也算是入门了吧 在看了老外写的书 OpenGL ES 2 for Android A Quick - Start Guide.pdf 后,由于这本书上给的代码不够全,自己功力太浅,对于一些了解有点疑惑, 费了差不多两天才调出想要的结果,下面就分享一下我的经历,若有问题,希望大家多多交流 本代码中包含的内容还是比较多的,使用OpenG 阅读详情

先改正在"位图子体"中关于坐标的说法

正确的画法应如下图所示

哦哦,粒子系统的实现与星星实现有相似之处,大体上就是先创建一个类,这个类中包含了要创建原型的各类属性,然后再在Renderer中将其各类属性赋予相应的值。粒子系统呢,先用一个循环初始化所有的particles,然后在onDrawFrame中循环出每一个particle,NEHE把他们叫三角地带,最后判断运行一段时间的particle是否还为激活状态,若为false,则再初始化一次。大体思路就是这样,下面把今天代码粘上来。

 

 

(1)Activity

 

package sim.feel;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

/**
 * Activity类ParticleActivity
 *
 * @author Sim
 */
public class ParticleActivity extends Activity {
    private GLSurfaceView glSurfaceView;
    private MyRenderer myRenderer;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LoadImage.load(getResources());
        myRenderer = new MyRenderer();
        glSurfaceView = new GLSurfaceView(this);
        glSurfaceView.setRenderer(myRenderer);
        setContentView(glSurfaceView);
    }
}

/**
 * 载入图片类LoadImage
 */
class LoadImage {
    public static Bitmap bitmap;

    public static void load(Resources res) {
        bitmap = BitmapFactory.decodeResource(res, R.drawable.particle);
    }
}

 

(2)Particle

package sim.feel;

/**
 * 粒子类
 *
 * @author Sim
 */
public class Particle {
    boolean active; // 是否激活
    float life;     // 粒子生命
    float fade;     // 衰减速度

    float r;        // 红色值
    float g;        // 绿色值
    float b;        // 蓝色值

    float x;        // X位置
    float y;        // Y位置
    float z;        // Z位置

    float xi;       // X方向
    float yi;       // Y方向
    float zi;       // Z方向
   
    float xg;       // X 方向重力加速度
    float yg;       // Y 方向重力加速度
    float zg;       // Z 方向重力加速度
}

 

(3)Renderer类

 

package sim.feel;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Random;

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

import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;

/**
 * Renderer类MyRenderer
 *
 * @author Sim
 */
public class MyRenderer implements Renderer {
    // 纹理相关
    private int[] textures = new int[1];
    // 随机数
    private Random random = new Random();
    // 定义最在的粒子数
    private static final int MAX_PARTICLES = 1000;
    // 减速粒子
    private float slowdown = 0.5f;
    // X方向的速度
    private float xspeed = 20;
    // Y方向的速度
    private float yspeed = 20;
    // 沿Z轴缩放
    private float zoom = -30.0f;
    // 循环变量
    private int loop;

    // 创建一个名为Particle的数组,存储MAX_PARTICLES个元素
    private Particle particles[] = new Particle[MAX_PARTICLES];

    // 存储12种不同颜色
    private float colors[][] = { { 1.0f, 0.75f, 0.5f }, { 1.0f, 0.75f, 0.5f },
            { 1.0f, 1.0f, 0.5f }, { 0.75f, 1.0f, 0.5f }, { 0.5f, 1.0f, 0.5f },
            { 0.5f, 1.0f, 0.75f }, { 0.5f, 1.0f, 1.0f }, { 0.5f, 0.75f, 1.0f },
            { 0.5f, 0.5f, 1.0f }, { 0.75f, 0.5f, 1.0f }, { 1.0f, 0.5f, 1.0f },
            { 1.0f, 0.5f, 0.75f } };

    // vertexBuffer
    private FloatBuffer vertexBuffer;
    // texCoordBuffer
    private FloatBuffer texCoordBuffer;
    // vertex
    private float[] vertex = new float[12];
    // texCoord
    private float[] texCoord = new float[8];

    // LoadBuffer
    public void LoadBuffer(GL10 gl) {
        ByteBuffer vertexByteBuffer = ByteBuffer
                .allocateDirect(vertex.length * 4);
        vertexByteBuffer.order(ByteOrder.nativeOrder());
        vertexBuffer = vertexByteBuffer.asFloatBuffer();
        vertexBuffer.put(vertex);
        vertexBuffer.position(0);

        ByteBuffer texCoordByteBuffer = ByteBuffer
                .allocateDirect(texCoord.length * 4);
        texCoordByteBuffer.order(ByteOrder.nativeOrder());
        texCoordBuffer = texCoordByteBuffer.asFloatBuffer();
        texCoordBuffer.put(texCoord);
        texCoordBuffer.position(0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        // LoadBuffer
        LoadBuffer(gl);
        // 清除屏幕和颜色缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 重置模型变换矩阵
        gl.glLoadIdentity();

        // 开启顶点纹理状态
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoordBuffer);

        // 循环所有的粒子
        for (loop = 0; loop < MAX_PARTICLES; loop++) {
            // 如果粒子为激活的
            if (particles[loop].active) {
                // 返回X轴的位置
                float x = particles[loop].x;
                // 返回Y轴的位置
                float y = particles[loop].y;
                // 返回Z轴的位置
                float z = particles[loop].z + zoom;
                // 设置粒子颜色
                gl.glColor4f(particles[loop].r, particles[loop].g,
                        particles[loop].b, particles[loop].life);
                // 开始准备绘制"三角地带"(名字怪怪的)
                texCoordBuffer.clear();
                vertexBuffer.clear();
                texCoordBuffer.put(1.0f);
                texCoordBuffer.put(1.0f);
                vertexBuffer.put(x + 0.5f);
                vertexBuffer.put(y + 0.5f);
                vertexBuffer.put(z);
                texCoordBuffer.put(1.0f);
                texCoordBuffer.put(0.0f);
                vertexBuffer.put(x + 0.5f);
                vertexBuffer.put(y);
                vertexBuffer.put(z);
                texCoordBuffer.put(0.0f);
                texCoordBuffer.put(1.0f);
                vertexBuffer.put(x);
                vertexBuffer.put(y + 0.5f);
                vertexBuffer.put(z);
                texCoordBuffer.put(0.0f);
                texCoordBuffer.put(0.0f);
                vertexBuffer.put(x);
                vertexBuffer.put(y);
                vertexBuffer.put(z);
                // 绘制
                gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
                // 更新X坐标的位置
                particles[loop].x += particles[loop].xi / (slowdown * 1000);
                // 更新Y坐标的位置
                particles[loop].y += particles[loop].yi / (slowdown * 1000);
                // 更新Z坐标的位置
                particles[loop].z += particles[loop].zi / (slowdown * 1000);

                // 更新X轴方向速度大小
                particles[loop].xi += particles[loop].xg;
                // 更新Y轴方向速度大小
                particles[loop].yi += particles[loop].yg;
                // 更新Z轴方向速度大小
                particles[loop].zi += particles[loop].zg;

                // 减少粒子的生命值
                particles[loop].life -= particles[loop].fade;

                // 如果粒子生命小于0
                if (particles[loop].life < 0.0f) {
                    float xi, yi, zi;
                    xi = xspeed + (float) ((rand() % 60) - 32.0f);
                    yi = yspeed + (float) ((rand() % 60) - 30.0f);
                    zi = (float) ((rand() % 60) - 30.0f);
                    initParticle(loop, random.nextInt(12), xi, yi, zi);
                }

            }
        }
        // 关闭顶点纹理状态
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glFinish();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // ratio
        float ratio;
        if (height == 0) {
            height = 1;
        }
        ratio = (float) width / (float) height;
        gl.glViewport(0, 0, (int) width, (int) height);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 1.0f, 200.0f);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        // 重置模型矩阵
        gl.glLoadIdentity();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
        // 黑色背景
        gl.glClearColor(0, 0, 0, 0);
        // 关闭深度测试
        gl.glDisable(GL10.GL_DEPTH_TEST);
        // 阴影平滑
        gl.glShadeModel(GL10.GL_SMOOTH);
        // 启用混合
        gl.glEnable(GL10.GL_BLEND);
        // 精细修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);

        // 启用纹理
        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, LoadImage.bitmap, 0);
        // 线性滤波
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                GL10.GL_LINEAR);

        for (loop = 0; loop < MAX_PARTICLES; loop++) {
            float xi, yi, zi;
            xi = (float) ((rand() % 50) - 26.0f) * 10.0f;
            yi = zi = (float) ((rand() % 50) - 25.0f) * 10.0f;
            // 初始化粒子
            initParticle(loop, random.nextInt(12), xi, yi, zi);
        }
    }

    public int rand() {
        return Math.abs(random.nextInt(1000));
    }

    // initParticle初始化粒子
    public void initParticle(int num, int color, float xDir, float yDir,
            float zDir) {
        Particle par = new Particle();
        // 使所有粒子为激活状态
        par.active = true;
        // 所有粒子生命值为最大
        par.life = 1.0f;
        // 随机生成衰率(0~99)/1000+0.003f
        par.fade = rand() % 100 / 1000.0f + 0.003f;

        // 赋予粒子颜色分量r,g,b
        // r
        par.r = colors[color][0];
        // g
        par.g = colors[color][1];
        // b
        par.b = colors[color][2];

        // 设定粒子方向xi,yi,zi
        // xi
        par.xi = xDir;
        // yi
        par.yi = yDir;
        // zi
        par.zi = zDir;

        // x,y,z方向加速度
        // xg
        par.xg = 0.0f;
        // yg
        par.yg = -0.5f;
        // zg
        par.zg = 0.0f;

        particles[loop] = par;
    }
}

 

运行效果:

 

openGL ES进阶教程(一)之粒子光束 2016AR/VR喊的火热,这些在Android上的实现或多或少与openGL 有关。 OpenGL能做的事情太多了!很多程序也看起来异常复杂。更有可能因为某一步的顺序错误导致最后渲染出错,这是因为,OpenGL和我们现在使用的C++、java这种面向对象的语言不同,OpenGL中的大多数函数使用了一种基于状态的方法。你可以看到Android中的播放器原理,就是API改变播放状态,逻辑性非常强~ 本 阅读详情

相关推荐

Android平台粒子系统实战:实现雪花飘舞与星空闪烁特效

你看,这片看似简单的雪花,背后竟藏着如此复杂的工程体系。从数学建模到内存优化,从时间控制到GPU渲染,每一个环节都在追求一件事:在有限的计算资源下,创造出无限接近真实的视觉体验。而这,也正是计算机图形学的魅力所在。下次当你看到屏幕上的雪花缓缓落下时,不妨停下来想一想:那不仅仅是一段代码,那是无数工程师对“美”的执着追求。✨“真正的技术,是从不说破的魔法。—— 致每一位默默打磨细节的开发者 🫶本文还有配套的精品资源,点击获取。

weixin_42418754的博客 500

Android粒子系统库——DroidParticle

今天给大家介绍一款粒子系统库,并简要介绍下粒子系统的工作原理。 首先这款名为DroidParticle的库其实就是我自己没事做的,因为以前看过HGE的C++的粒子系统,觉得很有趣,现在从事Android开发工作就模仿着做了一个,希望对大家有用处。 先给大家看一下效果: 源代码下载地址: https://github.com/sunty2016/DroidParticle 下面

sunty2016的博客 3577

OpenGL实现的烟花粒子系统(Android)

Android上用OpenGL实现的烟花粒子系统,非常漂亮,欢迎大家交流。还有一个VC平台实现的,在我的资源列表里可以找到。 我这个程序是在模拟器里写的,所以,运行的时候可能需要调整一下slowdown、y方向的初始速度和加速度才能看到较好的效果。

Android OpenGL粒子

Android OpenGL粒子 粒子就是被画作一组点的简单物体。 1、着色器文件 (1) 顶点着色器,particle_vertex_shader.glsl文件 其中u_Time代表程序运行时间,a_ParticleStartTime代表粒子运行时间。 uniform mat4 u_Matrix; uniform float u_Time; attribute vec3 a_Posi

假装你是大灰狼的专栏 2449

Android OpenGL ES2.0粒子系统

Android OpenGL ES2.0粒子系统,包含了VBO的使用方法,用时间来做参数传递给顶点shader,让shader根据时间变换,从而改变当前绘制点的位子,从而形成粒子流

Android高级进阶十四 Android OpenGL粒子模型源码

Android高级进阶十四 Android OpenGL粒子模型源码

android opengl es 粒子效果实例代码

概述:粒子系统采用许多形状简单的微小粒子作为基本元素,用它们来表示不规则模糊物体,系统中的每个粒子都有各自的生命周期,我们可以管理它们从创建到消亡的时间,它们都要经历“产生”、“运动”、“消亡”这三个阶段。 下面我们做个简单的粒子效果,但感觉我做的效果跟原先想象的,有点不一样,还得继续改进,呵呵。 代码如下: 1、Activity类代码 import android.app.Act

楼中望月 6655

android 粒子特效 的展示

气泡 下雪 彩带 花瓣特效

Android JBox2d,Box2d,opengl es+算法 粒子系统水流的模拟体会

转载自:http://labs.ywlx.net/?tag=box2d%E6%B0%B4%E6%B5%81%E6%A8%A1%E6%8B%9F 前段时间做小熊蜂蜜,碰到一个做水流的问题,原先我们处理这种情况都是通过在某一位置切图片来实现的,但是在做出来之后发现效果并不是很理想,我们刘大美工拿出了鳄鱼洗澡的游戏进行比较…让我汗颜…可见切图已经无法满足我们的需要了,于是想通过各种方法来模拟一下,看能...

weixin_30847939的博客 94

OpenGL粒子系统

OpenGL 粒子系统 C/C++

深入解析CAN2.0A与CAN2.0B协议:帧格式与通信机制对比

本文深入对比了CAN2.0A与CAN2.0B协议的核心差异,重点解析了11位标准帧与29位扩展帧的帧格式、标识符长度及通信机制。文章阐述了CAN2.0B向下兼容的特性,并探讨了在汽车电子、工业控制等复杂网络中,如何根据项目需求、兼容性及实时性要求,在标准帧与扩展帧之间做出合理选择。

weixin_29163797的博客 392

粒子系统代码示例

在书上看到的粒子系统的示例分享给大家参考,希望可以帮助大家学习安卓!   首先是MyRenderer.java   package com.boring.ParticleActivity; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import j...

boring 918

【STM32】CubeMx系列教程之移植FreeRTOS

本文详细介绍了在STM32F429上通过CubeMX工具移植FreeRTOS的方法。主要内容包括:1)配置系统时钟源,将TIM1替换SysTick作为时钟基准;2)FreeRTOS的创建与配置,包括任务创建、堆栈大小设置等;3)关键配置参数说明,如堆大小建议设为RAM的50%-70%;4)常用函数如堆栈监控、任务挂起/恢复等。文章提供了从基础配置到深入优化的完整移植指南,适合STM32开发者参考使用。

JackieJin123的博客 785

OpenGL ES 3.0多平台开发指南:Windows、Linux、Android、iOS全平台构建

OpenGL ES 3.0是移动和嵌入式设备上高性能图形渲染的行业标准,本指南将带你掌握在Windows、Linux、Android和iOS四大平台上构建OpenGL ES 3.0应用的完整流程。通过GitHub加速计划提供的opengles3-book项目,你将获得丰富的示例代码和跨平台开发最佳实践,轻松开启全平台图形开发之旅。 ## 📋 项目结构解析:跨平台开发的基础 opengles3

gitblog_00163的博客 1139

【Docker】从零构建达梦DM8轻量级服务镜像:实战与优化

本文详细介绍了从零开始构建达梦DM8轻量级Docker镜像的完整实战流程。通过分析传统安装方式的痛点,阐述了使用Docker封装数据库的优势,并重点讲解了如何利用静默安装、精简组件、多阶段构建等优化技巧,打造一个体积小巧、启动迅速、配置灵活的DM8服务镜像,助力实现开发、测试与部署的环境一致性与高效性。

ooo22的博客 519

电力现货市场出清机制解析:从理论到实践(附节点电价计算实例)

本文深入解析电力现货市场的核心出清机制,重点阐述了节点边际电价的计算原理与实践方法。通过对比系统边际电价、节点边际电价和分区边际电价三种模式,揭示了市场出清价格如何反映电力供需与网络阻塞。文章结合IEEE 30节点系统,提供了基于MATLAB和最优潮流模型的计算实例,详细展示了从构建模型到求解对偶变量以获取节点电价的全过程,为理解电力市场定价机制提供了从理论到实践的完整路径。

whisky的博客 756

ParticleView:基于Android的开源粒子系统库

ParticleView:基于Android的开源粒子系统库 1. 项目基础介绍 ParticleView 是一个开源的 Android 库,用于在 Android 应用中显示大量的粒子。该项目使用 Java 编程语言实现,基于 OpenGL ES 2.0 进行渲染,相较于常规的 Canvas 绘制方式,能够提供显著的性能提升。 2. 核心功能 粒子渲染:ParticleView 能够高效地渲染...

gitblog_01126的博客 398

C# WinForm和Sherlock进行对接

文章目录 前言 一、使用步骤 二、使用步骤 1.引入库 2.读入数据 总结 前言 本人公司最近在做一款瑕疵检测的视觉项目,项目中利用Sherlock从相机中取图和对图像进行视觉处理,然后将图像和数据传输到项目中。这过程中软件需要和Sherlock进行图像和数据的传递,这就需要WinForm和Sherlock进行对接,但我在网上查找了许久能用上的资料十分有限,所以我决定写下这篇文章,来做一次总结,同时也希望能帮助到同样在为此问题困扰的你。 一、使用步骤 废话不...

adminmmrt的博客 3221

Storybook docs-review 技能详解:AI Agent 系统化评审与重写 /docs 文档的七步工作流

在 Storybook 仓库中,`.agents/skills/docs-review/` 定义了一个面向 AI Agent 的文档评审技能(Skill):当被要求审查、改进、重写或起草 `/docs` 下的文档时,Agent 会加载该技能,按照"诊断四步 + 执行三步"的固定工作流,从五个模式中选择干预级别,以六个文档类型和七个质量维度为标尺评估页面,最后以 `storybook-style.m

gitblog_00695的博客 1097

VSCODE 安装LATEX环境,参数配置,常见问题解决

1 准备Texlive安装包 可以从以下网址下载 texlive 的镜像文件: 华为镜像 阿里镜像 官网 网址中大概文件构成 下载完后我们需要的文件构成(我是2020年下载过了,这次就不重新下载了) 将这个镜像文件进行解压 2 安装Texlive 右键install-tl-windows.bat,单击以管理员身份运行,进入安装界面. 点击左下角的“Advanced”进入高级安装来取消你不需要安装的宏包。 点击“Customize”来取消勾选不需要的宏包。 单是把非中英的语言包取消勾选可以省掉 1G

呆呆象呆呆的博客 6万+

高效搭建微信公众号爬虫全流程

微信公众号爬虫系统成功完成功能测试验证。该系统具备完整的数据采集与管理能力,支持多公众号内容爬取、数据存储与统计分析。通过命令行界面可执行爬取操作(如量子位、新智元等公众号),查看最新文章列表和系统统计信息。测试显示SQLite数据库正常存储数据,所有核心功能(多源支持、文章检索、数据统计)均运行良好。系统采用模块化设计,扩展性强,为后续接入真实API或网页爬取奠定了坚实基础,是AI内容聚合的优质开发平台。🎉

weixin_44975687的博客 1553

Opengl ES系列学习--用粒子增添趣味

我们本节开始分析《OpenGL ES应用开发实践指南 Android卷》书中第10章中的粒子系统的实现原理,搞清楚其中的代码逻辑,代码下载请点击:Opengl ES Source Code,该Git库中的particlesModule就是我们本节要分析的目标,先看下本节最终实现的结果。 最终运行在真机上的效果非常炫,三个红绿蓝粒子系统不断的发射新的粒子,所有粒子由于重力...

红旺永福 688

STM32入门教程:人脸识别

STM32CubeMX配置 打开STM32CubeMX,创建一个新的工程,并选择你使用的STM32系列和具体型号。根据摄像头模块的规格,将摄像头的输出引脚连接到相应的STM32引脚上。人脸识别是一种非常常见的人工智能应用,它可以通过摄像头捕捉到的图像,识别出图像中的人脸并进行相关的分析和处理。在本教程中,我们将使用STM32开发板和相关传感器,通过指导你搭建一个基于STM32的简单人脸识别系统,并编写相应的代码来实现该功能。另外,为了达到更好的人脸识别效果,可能需要使用更高性能的处理器和更复杂的算法。

吃不胖. 374
上一篇: android opengl es 雾化效果
下一篇: android opengl es 蒙版效果
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值