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
This commit is contained in:
vincentlj 2013-12-27 22:52:44 +00:00
parent 4dd0c066df
commit e72e2de8ca
3 changed files with 149 additions and 159 deletions

View File

@ -171,15 +171,37 @@ 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);
fakemat.Lighting = false;
fakemat.ZWriteEnable = false;
fakemat.MaterialType = irr_driver->getShader(ES_RAIN);
fakemat.Thickness = 200;
fakemat.setTexture(0, tex);
}
void GPUParticle::render() {
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<irr::video::COpenGLDriver*>(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");
@ -192,9 +214,35 @@ GPUParticle::GPUParticle(unsigned c, float *initialSamples, GLuint tex, GLuint r
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;
}
void GPUParticle::simulate() {
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);
@ -215,7 +263,7 @@ void GPUParticle::simulate() {
glDisable(GL_RASTERIZER_DISCARD);
}
void GPUParticle::render() {
void RainNode::draw() {
const float screenw = (float)UserConfigParams::m_width;
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
@ -244,3 +292,8 @@ void GPUParticle::render() {
glActiveTexture(GL_TEXTURE0);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
}
const core::aabbox3d<f32>& RainNode::getBoundingBox() const
{
return box;
}

View File

@ -14,17 +14,35 @@ GLuint getTextureGLuint(irr::video::ITexture *tex);
void bindUniformToTextureUnit(GLuint location, GLuint texid, unsigned textureUnit);
class GPUParticle {
private:
unsigned count;
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);
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<f32> box;
virtual void simulate();
virtual void draw();
public:
GPUParticle(unsigned c, float *initialSamples, GLuint tex, GLuint rtt);
void simulate();
void render();
RainNode(scene::ISceneManager* mgr, ITexture *tex);
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual u32 getMaterialCount() const { return 1; }
};
#endif // GPUPARTICLES_H

View File

@ -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<COpenGLDriver*>(drv)->setRenderStates3DMode();
}
virtual const core::aabbox3d<f32>& 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<f32> box;
u32 count;
s32 area;
};
// The rain manager
Rain::Rain(Camera *camera, irr::scene::ISceneNode* parent)