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++

基于AutoDL复现A-LOAM

Ceres solver 是谷歌开发的一款用于非线性优化的库,在谷歌的开源激光雷达slam项目cartographer中被大量使用。在autodl上面租服务器,地区我租的重庆A区的,GPU我选择的是RTX4090,基础镜像选择的是Miniconda / conda3 / 3.8(ubuntu20.04)/11.6。在AutoDL中我使用的方式是先将该数据集先下载到自己的电脑上,然后再上传到虚拟机中。用MobaXterm解决该问题!搜到的一个解决方式:该问题属于ceres版本问题,将A-LOAM下的。

m0_61281610的博客 1942

粒子系统代码示例

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

boring 918

Claude Code+Cursor+Claude 4三剑合璧!5步搞定Magentic-UI的OAuth2.0集成,开发效率飙升500%,新手秒变全栈工程师

本文详细介绍了如何利用Claude Code、Cursor和Claude 4三款AI工具高效集成Magentic-UI的OAuth2.0认证系统。通过5个步骤的实战演练,开发者可快速完成从环境搭建、项目分析、代码生成到前端集成的全过程,显著提升开发效率。文章还提供了JWT令牌管理、安全配置及常见问题解决方案。

weixin_29234509的博客 453

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

中科蓝讯蓝牙耳机SDK实战:从目录解析到消息处理框架

本文深入解析中科蓝讯蓝牙耳机SDK的目录结构与消息处理框架,提供从硬件驱动到蓝牙功能定制的实战指南。重点剖析SDK核心模块如消息队列机制、按键事件处理及电量报告优化,并分享二次开发中的调试技巧与避坑经验,助力开发者高效完成TWS耳机功能定制。

weixin_30335575的博客 387

YOLOv11改进 | 损失函数改进篇 | EIoU、SIoU、WIoU、DIoU、FocusIoU等二十余种损失函数

这篇文章介绍了YOLOv11的重大改进,特别是在损失函数方面的创新。它不仅包括了多种IoU损失函数的改进和变体,如SIoU、WIoU、GIoU、DIoU、EIOU、CIoU,还融合了“Focus”思想,创造了一系列新的损失函数。这些组合形式的损失函数超过了二十余种,每种都针对特定的目标检测挑战进行优化。文章会详细探讨这些损失函数如何提高YOLOv11在各种检测任务中的性能,包括提升精度、加快收敛速度和增强模型对复杂场景的适应性。

Snu77的博客 6191

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

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

gitblog_01126的博客 398

在hyper-v管理器中修改WSL虚拟交换机后,打开wsl闪退

此次是因为修改了WSL虚拟交换机造成的wsl打不开或闪退,还有一种可能是关闭了hyper-v造成了wsl。

DN金猿的博客 1171

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

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

gitblog_00695的博客 1097

Python散点图(Scatter Plot):高阶分析、散点图矩阵、三维散点图及综合应用

散点图作为一种直观且功能强大的数据可视化工具,在数据分析中具有广泛的应用。通过观察散点图中数据点的分布模式,我们可以轻松地判断变量之间是否存在相关性,以及相关性的类型和强度。同时,散点图也是识别数据集中异常值的有效工具,无论是通过直观观察还是结合统计方法,都能帮助我们发现数据中的异常情况。掌握散点图的绘制和分析技巧,将使我们在数据探索和决策制定中更加得心应手。

SiArch的博客 1444

【数据集】全球首个10米分辨率精细分类土地覆盖数据集GLC_FCS10

【数据集】全球首个10米分辨率精细分类土地覆盖数据集GLC_FCS10

WW、forever的博客 1567

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

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

红旺永福 688

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值