From e72e2de8caacaf07f230f7b2f3cbca1e5f990a02 Mon Sep 17 00:00:00 2001 From: vincentlj Date: Fri, 27 Dec 2013 22:52:44 +0000 Subject: [PATCH] GPUParticle: Make RainNode a child of GPUParticle git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14817 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/gpuparticles.cpp | 189 ++++++++++++++++++++++------------ src/graphics/gpuparticles.h | 38 +++++-- src/graphics/rain.cpp | 81 --------------- 3 files changed, 149 insertions(+), 159 deletions(-) diff --git a/src/graphics/gpuparticles.cpp b/src/graphics/gpuparticles.cpp index fa65fda77..70ffe833a 100644 --- a/src/graphics/gpuparticles.cpp +++ b/src/graphics/gpuparticles.cpp @@ -171,76 +171,129 @@ void bindUniformToTextureUnit(GLuint location, GLuint texid, unsigned textureUni glUniform1i(location, textureUnit); } -GPUParticle::GPUParticle(unsigned c, float *initialSamples, GLuint tex, GLuint rtt) : - count(c), texture(tex), normal_and_depth(rtt) { +GPUParticle::GPUParticle(scene::ISceneManager* mgr, ITexture *tex) + : scene::ISceneNode(0, mgr, -1) { initGL(); - glGenBuffers(2, tfb_vertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[0]); - glBufferData(GL_ARRAY_BUFFER, 3 * count * sizeof(float), initialSamples, GL_STREAM_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[1]); - glBufferData(GL_ARRAY_BUFFER, 3 * count * sizeof(float), 0, GL_STREAM_DRAW); - - RenderProgram = LoadProgram(file_manager->getAsset("shaders/rain.vert").c_str(), file_manager->getAsset("shaders/rain.frag").c_str()); - loc_screenw = glGetUniformLocation(RenderProgram, "screenw"); - loc_screen = glGetUniformLocation(RenderProgram, "screen"); - loc_invproj = glGetUniformLocation(RenderProgram, "invproj"); - texloc_tex = glGetUniformLocation(RenderProgram, "tex"); - texloc_normal_and_depths = glGetUniformLocation(RenderProgram, "normals_and_depth"); - - const char *varyings[] = {"currentPosition"}; - SimulationProgram = LoadTFBProgram(file_manager->getAsset("shaders/rainsim.vert").c_str(), varyings, 1); - loc_campos = glGetUniformLocation(SimulationProgram, "campos"); - loc_viewm = glGetUniformLocation(SimulationProgram, "viewm"); - loc_time = glGetUniformLocation(SimulationProgram, "time"); + fakemat.Lighting = false; + fakemat.ZWriteEnable = false; + fakemat.MaterialType = irr_driver->getShader(ES_RAIN); + fakemat.Thickness = 200; + fakemat.setTexture(0, tex); } -void GPUParticle::simulate() { - glUseProgram(SimulationProgram); - const float time = irr_driver->getDevice()->getTimer()->getTime() / 90.0f; - const irr::core::matrix4 viewm = irr_driver->getVideoDriver()->getTransform(irr::video::ETS_VIEW); - const irr::core::vector3df campos = irr_driver->getSceneManager()->getActiveCamera()->getPosition(); - - glEnable(GL_RASTERIZER_DISCARD); - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[0]); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_vertex_buffer[1]); - - glUniformMatrix4fv(loc_viewm, 1, GL_FALSE, viewm.pointer()); - glUniform1f(loc_time, time); - glUniform3f(loc_campos, campos.X, campos.Y, campos.Z); - glBeginTransformFeedback(GL_POINTS); - glDrawArrays(GL_POINTS, 0, count); - glEndTransformFeedback(); - glDisable(GL_RASTERIZER_DISCARD); -} - void GPUParticle::render() { - const float screenw = (float)UserConfigParams::m_width; - - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - glEnable(GL_POINT_SPRITE); - glUseProgram(RenderProgram); - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[1]); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); - - float screen[2] = { - (float)UserConfigParams::m_width, - (float)UserConfigParams::m_height - }; - irr::core::matrix4 invproj = irr_driver->getVideoDriver()->getTransform(irr::video::ETS_PROJECTION); - invproj.makeInverse(); - - bindUniformToTextureUnit(texloc_tex, texture, 0); - bindUniformToTextureUnit(texloc_normal_and_depths, normal_and_depth, 1); - - glUniformMatrix4fv(loc_invproj, 1, GL_FALSE, invproj.pointer()); - glUniform2f(loc_screen, screen[0], screen[1]); - glUniform1f(loc_screenw, screenw); - glDrawArrays(GL_POINTS, 0, count); - glDisableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glActiveTexture(GL_TEXTURE0); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); + simulate(); + draw(); + // We need to force irrlicht to update its internal states + irr::video::IVideoDriver * const drv = irr_driver->getVideoDriver(); + drv->setMaterial(fakemat); + static_cast(drv)->setRenderStates3DMode(); } + +void GPUParticle::OnRegisterSceneNode() { + if (IsVisible && + (irr_driver->getRenderPass() & irr::scene::ESNRP_TRANSPARENT) == irr::scene::ESNRP_TRANSPARENT) + { + SceneManager->registerNodeForRendering(this, irr::scene::ESNRP_TRANSPARENT); + } + ISceneNode::OnRegisterSceneNode(); +} + +RainNode::RainNode(scene::ISceneManager* mgr, ITexture *tex) + : GPUParticle(mgr, tex) +{ + RenderProgram = LoadProgram(file_manager->getAsset("shaders/rain.vert").c_str(), file_manager->getAsset("shaders/rain.frag").c_str()); + loc_screenw = glGetUniformLocation(RenderProgram, "screenw"); + loc_screen = glGetUniformLocation(RenderProgram, "screen"); + loc_invproj = glGetUniformLocation(RenderProgram, "invproj"); + texloc_tex = glGetUniformLocation(RenderProgram, "tex"); + texloc_normal_and_depths = glGetUniformLocation(RenderProgram, "normals_and_depth"); + + const char *varyings[] = { "currentPosition" }; + SimulationProgram = LoadTFBProgram(file_manager->getAsset("shaders/rainsim.vert").c_str(), varyings, 1); + loc_campos = glGetUniformLocation(SimulationProgram, "campos"); + loc_viewm = glGetUniformLocation(SimulationProgram, "viewm"); + loc_time = glGetUniformLocation(SimulationProgram, "time"); + count = 2500; + area = 3500; + + u32 i; + float x, y, z, vertices[7500]; + for (i = 0; i < count; i++) + { + x = ((rand() % area) - area / 2) / 100.0f; + y = ((rand() % 2400)) / 100.0f; + z = ((rand() % area) - area / 2) / 100.0f; + + vertices[3 * i] = x; + vertices[3 * i + 1] = y; + vertices[3 * i + 2] = z; + } + + texture = getTextureGLuint(tex); + normal_and_depth = getTextureGLuint(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH)); + glGenBuffers(2, tfb_vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[0]); + glBufferData(GL_ARRAY_BUFFER, 3 * count * sizeof(float), vertices, GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[1]); + glBufferData(GL_ARRAY_BUFFER, 3 * count * sizeof(float), 0, GL_STREAM_DRAW); + + box.addInternalPoint(vector3df((float)(-area / 2))); + box.addInternalPoint(vector3df((float)(area / 2))); +} + +void RainNode::simulate() { + glUseProgram(SimulationProgram); + const float time = irr_driver->getDevice()->getTimer()->getTime() / 90.0f; + const irr::core::matrix4 viewm = irr_driver->getVideoDriver()->getTransform(irr::video::ETS_VIEW); + const irr::core::vector3df campos = irr_driver->getSceneManager()->getActiveCamera()->getPosition(); + + glEnable(GL_RASTERIZER_DISCARD); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[0]); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_vertex_buffer[1]); + + glUniformMatrix4fv(loc_viewm, 1, GL_FALSE, viewm.pointer()); + glUniform1f(loc_time, time); + glUniform3f(loc_campos, campos.X, campos.Y, campos.Z); + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, count); + glEndTransformFeedback(); + glDisable(GL_RASTERIZER_DISCARD); +} + +void RainNode::draw() { + const float screenw = (float)UserConfigParams::m_width; + + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + glEnable(GL_POINT_SPRITE); + glUseProgram(RenderProgram); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, tfb_vertex_buffer[1]); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + + float screen[2] = { + (float)UserConfigParams::m_width, + (float)UserConfigParams::m_height + }; + irr::core::matrix4 invproj = irr_driver->getVideoDriver()->getTransform(irr::video::ETS_PROJECTION); + invproj.makeInverse(); + + bindUniformToTextureUnit(texloc_tex, texture, 0); + bindUniformToTextureUnit(texloc_normal_and_depths, normal_and_depth, 1); + + glUniformMatrix4fv(loc_invproj, 1, GL_FALSE, invproj.pointer()); + glUniform2f(loc_screen, screen[0], screen[1]); + glUniform1f(loc_screenw, screenw); + glDrawArrays(GL_POINTS, 0, count); + glDisableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glActiveTexture(GL_TEXTURE0); + glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); +} + +const core::aabbox3d& RainNode::getBoundingBox() const +{ + return box; +} \ No newline at end of file diff --git a/src/graphics/gpuparticles.h b/src/graphics/gpuparticles.h index ba3892823..e0bf03ddc 100644 --- a/src/graphics/gpuparticles.h +++ b/src/graphics/gpuparticles.h @@ -14,17 +14,35 @@ GLuint getTextureGLuint(irr::video::ITexture *tex); void bindUniformToTextureUnit(GLuint location, GLuint texid, unsigned textureUnit); -class GPUParticle { -private: - unsigned count; - GLuint SimulationProgram, RenderProgram, tfb_vertex_buffer[2]; - GLuint texture, normal_and_depth; - GLuint loc_campos, loc_viewm, loc_time; - GLuint loc_screenw, loc_screen, loc_invproj, texloc_tex, texloc_normal_and_depths; +class GPUParticle : public scene::ISceneNode { +protected: + video::SMaterial fakemat; + virtual void simulate() = 0; + virtual void draw() = 0; public: - GPUParticle(unsigned c, float *initialSamples, GLuint tex, GLuint rtt); - void simulate(); - void render(); + //GPUParticle(unsigned c, float *initialSamples, GLuint tex, GLuint rtt); + GPUParticle(scene::ISceneManager* mgr, ITexture *tex); + virtual void render(); + virtual void OnRegisterSceneNode(); +}; + +class RainNode : public GPUParticle +{ +protected: + GLuint SimulationProgram, RenderProgram, tfb_vertex_buffer[2]; + unsigned count; + GLuint texture, normal_and_depth; + GLuint loc_campos, loc_viewm, loc_time; + GLuint loc_screenw, loc_screen, loc_invproj, texloc_tex, texloc_normal_and_depths; + s32 area; + core::aabbox3d box; + + virtual void simulate(); + virtual void draw(); +public: + RainNode(scene::ISceneManager* mgr, ITexture *tex); + virtual const core::aabbox3d& getBoundingBox() const; + virtual u32 getMaterialCount() const { return 1; } }; #endif // GPUPARTICLES_H \ No newline at end of file diff --git a/src/graphics/rain.cpp b/src/graphics/rain.cpp index 9e8c668f2..b2adc28c9 100644 --- a/src/graphics/rain.cpp +++ b/src/graphics/rain.cpp @@ -38,87 +38,6 @@ using namespace video; using namespace scene; using namespace core; -// The actual rain node -class RainNode: public scene::ISceneNode -{ -private: - GPUParticle *gpupart; -public: - RainNode(scene::ISceneManager* mgr, ITexture *tex) - : scene::ISceneNode(0, mgr, -1) - { - mat.Lighting = false; - mat.ZWriteEnable = false; - mat.MaterialType = irr_driver->getShader(ES_RAIN); - mat.Thickness = 200; - mat.BlendOperation = EBO_ADD; - - mat.setTexture(0, tex); - mat.TextureLayer[0].TextureWrapU = - mat.TextureLayer[0].TextureWrapV = ETC_CLAMP_TO_EDGE; - - count = 2500; - area = 3500; - - u32 i; - float x, y, z, vertices[7500]; - for (i = 0; i < count; i++) - { - x = ((rand() % area) - area/2) / 100.0f; - y = ((rand() % 2400)) / 100.0f; - z = ((rand() % area) - area/2) / 100.0f; - - vertices[3 * i] = x; - vertices[3 * i + 1] = y; - vertices[3 * i + 2] = z; - } - gpupart = new GPUParticle(count, vertices, getTextureGLuint(mat.getTexture(0)), getTextureGLuint(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH))); - - box.addInternalPoint(vector3df((float)(-area/2))); - box.addInternalPoint(vector3df((float)( area/2))); - } - - ~RainNode() - { - delete gpupart; - } - - virtual void render() - { - gpupart->simulate(); - gpupart->render(); - // We need to force irrlicht to update its internal states - IVideoDriver * const drv = irr_driver->getVideoDriver(); - drv->setMaterial(mat); - static_cast(drv)->setRenderStates3DMode(); - } - - virtual const core::aabbox3d& getBoundingBox() const - { - return box; - } - - virtual void OnRegisterSceneNode() - { - if (IsVisible && - (irr_driver->getRenderPass() & ESNRP_TRANSPARENT) == ESNRP_TRANSPARENT) - { - SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); - } - - ISceneNode::OnRegisterSceneNode(); - } - - virtual u32 getMaterialCount() const { return 1; } - virtual video::SMaterial& getMaterial(u32 i) { return mat; } - -private: - video::SMaterial mat; - core::aabbox3d box; - u32 count; - s32 area; -}; - // The rain manager Rain::Rain(Camera *camera, irr::scene::ISceneNode* parent)