Path: blob/main_old/samples/particle_system/ParticleSystem.cpp
1694 views
//1// Copyright 2014 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56// Based on ParticleSystem.c from7// Book: OpenGL(R) ES 2.0 Programming Guide8// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner9// ISBN-10: 032150279510// ISBN-13: 978032150279711// Publisher: Addison-Wesley Professional12// URLs: http://safari.informit.com/978032156383513// http://www.opengles-book.com1415#include "SampleApplication.h"1617#include "common/vector_utils.h"18#include "tga_utils.h"19#include "util/random_utils.h"20#include "util/shader_utils.h"2122#define _USE_MATH_DEFINES23#include <math.h>2425#include <string>2627using namespace angle;2829class ParticleSystemSample : public SampleApplication30{31public:32ParticleSystemSample(int argc, char **argv) : SampleApplication("ParticleSystem", argc, argv) {}3334bool initialize() override35{36constexpr char kVS[] = R"(uniform float u_time;37uniform vec3 u_centerPosition;38attribute float a_lifetime;39attribute vec3 a_startPosition;40attribute vec3 a_endPosition;41varying float v_lifetime;42void main()43{44if (u_time <= a_lifetime)45{46gl_Position.xyz = a_startPosition + (u_time * a_endPosition);47gl_Position.xyz += u_centerPosition;48gl_Position.w = 1.0;49}50else51{52gl_Position = vec4(-1000, -1000, 0, 0);53}54v_lifetime = 1.0 - (u_time / a_lifetime);55v_lifetime = clamp(v_lifetime, 0.0, 1.0);56gl_PointSize = (v_lifetime * v_lifetime) * 40.0;57})";5859constexpr char kFS[] = R"(precision mediump float;60uniform vec4 u_color;61varying float v_lifetime;62uniform sampler2D s_texture;63void main()64{65vec4 texColor;66texColor = texture2D(s_texture, gl_PointCoord);67gl_FragColor = vec4(u_color) * texColor;68gl_FragColor.a *= v_lifetime;69})";7071mProgram = CompileProgram(kVS, kFS);72if (!mProgram)73{74return false;75}7677// Get the attribute locations78mLifetimeLoc = glGetAttribLocation(mProgram, "a_lifetime");79mStartPositionLoc = glGetAttribLocation(mProgram, "a_startPosition");80mEndPositionLoc = glGetAttribLocation(mProgram, "a_endPosition");8182// Get the uniform locations83mTimeLoc = glGetUniformLocation(mProgram, "u_time");84mCenterPositionLoc = glGetUniformLocation(mProgram, "u_centerPosition");85mColorLoc = glGetUniformLocation(mProgram, "u_color");86mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");8788glClearColor(0.0f, 0.0f, 0.0f, 0.0f);8990// Fill in particle data array91for (size_t i = 0; i < mParticleCount; i++)92{93mParticles[i].lifetime = mRNG.randomFloatBetween(0.0f, 1.0f);9495float endAngle = mRNG.randomFloatBetween(0, 2.0f * float(M_PI));96float endRadius = mRNG.randomFloatBetween(0.0f, 2.0f);97mParticles[i].endPosition.x() = sinf(endAngle) * endRadius;98mParticles[i].endPosition.y() = cosf(endAngle) * endRadius;99mParticles[i].endPosition.z() = 0.0f;100101float startAngle = mRNG.randomFloatBetween(0, 2.0f * float(M_PI));102float startRadius = mRNG.randomFloatBetween(0.0f, 0.25f);103mParticles[i].startPosition.x() = sinf(startAngle) * startRadius;104mParticles[i].startPosition.y() = cosf(startAngle) * startRadius;105mParticles[i].startPosition.z() = 0.0f;106}107108mParticleTime = 1.0f;109110std::stringstream smokeStr;111smokeStr << angle::GetExecutableDirectory() << "/smoke.tga";112113TGAImage img;114if (!LoadTGAImageFromFile(smokeStr.str(), &img))115{116return false;117}118mTextureID = LoadTextureFromTGAImage(img);119if (!mTextureID)120{121return false;122}123124return true;125}126127void destroy() override { glDeleteProgram(mProgram); }128129void step(float dt, double totalTime) override130{131// Use the program object132glUseProgram(mProgram);133134mParticleTime += dt;135if (mParticleTime >= 1.0f)136{137mParticleTime = 0.0f;138139// Pick a new start location and color140Vector3 centerPos(mRNG.randomFloatBetween(-0.5f, 0.5f),141mRNG.randomFloatBetween(-0.5f, 0.5f),142mRNG.randomFloatBetween(-0.5f, 0.5f));143glUniform3fv(mCenterPositionLoc, 1, centerPos.data());144145// Random color146Vector4 color(mRNG.randomFloatBetween(0.0f, 1.0f), mRNG.randomFloatBetween(0.0f, 1.0f),147mRNG.randomFloatBetween(0.0f, 1.0f), 0.5f);148glUniform4fv(mColorLoc, 1, color.data());149}150151// Load uniform time variable152glUniform1f(mTimeLoc, mParticleTime);153}154155void draw() override156{157// Set the viewport158glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());159160// Clear the color buffer161glClear(GL_COLOR_BUFFER_BIT);162163// Use the program object164glUseProgram(mProgram);165166// Load the vertex attributes167glVertexAttribPointer(mLifetimeLoc, 1, GL_FLOAT, GL_FALSE, sizeof(Particle),168&mParticles[0].lifetime);169glVertexAttribPointer(mEndPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Particle),170&mParticles[0].endPosition);171glVertexAttribPointer(mStartPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Particle),172&mParticles[0].startPosition);173174glEnableVertexAttribArray(mLifetimeLoc);175glEnableVertexAttribArray(mEndPositionLoc);176glEnableVertexAttribArray(mStartPositionLoc);177178// Blend particles179glEnable(GL_BLEND);180glBlendFunc(GL_SRC_ALPHA, GL_ONE);181182// Bind the texture183glActiveTexture(GL_TEXTURE0);184glBindTexture(GL_TEXTURE_2D, mTextureID);185186// Set the sampler texture unit to 0187glUniform1i(mSamplerLoc, 0);188189glDrawArrays(GL_POINTS, 0, mParticleCount);190}191192private:193// Handle to a program object194GLuint mProgram;195196// Attribute locations197GLint mLifetimeLoc;198GLint mStartPositionLoc;199GLint mEndPositionLoc;200201// Uniform location202GLint mTimeLoc;203GLint mColorLoc;204GLint mCenterPositionLoc;205GLint mSamplerLoc;206207// Texture handle208GLuint mTextureID;209210// Particle vertex data211struct Particle212{213float lifetime;214Vector3 startPosition;215Vector3 endPosition;216};217static const size_t mParticleCount = 1024;218std::array<Particle, mParticleCount> mParticles;219float mParticleTime;220RNG mRNG;221};222223int main(int argc, char **argv)224{225ParticleSystemSample app(argc, argv);226return app.run();227}228229230