GPUParticles: Implement particle flip.

Snow quads suffers from folding, I have to investigate and/or ask hiker.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14969 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
vincentlj
2014-01-08 18:34:57 +00:00
parent c5c17747cb
commit 28d02f9622
4 changed files with 101 additions and 9 deletions

View File

@@ -7,6 +7,7 @@ uniform float track_x_len;
uniform float track_z_len;
uniform samplerBuffer heightmap;
uniform bool hasHeightMap;
uniform bool flips;
in vec2 quadcorner;
in vec2 texcoord;
@@ -14,6 +15,9 @@ in vec3 position;
in float lifetime;
in float size;
in vec3 rotationvec;
in float anglespeed;
out float lf;
out vec2 tc;
@@ -33,7 +37,54 @@ void main(void)
newposition.y = (h > 0.)? position.y : position.y - h;
}
vec4 viewpos = ViewMatrix * vec4(newposition, 1.0);
viewpos += size * vec4(quadcorner, 0., 0.);
gl_Position = ProjectionMatrix * viewpos;
if (flips)
{
// from http://jeux.developpez.com/faq/math
float angle = lf * anglespeed;
float sin_a = sin(angle / 2.);
float cos_a = cos(angle / 2.);
vec4 quaternion = normalize(vec4(rotationvec * sin_a, cos_a));
float xx = quaternion.x * quaternion.x;
float xy = quaternion.x * quaternion.y;
float xz = quaternion.x * quaternion.z;
float xw = quaternion.x * quaternion.w;
float yy = quaternion.y * quaternion.y;
float yz = quaternion.y * quaternion.z;
float yw = quaternion.y * quaternion.w;
float zz = quaternion.z * quaternion.z;
float zw = quaternion.z * quaternion.w;
vec4 col1 = vec4(
1. - 2. * ( yy + zz ),
2. * ( xy + zw ),
2. * ( xz - yw ),
0.);
vec4 col2 = vec4(
2. * ( xy - zw ),
1. - 2. * ( xx + zz ),
2. * ( yz + xw ),
0.);
vec4 col3 = vec4(
2. * ( xz + yw ),
2. * ( yz - xw ),
1. - 2. * ( xx + yy ),
0.);
vec4 col4 = vec4(0., 0., 0., 1.);
mat4 rotationMatrix = mat4(col1, col2, col3, col4);
vec3 newquadcorner = size * vec3(quadcorner, 0.);
newquadcorner = (rotationMatrix * vec4(newquadcorner, 0.)).xyz;
vec4 viewpos = ViewMatrix * vec4(newposition + newquadcorner, 1.0);
gl_Position = ProjectionMatrix * viewpos;
} else {
vec4 viewpos = ViewMatrix * vec4(newposition, 1.0);
viewpos += size * vec4(quadcorner, 0., 0.);
gl_Position = ProjectionMatrix * viewpos;
}
}

View File

@@ -75,6 +75,7 @@ ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter,
fakemat.BackfaceCulling = false;
glGenBuffers(1, &initial_values_buffer);
glGenBuffers(2, tfb_buffers);
glGenBuffers(1, &quaternionsbuffer);
size_increase_factor = 0.;
if (quad_vertex_buffer)
return;
@@ -94,6 +95,7 @@ ParticleSystemProxy::~ParticleSystemProxy()
{
glDeleteBuffers(2, tfb_buffers);
glDeleteBuffers(1, &initial_values_buffer);
glDeleteBuffers(1, &quaternionsbuffer);
if (has_height_map)
{
glDeleteBuffers(1, &heighmapbuffer);
@@ -106,6 +108,10 @@ void ParticleSystemProxy::setAlphaAdditive(bool val) { m_alpha_additive = val; }
void ParticleSystemProxy::setIncreaseFactor(float val) { size_increase_factor = val; }
void ParticleSystemProxy::setFlip() {
flip = true;
}
void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &hm,
float f1, float f2, float f3, float f4) {
track_x = f1, track_z = f2, track_x_len = f3, track_z_len = f4;
@@ -281,6 +287,7 @@ GLuint ParticleSystemProxy::uniform_track_x;
GLuint ParticleSystemProxy::uniform_track_x_len;
GLuint ParticleSystemProxy::uniform_track_z;
GLuint ParticleSystemProxy::uniform_track_z_len;
GLuint ParticleSystemProxy::uniform_flips;
GLuint ParticleSystemProxy::attrib_pos;
@@ -288,6 +295,8 @@ GLuint ParticleSystemProxy::attrib_lf;
GLuint ParticleSystemProxy::attrib_quadcorner;
GLuint ParticleSystemProxy::attrib_texcoord;
GLuint ParticleSystemProxy::attrib_sz;
GLuint ParticleSystemProxy::attrib_rotationvec;
GLuint ParticleSystemProxy::attrib_anglespeed;
GLuint ParticleSystemProxy::uniform_matrix;
GLuint ParticleSystemProxy::uniform_viewmatrix;
GLuint ParticleSystemProxy::uniform_texture;
@@ -314,6 +323,7 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
if (!emitter || !isGPUParticleType(emitter->getType()))
return;
has_height_map = false;
flip = false;
// Pass a fake material type to force irrlicht to update its internal states on rendering
setMaterialType(irr_driver->getShader(ES_RAIN));
setAutomaticCulling(0);
@@ -334,6 +344,24 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
default:
assert(0 && "Wrong particle type");
}
float *quaternions = new float[4 * count];
for (unsigned i = 0; i < count; i++)
{
core::vector3df rotationdir(1., 0., 0.);
rotationdir.rotateXYBy(os::Randomizer::frand() * 180.);
rotationdir.rotateYZBy(os::Randomizer::frand() * 180.);
rotationdir.rotateXZBy(os::Randomizer::frand() * 180.);
quaternions[4 * i] = rotationdir.X;
quaternions[4 * i + 1] = rotationdir.Y;
quaternions[4 * i + 2] = rotationdir.Z;
quaternions[4 * i + 3] = 3.14; // 10 rotation during lifetime
}
glGenBuffers(1, &quaternionsbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
delete[] quaternions;
glBindBuffer(GL_ARRAY_BUFFER, 0);
texture = getTextureGLuint(getMaterial(0).getTexture(0));
@@ -371,6 +399,9 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
attrib_lf = glGetAttribLocation(RenderProgram, "lifetime");
attrib_quadcorner = glGetAttribLocation(RenderProgram, "quadcorner");
attrib_texcoord = glGetAttribLocation(RenderProgram, "texcoord");
attrib_rotationvec = glGetAttribLocation(RenderProgram, "rotationvec");
attrib_anglespeed = glGetAttribLocation(RenderProgram, "anglespeed");
uniform_matrix = glGetUniformLocation(RenderProgram, "ProjectionMatrix");
uniform_viewmatrix = glGetUniformLocation(RenderProgram, "ViewMatrix");
@@ -384,6 +415,7 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
uniform_track_x_len = glGetUniformLocation(RenderProgram, "track_x_len");
uniform_track_z = glGetUniformLocation(RenderProgram, "track_z");
uniform_track_z_len = glGetUniformLocation(RenderProgram, "track_z_len");
uniform_flips = glGetUniformLocation(RenderProgram, "flips");
}
void ParticleSystemProxy::simulate()
@@ -483,6 +515,12 @@ void ParticleSystemProxy::draw()
glUniform1f(uniform_track_x_len, track_x_len);
glUniform1f(uniform_track_z_len, track_z_len);
}
glEnableVertexAttribArray(attrib_rotationvec);
glEnableVertexAttribArray(attrib_anglespeed);
glUniform1i(uniform_flips, flip);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glVertexAttribPointer(attrib_rotationvec, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(attrib_anglespeed, 1, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(3 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, quad_vertex_buffer);
glVertexAttribPointer(attrib_quadcorner, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
@@ -505,6 +543,8 @@ void ParticleSystemProxy::draw()
glDisableVertexAttribArray(attrib_quadcorner);
glDisableVertexAttribArray(attrib_texcoord);
glDisableVertexAttribArray(attrib_sz);
glDisableVertexAttribArray(attrib_rotationvec);
glDisableVertexAttribArray(attrib_anglespeed);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_BLEND);

View File

@@ -27,8 +27,8 @@ public:
class ParticleSystemProxy : public scene::CParticleSystemSceneNode {
protected:
video::SMaterial fakemat;
GLuint tfb_buffers[2], initial_values_buffer, heighmapbuffer, heightmaptexture;
bool m_alpha_additive, has_height_map;
GLuint tfb_buffers[2], initial_values_buffer, heighmapbuffer, heightmaptexture, quaternionsbuffer;
bool m_alpha_additive, has_height_map, flip;
float size_increase_factor, track_x, track_z, track_x_len, track_z_len;
static GLuint SimulationProgram;
@@ -36,8 +36,8 @@ protected:
static GLuint uniform_sourcematrix, uniform_dt, uniform_level, uniform_size_increase_factor, uniform_has_heightmap, uniform_heightmap;
static GLuint RenderProgram;
static GLuint attrib_pos, attrib_lf, attrib_quadcorner, attrib_texcoord, attrib_sz;
static GLuint uniform_matrix, uniform_viewmatrix, uniform_texture, uniform_normal_and_depths, uniform_screen, uniform_invproj;
static GLuint attrib_pos, attrib_lf, attrib_quadcorner, attrib_texcoord, attrib_sz, attrib_rotationvec, attrib_anglespeed;
static GLuint uniform_matrix, uniform_viewmatrix, uniform_texture, uniform_normal_and_depths, uniform_screen, uniform_invproj, uniform_flips;
static GLuint uniform_track_x, uniform_track_z, uniform_track_x_len, uniform_track_z_len;
@@ -70,6 +70,7 @@ public:
void setAlphaAdditive(bool);
void setIncreaseFactor(float);
void setHeightmap(const std::vector<std::vector<float> >&, float, float, float, float);
void setFlip();
};
class PointEmitter : public GPUParticle

View File

@@ -572,8 +572,8 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
if (flips)
{
if (irr_driver->isGLSL())
m_node->getMaterial(0).MaterialType = irr_driver->getShader(ES_SNOW);
m_node->getMaterial(0).BlendOperation = video::EBO_ADD;
static_cast<ParticleSystemProxy *>(m_node)->setFlip();
//m_node->getMaterial(0).BlendOperation = video::EBO_ADD;
}
}
} // setParticleType