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

LAN8720芯片硬件设计避坑指南:从晶振选择到PHY地址配置的5个关键细节

本文深入解析LAN8720以太网PHY芯片硬件设计的五个关键细节,涵盖晶振模式选择、PHY地址配置、复位电路设计、电源滤波与接口布线。重点阐述了REF_CLK Out与REF_CLK In两种时钟模式的配置逻辑与应用场景,提供了避免通信失败与信号完整性问题的实战方案,是嵌入式网络硬件开发的实用避坑指南。

i1j2k的博客 514

粒子系统代码示例

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

boring 918

深入解析LCD DRM驱动框架中的KMS与GEM机制

本文深入解析了Linux内核中DRM(Direct Rendering Manager)驱动框架的核心机制,重点剖析了KMS(内核模式设置)与GEM(图形执行管理器)的工作原理。KMS作为显示系统的总指挥,负责原子化地控制CRTC、Encoder、Plane等硬件资源,确保画面同步更新,避免撕裂;GEM则作为显存大管家,通过DUMB和PRIME机制高效管理图形缓冲区的分配、共享与同步。文章结合RK3568平台实战,阐述了如何利用这些机制优化显示性能,并提供了调试技巧与常见问题解决方案。

weixin_29188997的博客 387

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

《生成式AI引发的“认知污染”:社交媒体虚假信息的治理困局》

认知污染与生成式AI“认知污染”指信息环境被大量虚假、误导性内容所充斥,干扰公众对事实的认知判断。在社交媒体时代,虚假信息的生产和传播门槛大幅降低,呈现出工业化、规模化的趋势。近年兴起的生成式人工智能(Generative AI)技术,如大型语言模型(LLM)和深度伪造(deepfake),更是加剧了这一问题。AI可以自动生成看似真实的文本、图像、音视频,将虚假信息批量生产并快速散播到社交平台上。

那谁的博客 5912

第三节: 串口通信(用CubeMX学习STM32)

用CubeMX学习STM32, 串口通信学习, 通过轮询方式和中断方式两种方式进行通信演示。 STM32F407zgt6

Kevin_8_Lee的博客 8904

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

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

gitblog_01126的博客 398

Android车载应用开发与分析(11)- 车载Android应用开发入门指南

将时间回退到2017年我大学刚毕业时,彼时移动互联网就已经开始退潮,各大个培训机构也纷纷停止了Android相关的培训,曾经热火朝天的应用开发从那时起,就开始走向下坡路,小程序以及众多跨平台框架也让市场对Android原生开发的需求逐年降低,市场需求的降低也造就了Android开发的面试变得史无前例的“卷”。 终于我在2019年选择离开了互联网,投身当时还不是非常火热的车载Android领域继续从事Android原生开发。而这一年中国首个外商独资的整车制造项目,“...

linkwj的博客 1万+

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

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

gitblog_00695的博客 1097

基于粒子群算法优化的灰色预测模型GM实现数据预测(附带MATLAB代码)

灰色预测模型(Grey Model,简称GM)是一种常用的非线性时间序列预测方法,它在处理少量数据和缺乏规律性的序列预测问题上表现出良好的性能。c. 建立灰色微分方程:根据紧邻均值生成序列建立灰色微分方程,通常形式为:dx(n) + ax(n) = b,其中dx(n)是紧邻均值生成序列,x(n)是原始序列。为了提高GM模型的预测准确性,我们将使用粒子群算法来优化灰色微分方程的参数a和b。a. 利用灰色微分方程进行预测:根据已得到的灰色微分方程,进行后续时间点的数据预测。首先,定义了两个函数。

CoderExtra的博客 606

浏览器缓存导致代码不更新?一招解决部署后用户仍看到旧页面的问题

方案效果适用场景文件名哈希永久解决前端工程化项目HTTP缓存头控制精准控制需服务器权限Meta标签部分生效临时补救方案最佳实践:入口HTML禁用缓存,静态资源使用哈希文件名 + 长期缓存,达到「秒级更新」+「高性能」的平衡!

江拥羡橙的博客 810

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

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

红旺永福 688

ADES1831和ADBMS6830

1、上电默认进入STANDBY模式,SPI发送0xFF也可以进入STANDBY模式2、看门狗定时器超时后,进入SLEEP状态3、配置寄存器中的REFON位使用WRCFGA命令将组A设置为1进入REFUP状态,此状态比待机状态更快地启动ADC转换。i<TOTAL_IC;i++)注意:读AFE数据时会随着AFE片数增加而增加,原因是唤醒时间和AFE片数密切相关,如果需要缩短时间,那么减少唤醒频次。

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值