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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user