GPUParticles: Got PointEmitter to draw something at last.

Still WIP, uses a #ifdef to disable it but I wanted to keep a working commit
somewhere in case I mess up somewhere.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14829 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
vincentlj 2013-12-29 18:23:36 +00:00
parent 681f095140
commit 4c725ac8f4
6 changed files with 484 additions and 287 deletions

View File

@ -0,0 +1,12 @@
#version 130
in float lifetime;
out vec3 color;
void main(void)
{
color = vec3(
(lifetime < 33.) ? 1. : 0.,
(lifetime < 67. && lifetime >= 34.) ? 1. : 0.,
(lifetime > 68.) ? 1. : 0.);
}

View File

@ -0,0 +1,13 @@
#version 130
in vec3 position;
in float lf;
uniform mat4 matrix;
out float lifetime;
void main(void)
{
gl_PointSize = 10.;
gl_Position = matrix * vec4(position, 1.0);
lifetime = lf;
}

View File

@ -0,0 +1,20 @@
#version 130
uniform int dt;
uniform vec3 source;
uniform int duration;
in vec3 particle_position;
in float lifetime;
in vec4 particle_velocity;
out vec3 new_particle_position;
out float new_lifetime;
out vec4 new_particle_velocity;
void main(void)
{
new_particle_position = (lifetime > 0.) ? particle_position + particle_velocity.xyz * float(dt) : vec3(0., 0., 0.);
new_lifetime = (lifetime > 0.) ? lifetime - float(dt) : float(duration);
new_particle_velocity = particle_velocity;
gl_Position = vec4(0.);
}

View File

@ -41,6 +41,7 @@ PFNGLUNIFORM2FPROC glUniform2f;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
#endif
void initGL()
@ -78,6 +79,7 @@ void initGL()
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)IRR_OGL_LOAD_EXTENSION("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)IRR_OGL_LOAD_EXTENSION("glGetProgramInfoLog");
glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)IRR_OGL_LOAD_EXTENSION("glTransformFeedbackVaryings");
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)IRR_OGL_LOAD_EXTENSION("glGetAttribLocation");
#endif
}
@ -191,7 +193,7 @@ void GPUParticle::render() {
}
void GPUParticle::OnRegisterSceneNode() {
if (IsVisible &&
if (
(irr_driver->getRenderPass() & irr::scene::ESNRP_TRANSPARENT) == irr::scene::ESNRP_TRANSPARENT)
{
SceneManager->registerNodeForRendering(this, irr::scene::ESNRP_TRANSPARENT);
@ -199,6 +201,112 @@ void GPUParticle::OnRegisterSceneNode() {
ISceneNode::OnRegisterSceneNode();
}
#define COMPONENTCOUNT 8
PointEmitter::PointEmitter(scene::ISceneManager* mgr, ITexture *tex,
const core::vector3df& direction,
u32 minParticlesPerSecond,
u32 maxParticlesPerSecond,
const video::SColor& minStartColor,
const video::SColor& maxStartColor,
u32 lifeTimeMin, u32 lifeTimeMax,
s32 maxAngleDegrees
// const core::dimension2df& minStartSize,
// const core::dimension2df& maxStartSize
) : GPUParticle(mgr, tex) {
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
//"gl_SkipComponents3"
};
SimulationProgram = LoadTFBProgram(file_manager->getAsset("shaders/pointemitter.vert").c_str(), varyings, 3);
loc_duration = glGetUniformLocation(SimulationProgram, "duration");
loc_dt = glGetUniformLocation(SimulationProgram, "dt");
loc_source = glGetUniformLocation(SimulationProgram, "source");
loc_position = glGetAttribLocation(SimulationProgram, "particle_position");
loc_lifetime = glGetAttribLocation(SimulationProgram, "lifetime");
loc_velocity = glGetAttribLocation(SimulationProgram, "particle_velocity");
printf("locs are %d, %d, %d\n", loc_position, loc_lifetime, loc_velocity);
RenderProgram = LoadProgram(file_manager->getAsset("shaders/particle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
loc_matrix = glGetUniformLocation(RenderProgram, "matrix");
count = 25;
float *particles = new float[COMPONENTCOUNT * count];
for (unsigned i = 0; i < count; i++) {
particles[COMPONENTCOUNT * i] = 0.;// getPosition().X;
particles[COMPONENTCOUNT * i + 1] = 0.;// getPosition().Y;
particles[COMPONENTCOUNT * i + 2] = 0.;//getPosition().Z;
particles[COMPONENTCOUNT * i + 3] = i * 10;
particles[COMPONENTCOUNT * i + 4] = direction.X;
particles[COMPONENTCOUNT * i + 5] = direction.Y;
particles[COMPONENTCOUNT * i + 6] = direction.Z;
// particles[COMPONENTCOUNT * i + 8] = 100.;
//memcpy(&particles[COMPONENTCOUNT * i + 3], &i, sizeof(float));
}
printf("dir is %f, %f, %f\n", direction.X, direction.Y, direction.Z);
glGenBuffers(2, tfb_buffers);
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glBufferData(GL_ARRAY_BUFFER, COMPONENTCOUNT * count * sizeof(float), particles, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[1]);
glBufferData(GL_ARRAY_BUFFER, COMPONENTCOUNT * count * sizeof(float), 0, GL_STREAM_DRAW);
delete [] particles;
}
void PointEmitter::simulate()
{
glUseProgram(SimulationProgram);
glEnable(GL_RASTERIZER_DISCARD);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glVertexAttribPointer(loc_position, 3, GL_FLOAT, GL_FALSE, COMPONENTCOUNT * sizeof(float), (GLvoid*)0);
glVertexAttribPointer(loc_lifetime, 1, GL_FLOAT, GL_FALSE, COMPONENTCOUNT * sizeof(float), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(loc_velocity, 4, GL_FLOAT, GL_FALSE, COMPONENTCOUNT * sizeof(float), (GLvoid*)(4 * sizeof(float)));
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]);
glUniform1i(loc_dt, 1);
glUniform1i(loc_duration, 100);
glUniform3f(loc_source, getPosition().X, getPosition().Y, getPosition().Z);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, count);
glEndTransformFeedback();
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisable(GL_RASTERIZER_DISCARD);
std::swap(tfb_buffers[0], tfb_buffers[1]);
}
void PointEmitter::draw()
{
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
core::matrix4 matrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
matrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
matrix *= getAbsoluteTransformation();;
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glEnable(GL_POINT_SPRITE);
glUseProgram(RenderProgram);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glUniformMatrix4fv(loc_matrix, 1, GL_FALSE, matrix.pointer());
glVertexAttribPointer(glGetAttribLocation(RenderProgram, "position"), 3, GL_FLOAT, GL_FALSE, COMPONENTCOUNT * sizeof(float), 0);
glVertexAttribPointer(glGetAttribLocation(RenderProgram, "lf"), 1, GL_FLOAT, GL_FALSE, COMPONENTCOUNT * sizeof(float), (GLvoid *)(3 * sizeof(float)));
glDrawArrays(GL_POINTS, 0, count);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
}
RainNode::RainNode(scene::ISceneManager* mgr, ITexture *tex)
: GPUParticle(mgr, tex)
{

View File

@ -20,12 +20,41 @@ protected:
virtual void simulate() = 0;
virtual void draw() = 0;
public:
//GPUParticle(unsigned c, float *initialSamples, GLuint tex, GLuint rtt);
GPUParticle(scene::ISceneManager* mgr, ITexture *tex);
virtual void render();
virtual void OnRegisterSceneNode();
};
class PointEmitter : public GPUParticle
{
protected:
GLuint SimulationProgram, RenderProgram;
GLuint loc_duration, loc_source, loc_dt, loc_matrix;
GLuint loc_position, loc_velocity, loc_lifetime;
GLuint tfb_buffers[2];
unsigned duration, count;
core::vector3df direction;
core::aabbox3d<f32> box;
virtual void simulate();
virtual void draw();
public:
PointEmitter(
scene::ISceneManager* mgr, ITexture *tex,
const core::vector3df& dir,
u32 minParticlesPerSecond,
u32 maxParticlesPerSecond,
const video::SColor& minStartColor,
const video::SColor& maxStartColor,
u32 lifeTimeMin, u32 lifeTimeMax,
s32 maxAngleDegrees
// const core::dimension2df& minStartSize,
// const core::dimension2df& maxStartSize
);
virtual const core::aabbox3d<f32>& getBoundingBox() const { return box; }
virtual u32 getMaterialCount() const { return 1; }
};
class RainNode : public GPUParticle
{
protected:

View File

@ -28,6 +28,7 @@
#include "tracks/track.hpp"
#include "utils/constants.hpp"
#include "utils/helpers.hpp"
#include "graphics/gpuparticles.h"
#include <SParticle.h>
#include <IParticleAffector.h>
@ -436,11 +437,25 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
case EMITTER_POINT:
{
m_emitter = m_node->createPointEmitter(velocity,
#ifdef GPUPARTICLE
0., 0.,
#else
type->getMinRate(), type->getMaxRate(),
#endif
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread() /* angle */
);
#ifdef GPUPARTICLE
PointEmitter *PE = new PointEmitter(irr_driver->getSceneManager(), m_node->getMaterial(0).getTexture(0),
velocity,
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread());
PE->setPosition(m_node->getPosition());
irr_driver->addPerCameraNode(PE, irr_driver->getSceneManager()->getActiveCamera(), NULL);
#endif
break;
}