From 5b8ca4fcd706539e023e635ecd6f4c3cef90405f Mon Sep 17 00:00:00 2001 From: vincentlj Date: Tue, 7 Jan 2014 21:06:06 +0000 Subject: [PATCH] GPUParticles: Implement HeightMapAffector equivalent. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14961 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/shaders/particle.vert | 20 +++++++++++- src/graphics/glwrap.cpp | 2 ++ src/graphics/glwrap.hpp | 1 + src/graphics/gpuparticles.cpp | 54 +++++++++++++++++++++++++++++++ src/graphics/gpuparticles.h | 11 ++++--- src/graphics/particle_emitter.cpp | 11 +++++++ 6 files changed, 94 insertions(+), 5 deletions(-) diff --git a/data/shaders/particle.vert b/data/shaders/particle.vert index 82d0f2e76..02a86f1d6 100644 --- a/data/shaders/particle.vert +++ b/data/shaders/particle.vert @@ -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; } diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index 0408d30c9..7f04e293a 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -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); diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index 016b84e8f..10c65a3e3 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -70,6 +70,7 @@ extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; +extern PFNGLTEXBUFFERPROC glTexBuffer; #endif // core::rect needs these includes diff --git a/src/graphics/gpuparticles.cpp b/src/graphics/gpuparticles.cpp index 1625d7cbb..204f508b2 100644 --- a/src/graphics/gpuparticles.cpp +++ b/src/graphics/gpuparticles.cpp @@ -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 > &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))); diff --git a/src/graphics/gpuparticles.h b/src/graphics/gpuparticles.h index 4f0dac86d..c3123b68c 100644 --- a/src/graphics/gpuparticles.h +++ b/src/graphics/gpuparticles.h @@ -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 >&, float, float, float, float); }; class PointEmitter : public GPUParticle diff --git a/src/graphics/particle_emitter.cpp b/src/graphics/particle_emitter.cpp index bd9a009ab..be8c6710a 100644 --- a/src/graphics/particle_emitter.cpp +++ b/src/graphics/particle_emitter.cpp @@ -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(m_node)->setHeightmap(t->buildHeightMap(), + track_x, track_z, track_x_len, track_z_len); + } } //-----------------------------------------------------------------------------