GPUParticles: Implement HeightMapAffector equivalent.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14961 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
vincentlj 2014-01-07 21:06:06 +00:00
parent 0be4825ef2
commit 5b8ca4fcd7
6 changed files with 94 additions and 5 deletions

View File

@ -1,6 +1,12 @@
#version 130
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform float track_x;
uniform float track_z;
uniform float track_x_len;
uniform float track_z_len;
uniform samplerBuffer heightmap;
uniform bool hasHeightMap;
in vec2 quadcorner;
in vec2 texcoord;
@ -15,7 +21,19 @@ void main(void)
{
tc = texcoord;
lf = lifetime;
vec4 viewpos = ViewMatrix * vec4(position, 1.0);
vec3 newposition = position;
float i_as_float = clamp(256. * (position.x - track_x) / track_x_len, 0., 255.);
float j_as_float = clamp(256. * (position.z - track_z) / track_z_len, 0., 255.);
int i = int(i_as_float);
int j = int(j_as_float);
if (hasHeightMap) {
float h = position.y - texelFetch(heightmap, i * 256 + j).r;
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;
}

View File

@ -47,6 +47,7 @@ PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLTEXBUFFERPROC glTexBuffer;
#endif
static GLuint quad_buffer;
@ -167,6 +168,7 @@ void initGL()
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteVertexArrays");
glTexBuffer = (PFNGLTEXBUFFERPROC)IRR_OGL_LOAD_EXTENSION("glTexBuffer");
#endif
#if ENABLE_ARB_DEBUG_OUTPUT
glDebugMessageCallbackARB(debugCallback, NULL);

View File

@ -70,6 +70,7 @@ extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLTEXBUFFERPROC glTexBuffer;
#endif
// core::rect<s32> needs these includes

View File

@ -94,12 +94,40 @@ ParticleSystemProxy::~ParticleSystemProxy()
{
glDeleteBuffers(2, tfb_buffers);
glDeleteBuffers(1, &initial_values_buffer);
if (has_height_map)
glDeleteBuffers(1, &heighmapbuffer);
}
void ParticleSystemProxy::setAlphaAdditive(bool val) { m_alpha_additive = val; }
void ParticleSystemProxy::setIncreaseFactor(float val) { size_increase_factor = val; }
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;
printf("track_x is %f, track_x_len is %f, track_z is %f, track_z_len is %f\n",
track_x, track_x_len, track_z, track_z_len);
unsigned width = hm.size();
unsigned height = hm[0].size();
float *hm_array = new float[width * height];
for (unsigned i = 0; i < width; i++)
{
for (unsigned j = 0; j < height; j++)
{
hm_array[i * height + j] = hm[i][j];
}
}
has_height_map = true;
glGenBuffers(1, &heighmapbuffer);
glBindBuffer(GL_TEXTURE_BUFFER, heighmapbuffer);
glBufferData(GL_TEXTURE_BUFFER, width * height * sizeof(float), hm_array, GL_STATIC_DRAW);
glGenTextures(1, &heightmaptexture);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, heighmapbuffer);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
delete[] hm_array;
}
static
void generateLifetimeSizeDirection(scene::IParticleEmitter *emitter, float &lifetime, float &size, float &dirX, float &dirY, float &dirZ)
{
@ -243,6 +271,12 @@ GLuint ParticleSystemProxy::uniform_sourcematrix;
GLuint ParticleSystemProxy::uniform_dt;
GLuint ParticleSystemProxy::uniform_level;
GLuint ParticleSystemProxy::uniform_size_increase_factor;
GLuint ParticleSystemProxy::uniform_has_heightmap;
GLuint ParticleSystemProxy::uniform_heightmap;
GLuint ParticleSystemProxy::uniform_track_x;
GLuint ParticleSystemProxy::uniform_track_x_len;
GLuint ParticleSystemProxy::uniform_track_z;
GLuint ParticleSystemProxy::uniform_track_z_len;
GLuint ParticleSystemProxy::attrib_pos;
@ -275,6 +309,7 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
CParticleSystemSceneNode::setEmitter(emitter);
if (!emitter || !isGPUParticleType(emitter->getType()))
return;
has_height_map = false;
// Pass a fake material type to force irrlicht to update its internal states on rendering
setMaterialType(irr_driver->getShader(ES_RAIN));
setAutomaticCulling(0);
@ -339,6 +374,12 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
uniform_invproj = glGetUniformLocation(RenderProgram, "invproj");
uniform_screen = glGetUniformLocation(RenderProgram, "screen");
uniform_normal_and_depths = glGetUniformLocation(RenderProgram, "normals_and_depth");
uniform_has_heightmap = glGetUniformLocation(RenderProgram, "hasHeightMap");
uniform_heightmap = glGetUniformLocation(RenderProgram, "heightmap");
uniform_track_x = glGetUniformLocation(RenderProgram, "track_x");
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");
}
void ParticleSystemProxy::simulate()
@ -380,6 +421,7 @@ void ParticleSystemProxy::simulate()
glUniform1i(uniform_level, active_count);
glUniformMatrix4fv(uniform_sourcematrix, 1, GL_FALSE, matrix.pointer());
glUniform1f(uniform_size_increase_factor, size_increase_factor);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, count);
glEndTransformFeedback();
@ -426,6 +468,18 @@ void ParticleSystemProxy::draw()
glUniformMatrix4fv(uniform_matrix, 1, GL_FALSE, irr_driver->getProjMatrix().pointer());
glUniformMatrix4fv(uniform_viewmatrix, 1, GL_FALSE, irr_driver->getViewMatrix().pointer());
glUniform1i(uniform_has_heightmap, has_height_map);
if (has_height_map)
{
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
glUniform1i(uniform_heightmap, 2);
glUniform1f(uniform_track_x, track_x);
glUniform1f(uniform_track_z, track_z);
glUniform1f(uniform_track_x_len, track_x_len);
glUniform1f(uniform_track_z_len, track_z_len);
}
glBindBuffer(GL_ARRAY_BUFFER, quad_vertex_buffer);
glVertexAttribPointer(attrib_quadcorner, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float)));

View File

@ -27,18 +27,20 @@ public:
class ParticleSystemProxy : public scene::CParticleSystemSceneNode {
protected:
video::SMaterial fakemat;
GLuint tfb_buffers[2], initial_values_buffer;
bool m_alpha_additive;
float size_increase_factor;
GLuint tfb_buffers[2], initial_values_buffer, heighmapbuffer, heightmaptexture;
bool m_alpha_additive, has_height_map;
float size_increase_factor, track_x, track_z, track_x_len, track_z_len;
static GLuint SimulationProgram;
static GLuint attrib_position, attrib_velocity, attrib_lifetime, attrib_initial_position, attrib_initial_velocity, attrib_initial_lifetime, attrib_size, attrib_initial_size;
static GLuint uniform_sourcematrix, uniform_dt, uniform_level, uniform_size_increase_factor;
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 uniform_track_x, uniform_track_z, uniform_track_x_len, uniform_track_z_len;
static GLuint quad_vertex_buffer;
GLuint texture, normal_and_depth;
@ -67,6 +69,7 @@ public:
virtual void render();
void setAlphaAdditive(bool);
void setIncreaseFactor(float);
void setHeightmap(const std::vector<std::vector<float> >&, float, float, float, float);
};
class PointEmitter : public GPUParticle

View File

@ -585,6 +585,17 @@ void ParticleEmitter::addHeightMapAffector(Track* t)
HeightMapCollisionAffector* hmca = new HeightMapCollisionAffector(t);
m_node->addAffector(hmca);
hmca->drop();
if (irr_driver->isGLSL()) {
const Vec3* aabb_min;
const Vec3* aabb_max;
t->getAABB(&aabb_min, &aabb_max);
float track_x = aabb_min->getX();
float track_z = aabb_min->getZ();
const float track_x_len = aabb_max->getX() - aabb_min->getX();
const float track_z_len = aabb_max->getZ() - aabb_min->getZ();
static_cast<ParticleSystemProxy *>(m_node)->setHeightmap(t->buildHeightMap(),
track_x, track_z, track_x_len, track_z_len);
}
}
//-----------------------------------------------------------------------------