Giter VIP home page Giter VIP logo

gemparticles's Introduction

GemParticles - Particles sandbox

This is a basic core-profile compliant OpenGL particle sandbox I used to create various visual effects and learning 3D concepts.

Updates and important mentions:

  • [2021/08/04] I decided to stop using this code or maintaining it. It was created with the intention of learning and not building a reusable framework for particles.
  • [2018/11/05] None of the following stats are using multi-threading. I might implement threaded stages in the system's pipeline. WIP
  • [2018/11/05] I'm currently working on GPU particles with Curl noise...
  • Big thanks to Mr. Lariviere for the help!

Description

The code itself is pretty simple and follows a templated data-oriented design. The ParticlesSystem class is type-bound to the particle structure. It also contains a renderer, dynamics and emitters and a particle pool. For each experiment that I want to make I create a new cmake library project that is built in the GemParticlesApp executable project and by passing the project name as an argument to the executable you can select which experiment you want to load.

Highlights

Here are some highlights that I managed to create with this system. Please note that, at the time of taking those screenshots, I had an i5-3570k CPU and Geforce GTX 660 GPU.

Lit particles or particles with 200 dynamic CPU lights 500000 CPU particles attracted toward a location with hot and cold colors and some rain... (1 million CPU particles)

Launching or installing the project

The project uses CMake files for portability and the Conan package manager to manage the dependencies so in order to launch the whole thing you have to

  1. Ensure you have both CMake (at least 3.10) and Conan installed. See https://cmake.org/install/ and https://docs.conan.io/en/latest/installation.html respectively for more details.
  2. mkdir build && cd build
  3. conan install .. (NOTE: it's possible you have to run conan profile new default --detect beforehand and set prefered compiler and architecture to 64 bits which is the architecture I've been using)
  4. Generate the projects using CMake (cmake .. -G "MY PREFERED BUILD TOOL")
  5. Build using the generated files
  6. Launch by passing the project name to the executable (e.g. ./GemparticlesApp.exe lit_particles)

External libraries

I'm using various external libraries in this project which are listed in the file conanfile.txt

  • ImGui
  • GLM
  • Glew
  • GLFW
  • STB
  • OpenGL

Utilities

I pretty much built this from scratch looking up efficient design patterns and tutorials. So you'll find a handful of utilities that I built to help me create stuff more easily. Most of them are named as modules.

  • Light module
  • Shader module
  • Texture module
  • Timer

And last but not least, some wrapper utilities I built around ImGui examples. This includes

  • A property editor
  • A logger

Extending the project

If you want to create your own project using this "engine" or the project structure you can

  1. Add the project to the list of sub-directories in projects cmakelists.txt file
  2. Register the project in the project dictionary (if you use the REGISTER_STD_PROJECT you'll have to define the init, run and terminate functions in your project)
  3. Add your own cmakelists.txt and sub-directory in the projects/ folder
  4. Refer to the other projects' blueprints or *_project.cc files
  5. Run the GemParticlesApp (main) executable with the name of your project passed as an argument.

gemparticles's People

Contributors

frtru avatar larivierec avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

gemparticles's Issues

As a developer, I want to replace VS files with a CMakeLists.txt file

Currently, I am using an hand-made visual studio solution. My aim is to also develop under a linux distribution, so I'd like to have CMakeLists.txt file that

  • Generates the corresponding compilation tools depending on which OS I'm working on
    • A Visual Studio solution when I'm on windows
    • A makefile running gcc or clang when I'm on Linux
  • Links with the external libraries I will be using
    • GLM
    • AntTweakBar
    • OpenGL
    • OpenCL
  • Includes all the source code in this project

Error handling

Useful references:
http://gamedev.stackexchange.com/questions/46424/try-catch-or-ifs-for-error-handling-in-c
http://bitsquid.blogspot.ca/2012/01/sensible-error-handling-part-1.html

  • Adopt an uniform method of handling errors (instead of returning bools at some places and 0xFFFFFFFF at other places...)
  • If keeping the 0xFFFFFFF, use UINT32_MAX instead
  • For shaders it might be a bigger problem if an error occurs, because the program will simply not work properly (in contrast with the textures which is not a big problem for the app itself if they fail)

Resolve some todos (3/3)

in files

  • particle_system.* (do not care about the remove thingy and parallel stuff)
  • particle_system_component.*
  • app.*

Some refactor needed

  • - Put shared_ptr/unique_ptr where applicable,
  • - check if component pattern is applicable : http://gameprogrammingpatterns.com/component.html
  • - Rename everything properly
  • - Change unique_ptrs for raw pointers in pool to see if it gives some performance boost
  • - Apply macros for copyable/movable everywhere
  • - Change raw classes for pointers (when it is an attribute of a class)
  • - Should also create folders and corresponding namespaces for classes (core,utils,dynamics,etc.)
  • - Remove the PUBLIC init/terminate idiom in classes and put initialization in constructor.

Update CMake files...

Since the last time the Cmake files were updated a lot of new files and external libraries were added to the project. I am currently maintaining a VS solution, but if people want to reuse this project, we need to this for sure.

I want to decouple the projects in my application

Right now, the application loads explicitely (hardcoded in the code) all the different projects that could be executed in the application.

It could be replaced by another setup like this one :

Each project has its own dll/.so, the engine is a .lib/.a
and the executable only runs the dll/.so loading (through .ini/xml files maybe?)
and launching the said dynamic library. But this is good enough for now for decoupling.
An issue will be created for this.

I also tried to register the projects in a map in a static fashion, meaning that its initialization(project registration) would be executed before the logic in the main, but ran into runtime issues. Wanted to focus on the core.

Lit particles

Just as explained here https://www.youtube.com/watch?v=7hC_QT4GLiU

NOTE: GeForce GTX 660 limits:

  • GL_MAX_UNIFORM_BUFFER_BINDINGS -> 84

  • GL_MAX_UNIFORM_BLOCK_SIZE -> 65536 (bytes)

  • GL_MAX_VERTEX_UNIFORM_BLOCKS -> 14

  • GL_MAX_FRAGMENT_UNIFORM_BLOCKS -> 14

  • GL_MAX_GEOMETRY_UNIFORM_BLOCKS -> 14

  • See light_module.cc, current implementation is not good enough for having particle lights. I need the Light structure to be directly integrated in a new ParticleData (like in particle_core_data.hh).
    struct ParticlesLight {
    float intensity;
    float radius;
    float attenuation;
    };

struct LitParticlesData {
std::unique_ptr<float[] > m_lifetime;
std::unique_ptrglm::f32vec3[] m_velocity;
std::unique_ptr<glm::u8vec4[] > m_color;
std::unique_ptrglm::f32vec3[] m_position;
std::unique_ptr<ParticlesLight[]> m_light;
...
};

NO, in fact the attributes of ParticlesLight will be shared for all particles. So ParticleCoreData is enough, I only need a light updater (CPU or GPU). If CPU, this light updater only needs to update the UBO block, which will look like this:

layout (std140, binding = WHATEVER) uniform ParticleLightsData {
vec4 ParticleColors[2000];
vec3 ParticlePosition[2000];
float Radius;
float Intensity;
float Attenuation;
}

The 2000 is a rounded value that matches GL_MAX_UNIFORM_BLOCK_SIZE (65536 byte for Geforce GTX 660) for the UBO above (total size is 56012 bytes).

Also, UBOs are usually faster than SSBOs, and it is quite standard to use uniforms this way, (see https://github.com/andreasmuller/NoiseWorkshop/blob/05eacee5dc58e48265e0153aba9ad2782190f185/ParticleCloudGPU/src/ParticleSystemGPU.cpp#L128)

  • A parameter will determine what is the percentage of particles that will emit lights. This percentage will cap at PERCENTAGE * NUMBER_OF_PARTICLES * SIZEOF(LIGHTDATA) < GL_MAX_UNIFORM_BLOCK_SIZE (in other words, needs to be < GL_MAX_UNIFORM_BLOCK_SIZE/(NUMBER_OF_PARTICLES * SIZEOF(LIGHT_DATA))). So with the data above, if particle_count = 5000, the percentage must cap at <=40% (0.4*5000 = 2000).

  • Since the alive particles (in the pool) are not sorted, the first ones could be the lit particles. To make sure this is truly "random", the life of each particles should be randomized (their age should be randomized and capped at maximum lifetime)

Design some new entities/functions to move all the temporary stuff and the todos

  • The axis lines should be put as a debug option....maybe of opengl_context or something new. Certainly not the renderers, because it would be something to duplicate in each renderer. Also there'll be more than one renderer per system (most likely) and this needs to be rendered only once.

  • Find a place where to put the MVP matrix.

Create builder/factory/DI entities for the following entities

ShaderManager
GraphicContext
Camera
ParticleSystem

http://gameprogrammingpatterns.com/service-locator.html
http://gameprogrammingpatterns.com/component.html

I love the servicelocator pattern for the factories...check how it integrates.

Redesign with component pattern
rename sources to spawns
rename dynamics (maybe?)
set both as deriving from a component class
start to integrate the entity/component pattern where the particlesystem is an entity/aggregate of components and we could have a noise component which would be a dynamic

Sort the particlemodule by program IDs

There's a performance leak for applications that switch programs too often. There shouldn't be any other program IDs outside of the renderers, except for entities which use compute shaders, so it shouldn't be that hard to implement.

Change emitter position with mouse position and left click press

When pressing left click, particle emitter position should be set accordingly with mouse position translated into world coordinates. Emission rate should also be set to 0 when left button is released.

This implies either changing unique_ptrs for emitters and dynamics in the particle_system to shared_ptrs and add a shared_ptr to the corresponding emitter somewhere (event handler?.....) OR go through an ID for the emitter object ID and add methods in the Iparticle system to set parameters....

I want to have a pseudo-blueprint extensible system for the particle systems

In other words, I want to be able to keep track and have multiple particlesystems in my applications. They would be accissble from a dictionary and selected by either :

  • inputs sent to the program
  • project properties including definition of a macro
  • directly in the code of main selecting the right project

I need to have a dedicated module for OpenGL related initialization and destruction manipulations in my app

Currently everything is in app.cc, I need to seperate the glfw, glew and even shadermanager initialization in a separate component.

Solutions are:
1- Clean the way it is used in app.cc and leave it there
2- Maybe have a component structure?
3- Have a GraphicContext class and make OpenGLContext and Direct3D (or whatever it's called) inherit from it
4- I like the name GraphicComponent, but it would be confusing and I could easily assume I need to use this to render something...

GPU Particles

NOTE: As seen here https://github.com/amulware/genericgamedev-gpu-particles/tree/cpu-gpu-comparison/GenericGamedev.Pixelation
The CPUSimpleParticles.cs, AlmostGPUParticles.cs and GPUParticles.cs demonstrate how you can completely render/update on the GPU.

List of things to do for this:

  • Need to add a call from app to particlesystem or something else
  • Maybe add renderers or entities that can iterate through all the pool particles and render and use the camera and add some special effects i guess
  • I need to provide minimal implementation in the shaders (take the matrices and multiply it with the vertex location)

SEE THIIIS
http://stackoverflow.com/questions/8608844/resizing-point-sprites-based-on-distance-from-the-camera he uses a sampler2darray as a uniform, would it be possible that way?

COMPUTE SHADERS

Fix camera movements with user inputs.

  1. Bug when moving camera with middle mouse button. After clicking, the cursor is positionned at the place where the cursor was when the middle mouse button was released.
  2. Sometimes when moving camera with W,A,S,D, the camera does a 180 degree turn instantly.

Glass particles

https://goo.gl/images/og7RaI

Prerequisite(s) :

  • - Be able to display sprites with blending
  • - Find adequate textures/material (IMPOORTANT)
  • - Have an event manager specific per project
  • - Find the right type of blending for this kind of particles
  • - Have an UI that allows me to change parameters at runtime

Implementation will need:

  • - Find a way to store the info about normals for each vertex (must use quads directly instead of points, OOORRR maybe we could still use billboards? would kinda look weird but the normals would be easy to compute (see wPosToCamera in geom shader)) BETTER IDEA: We could simply keep the normal vector and generate the quad from it and apply the texture (would need an up vector also)....
  • - Material class
  • - A luminosity intensity gradient array -> NOPE
  • - Lights (particles will need to have reflection and refraction)
  • - Particles must have a random initial rotation axis and rotate around it
  • - When they are about to die, particles drops their alpha value so that they fade-out in the oblivion
  • - Curl noise to give a leaf effect
  • - Not sure they will have to face the camera

Add anttweakbar to the project

See how it integrates with GLFW. You might have to reenable cursor upon a certain click to make it available for selecting some features. Maybe when middle mouse button is released or something.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.