Edit

kc3-lang/angle/samples/particle_system/ParticleSystem.cpp

Branch :

  • Show log

    Commit

  • Author : Stuart Morgan
    Date : 2019-08-14 12:25:12
    Hash : 9d737966
    Message : Standardize copyright notices to project style For all "ANGLE Project" copyrights, standardize to the format specified by the style guide. Changes: - "Copyright (c)" and "Copyright(c)" changed to just "Copyright". - Removed the second half of date ranges ("Y1Y1-Y2Y2"->"Y1Y1"). - Fixed a small number of files that had no copyright date using the initial commit year from the version control history. - Fixed one instance of copyright being "The ANGLE Project" rather than "The ANGLE Project Authors" These changes are applied both to the copyright of source file, and where applicable to copyright statements that are generated by templates. BUG=angleproject:3811 Change-Id: I973dd65e4ef9deeba232d5be74c768256a0eb2e5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1754397 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • samples/particle_system/ParticleSystem.cpp
  • //
    // Copyright 2014 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    //            Based on ParticleSystem.c from
    // Book:      OpenGL(R) ES 2.0 Programming Guide
    // Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
    // ISBN-10:   0321502795
    // ISBN-13:   9780321502797
    // Publisher: Addison-Wesley Professional
    // URLs:      http://safari.informit.com/9780321563835
    //            http://www.opengles-book.com
    
    #include "SampleApplication.h"
    
    #include "common/vector_utils.h"
    #include "tga_utils.h"
    #include "util/random_utils.h"
    #include "util/shader_utils.h"
    #include "util/system_utils.h"
    
    #define _USE_MATH_DEFINES
    #include <math.h>
    
    using namespace angle;
    
    class ParticleSystemSample : public SampleApplication
    {
      public:
        ParticleSystemSample(int argc, char **argv) : SampleApplication("ParticleSystem", argc, argv) {}
    
        bool initialize() override
        {
            constexpr char kVS[] = R"(uniform float u_time;
    uniform vec3 u_centerPosition;
    attribute float a_lifetime;
    attribute vec3 a_startPosition;
    attribute vec3 a_endPosition;
    varying float v_lifetime;
    void main()
    {
        if (u_time <= a_lifetime)
        {
            gl_Position.xyz = a_startPosition + (u_time * a_endPosition);
            gl_Position.xyz += u_centerPosition;
            gl_Position.w = 1.0;
        }
        else
        {
            gl_Position = vec4(-1000, -1000, 0, 0);
        }
        v_lifetime = 1.0 - (u_time / a_lifetime);
        v_lifetime = clamp(v_lifetime, 0.0, 1.0);
        gl_PointSize = (v_lifetime * v_lifetime) * 40.0;
    })";
    
            constexpr char kFS[] = R"(precision mediump float;
    uniform vec4 u_color;
    varying float v_lifetime;
    uniform sampler2D s_texture;
    void main()
    {
        vec4 texColor;
        texColor = texture2D(s_texture, gl_PointCoord);
        gl_FragColor = vec4(u_color) * texColor;
        gl_FragColor.a *= v_lifetime;
    })";
    
            mProgram = CompileProgram(kVS, kFS);
            if (!mProgram)
            {
                return false;
            }
    
            // Get the attribute locations
            mLifetimeLoc      = glGetAttribLocation(mProgram, "a_lifetime");
            mStartPositionLoc = glGetAttribLocation(mProgram, "a_startPosition");
            mEndPositionLoc   = glGetAttribLocation(mProgram, "a_endPosition");
    
            // Get the uniform locations
            mTimeLoc           = glGetUniformLocation(mProgram, "u_time");
            mCenterPositionLoc = glGetUniformLocation(mProgram, "u_centerPosition");
            mColorLoc          = glGetUniformLocation(mProgram, "u_color");
            mSamplerLoc        = glGetUniformLocation(mProgram, "s_texture");
    
            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
            // Fill in particle data array
            for (size_t i = 0; i < mParticleCount; i++)
            {
                mParticles[i].lifetime = mRNG.randomFloatBetween(0.0f, 1.0f);
    
                float endAngle                = mRNG.randomFloatBetween(0, 2.0f * float(M_PI));
                float endRadius               = mRNG.randomFloatBetween(0.0f, 2.0f);
                mParticles[i].endPosition.x() = sinf(endAngle) * endRadius;
                mParticles[i].endPosition.y() = cosf(endAngle) * endRadius;
                mParticles[i].endPosition.z() = 0.0f;
    
                float startAngle                = mRNG.randomFloatBetween(0, 2.0f * float(M_PI));
                float startRadius               = mRNG.randomFloatBetween(0.0f, 0.25f);
                mParticles[i].startPosition.x() = sinf(startAngle) * startRadius;
                mParticles[i].startPosition.y() = cosf(startAngle) * startRadius;
                mParticles[i].startPosition.z() = 0.0f;
            }
    
            mParticleTime = 1.0f;
    
            std::stringstream smokeStr;
            smokeStr << angle::GetExecutableDirectory() << "/smoke.tga";
    
            TGAImage img;
            if (!LoadTGAImageFromFile(smokeStr.str(), &img))
            {
                return false;
            }
            mTextureID = LoadTextureFromTGAImage(img);
            if (!mTextureID)
            {
                return false;
            }
    
            return true;
        }
    
        void destroy() override { glDeleteProgram(mProgram); }
    
        void step(float dt, double totalTime) override
        {
            // Use the program object
            glUseProgram(mProgram);
    
            mParticleTime += dt;
            if (mParticleTime >= 1.0f)
            {
                mParticleTime = 0.0f;
    
                // Pick a new start location and color
                Vector3 centerPos(mRNG.randomFloatBetween(-0.5f, 0.5f),
                                  mRNG.randomFloatBetween(-0.5f, 0.5f),
                                  mRNG.randomFloatBetween(-0.5f, 0.5f));
                glUniform3fv(mCenterPositionLoc, 1, centerPos.data());
    
                // Random color
                Vector4 color(mRNG.randomFloatBetween(0.0f, 1.0f), mRNG.randomFloatBetween(0.0f, 1.0f),
                              mRNG.randomFloatBetween(0.0f, 1.0f), 0.5f);
                glUniform4fv(mColorLoc, 1, color.data());
            }
    
            // Load uniform time variable
            glUniform1f(mTimeLoc, mParticleTime);
        }
    
        void draw() override
        {
            // Set the viewport
            glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
    
            // Clear the color buffer
            glClear(GL_COLOR_BUFFER_BIT);
    
            // Use the program object
            glUseProgram(mProgram);
    
            // Load the vertex attributes
            glVertexAttribPointer(mLifetimeLoc, 1, GL_FLOAT, GL_FALSE, sizeof(Particle),
                                  &mParticles[0].lifetime);
            glVertexAttribPointer(mEndPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Particle),
                                  &mParticles[0].endPosition);
            glVertexAttribPointer(mStartPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Particle),
                                  &mParticles[0].startPosition);
    
            glEnableVertexAttribArray(mLifetimeLoc);
            glEnableVertexAttribArray(mEndPositionLoc);
            glEnableVertexAttribArray(mStartPositionLoc);
    
            // Blend particles
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    
            // Bind the texture
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, mTextureID);
    
            // Set the sampler texture unit to 0
            glUniform1i(mSamplerLoc, 0);
    
            glDrawArrays(GL_POINTS, 0, mParticleCount);
        }
    
      private:
        // Handle to a program object
        GLuint mProgram;
    
        // Attribute locations
        GLint mLifetimeLoc;
        GLint mStartPositionLoc;
        GLint mEndPositionLoc;
    
        // Uniform location
        GLint mTimeLoc;
        GLint mColorLoc;
        GLint mCenterPositionLoc;
        GLint mSamplerLoc;
    
        // Texture handle
        GLuint mTextureID;
    
        // Particle vertex data
        struct Particle
        {
            float lifetime;
            Vector3 startPosition;
            Vector3 endPosition;
        };
        static const size_t mParticleCount = 1024;
        std::array<Particle, mParticleCount> mParticles;
        float mParticleTime;
        RNG mRNG;
    };
    
    int main(int argc, char **argv)
    {
        ParticleSystemSample app(argc, argv);
        return app.run();
    }