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:
parent
4dd0c066df
commit
e72e2de8ca
@ -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<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");
|
||||
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<f32>& RainNode::getBoundingBox() const
|
||||
{
|
||||
return box;
|
||||
}
|
@ -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<f32> box;
|
||||
|
||||
virtual void simulate();
|
||||
virtual void draw();
|
||||
public:
|
||||
RainNode(scene::ISceneManager* mgr, ITexture *tex);
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
virtual u32 getMaterialCount() const { return 1; }
|
||||
};
|
||||
|
||||
#endif // GPUPARTICLES_H
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user