Started refactoring of shaders to follow our coding style.

One transform feedback buffer shader in particles is done.
This commit is contained in:
hiker 2015-04-23 16:44:26 +10:00
parent 959c86d816
commit 262fc0c373
8 changed files with 578 additions and 95 deletions

View File

@ -17,6 +17,7 @@
#include "graphics/irr_driver.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/shaders_util.hpp"
#include "gpuparticles.hpp"
#include "io/file_manager.hpp"
#include "config/user_config.hpp"
@ -386,15 +387,15 @@ void ParticleSystemProxy::simulate()
glEnable(GL_RASTERIZER_DISCARD);
if (has_height_map)
{
glUseProgram(ParticleShader::HeightmapSimulationShader::getInstance()->Program);
glActiveTexture(GL_TEXTURE0 + ParticleShader::HeightmapSimulationShader::getInstance()->TU_heightmap);
glUseProgram(HeightmapSimulationShader::getInstance()->Program);
glActiveTexture(GL_TEXTURE0 + HeightmapSimulationShader::getInstance()->TU_heightmap);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
ParticleShader::HeightmapSimulationShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor, track_x, track_x_len, track_z, track_z_len);
HeightmapSimulationShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor, track_x, track_x_len, track_z, track_z_len);
}
else
{
glUseProgram(ParticleShader::SimpleSimulationShader::getInstance()->Program);
ParticleShader::SimpleSimulationShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor);
PointEmitterShader::getInstance()->use();
PointEmitterShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor);
}
glBindVertexArray(current_simulation_vao);
@ -432,10 +433,10 @@ void ParticleSystemProxy::simulate()
void ParticleSystemProxy::drawFlip()
{
glBlendFunc(GL_ONE, GL_ONE);
glUseProgram(ParticleShader::FlipParticleRender::getInstance()->Program);
glUseProgram(FlipParticleRender::getInstance()->Program);
ParticleShader::FlipParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
ParticleShader::FlipParticleRender::getInstance()->setUniforms();
FlipParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
FlipParticleRender::getInstance()->setUniforms();
glBindVertexArray(current_rendering_vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_count);
@ -447,13 +448,13 @@ void ParticleSystemProxy::drawNotFlip()
glBlendFunc(GL_ONE, GL_ONE);
else
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(ParticleShader::SimpleParticleRender::getInstance()->Program);
glUseProgram(SimpleParticleRender::getInstance()->Program);
ParticleShader::SimpleParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
SimpleParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
video::SColorf ColorFrom = video::SColorf(getColorFrom()[0], getColorFrom()[1], getColorFrom()[2]);
video::SColorf ColorTo = video::SColorf(getColorTo()[0], getColorTo()[1], getColorTo()[2]);
ParticleShader::SimpleParticleRender::getInstance()->setUniforms(ColorFrom, ColorTo);
SimpleParticleRender::getInstance()->setUniforms(ColorFrom, ColorTo);
glBindVertexArray(current_rendering_vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_count);
@ -534,3 +535,97 @@ void ParticleSystemProxy::render() {
simulate();
draw();
}
// ============================================================================
PointEmitterShader::PointEmitterShader()
{
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
loadTFBProgram("pointemitter.vert", varyings, 4);
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor");
}
struct TexUnit
{
GLuint m_index;
const char* m_uniform;
TexUnit(GLuint index, const char* uniform)
{
m_index = index;
m_uniform = uniform;
}
};
static void
AssignTextureUnit(GLuint Program, TexUnit texUnit)
{
glUseProgram(Program);
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
glUniform1i(uniform, texUnit.m_index);
glUseProgram(0);
}
template<typename... T>
static void AssignTextureUnit(GLuint Program, TexUnit texUnit, T... rest)
{
glUseProgram(Program);
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
glUniform1i(uniform, texUnit.m_index);
AssignTextureUnit_Sub(Program, rest...);
glUseProgram(0);
}
static void AssignTextureUnit_Sub(GLuint Program) {}
template<typename... T>
static void AssignTextureUnit_Sub(GLuint Program, TexUnit texUnit, T... rest)
{
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
glUniform1i(uniform, texUnit.m_index);
AssignTextureUnit_Sub(Program, rest...);
}
HeightmapSimulationShader::HeightmapSimulationShader()
{
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
Program = LoadTFBProgram(file_manager->getAsset("shaders/particlesimheightmap.vert").c_str(), varyings, 4);
TU_heightmap = 2;
AssignTextureUnit(Program, TexUnit(TU_heightmap, "heightmap"));
AssignUniforms("sourcematrix", "dt", "level", "size_increase_factor", "track_x", "track_x_len", "track_z", "track_z_len");
}
SimpleParticleRender::SimpleParticleRender()
{
Program = LoadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/particle.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
AssignUniforms("color_from", "color_to");
AssignSamplerNames(Program, 0, "tex", 1, "dtex");
}
FlipParticleRender::FlipParticleRender()
{
Program = LoadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/flipparticle.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex", 1, "dtex");
}

View File

@ -15,13 +15,45 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef GPUPARTICLES_H
#define GPUPARTICLES_H
#ifndef HEADER_GPU_PARTICLES_HPP
#define HEADER_GPU_PARTICLES_HPP
#include "graphics/shader.hpp"
#include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
#include <ISceneManager.h>
#include <IParticleSystemSceneNode.h>
class PointEmitterShader : public Shader
< PointEmitterShader, core::matrix4, int, int, float >
{
public:
PointEmitterShader();
};
class HeightmapSimulationShader : public ShaderHelperSingleton<HeightmapSimulationShader, core::matrix4, int, int, float, float, float, float, float>
{
public:
GLuint TU_heightmap;
HeightmapSimulationShader();
};
class SimpleParticleRender : public ShaderHelperSingleton<SimpleParticleRender, video::SColorf, video::SColorf>, public TextureRead<Trilinear_Anisotropic_Filtered, Nearest_Filtered>
{
public:
SimpleParticleRender();
};
class FlipParticleRender : public ShaderHelperSingleton<FlipParticleRender>, public TextureRead<Trilinear_Anisotropic_Filtered, Nearest_Filtered>
{
public:
FlipParticleRender();
};
namespace irr { namespace video{ class ITexture; } }
class ParticleSystemProxy : public scene::CParticleSystemSceneNode

200
src/graphics/shader.cpp Normal file
View File

@ -0,0 +1,200 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014-2015 SuperTuxKart-Team
// (C) 2015 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/shader.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/gl_headers.hpp"
#include "io/file_manager.hpp"
#include "utils/log.hpp"
#include <fstream>
#include <sstream>
#include <stdio.h>
std::string ShaderBase::m_shader_header = "";
std::vector<ShaderBase *> ShaderBase::m_all_shaders;
// ----------------------------------------------------------------------------
/** Returns a string with the content of header.txt (which contains basic
* shader defines).
*/
const std::string& ShaderBase::getHeader()
{
// Only read file first time
if (m_shader_header.empty())
{
std::ifstream stream(file_manager->getShader("header.txt"), std::ios::in);
if (stream.is_open())
{
std::string line = "";
while (getline(stream, line))
m_shader_header += "\n" + line;
stream.close();
}
} // if m_shader_header.empty()
return m_shader_header;
} // getHeader
// ----------------------------------------------------------------------------
/** Loads a single shader.
* \param file Filename of the shader to load.
* \param type Type of the shader.
*/
GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
{
GLuint id = glCreateShader(type);
std::ostringstream code;
code << "#version " << CVS->getGLSLVersion()<<"\n";
if (CVS->isAMDVertexShaderLayerUsable())
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
if (CVS->isAZDOEnabled())
{
code << "#extension GL_ARB_bindless_texture : enable\n";
code << "#define Use_Bindless_Texture\n";
}
code << "//" + std::string(file) + "\n";
if (!CVS->isARBUniformBufferObjectUsable())
code << "#define UBO_DISABLED\n";
if (CVS->isAMDVertexShaderLayerUsable())
code << "#define VSLayer\n";
if (CVS->needsRGBBindlessWorkaround())
code << "#define SRGBBindlessFix\n";
code << getHeader();
std::ifstream stream(file, std::ios::in);
if (stream.is_open())
{
std::string Line = "";
while (getline(stream, Line))
code << "\n" + Line;
stream.close();
}
else
Log::error("shader", "Can not open '%s'.", file.c_str());
Log::info("shader", "Compiling shader : %s", file);
const std::string &source = code.str();
char const *source_pointer = source.c_str();
int len = source.size();
glShaderSource(id, 1, &source_pointer, &len);
glCompileShader(id);
GLint result = GL_FALSE;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
int info_length;
Log::error("GLWrap", "Error in shader %s", file);
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length);
if (info_length<0)
info_length = 1024;
char *error_message = new char[info_length];
error_message[0] = 0;
glGetShaderInfoLog(id, info_length, NULL, error_message);
Log::error("GLWrap", error_message);
delete[] error_message;
}
glGetError();
return id;
} // loadShader
// ----------------------------------------------------------------------------
/** Loads a transform feedback buffer shader with a given number of varying
* parameters.
*/
int ShaderBase::loadTFBProgram(const std::string &shader_name,
const char **varyings,
unsigned varying_count)
{
std::string full_path = file_manager->getShader(shader_name);
m_program = glCreateProgram();
loadAndAttachShader(GL_VERTEX_SHADER, full_path);
if (CVS->getGLSLVersion() < 330)
setAttribute(PARTICLES_SIM);
glTransformFeedbackVaryings(m_program, varying_count, varyings,
GL_INTERLEAVED_ATTRIBS);
glLinkProgram(m_program);
GLint result = GL_FALSE;
glGetProgramiv(m_program, GL_LINK_STATUS, &result);
if (result == GL_FALSE)
{
int info_log_length;
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &info_log_length);
char *error_message = new char[info_log_length];
glGetProgramInfoLog(m_program, info_log_length, NULL, error_message);
Log::error("GLWrap", error_message);
delete[] error_message;
}
glGetError();
return m_program;
} // loadTFBProgram
// ----------------------------------------------------------------------------
ShaderBase::ShaderBase()
{
m_all_shaders.push_back(this);
} // ShaderBase
// ----------------------------------------------------------------------------
void ShaderBase::setAttribute(AttributeType type)
{
switch (type)
{
case OBJECT:
glBindAttribLocation(m_program, 0, "Position");
glBindAttribLocation(m_program, 1, "Normal");
glBindAttribLocation(m_program, 2, "Color");
glBindAttribLocation(m_program, 3, "Texcoord");
glBindAttribLocation(m_program, 4, "SecondTexcoord");
glBindAttribLocation(m_program, 5, "Tangent");
glBindAttribLocation(m_program, 6, "Bitangent");
glBindAttribLocation(m_program, 7, "Origin");
glBindAttribLocation(m_program, 8, "Orientation");
glBindAttribLocation(m_program, 9, "Scale");
break;
case PARTICLES_SIM:
glBindAttribLocation(m_program, 0, "particle_position");
glBindAttribLocation(m_program, 1, "lifetime");
glBindAttribLocation(m_program, 2, "particle_velocity");
glBindAttribLocation(m_program, 3, "size");
glBindAttribLocation(m_program, 4, "particle_position_initial");
glBindAttribLocation(m_program, 5, "lifetime_initial");
glBindAttribLocation(m_program, 6, "particle_velocity_initial");
glBindAttribLocation(m_program, 7, "size_initial");
break;
case PARTICLES_RENDERING:
glBindAttribLocation(m_program, 1, "lifetime");
glBindAttribLocation(m_program, 2, "size");
glBindAttribLocation(m_program, 4, "quadcorner");
glBindAttribLocation(m_program, 5, "rotationvec");
glBindAttribLocation(m_program, 6, "anglespeed");
break;
}
} // setAttribute
// ============================================================================

228
src/graphics/shader.hpp Normal file
View File

@ -0,0 +1,228 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014-2015 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_SHADER_HPP
#define HEADER_SHADER_HPP
#include "graphics/gl_headers.hpp"
#include "utils/singleton.hpp"
#include <matrix4.h>
#include <SColor.h>
#include <vector3d.h>
#include <string>
#include <vector>
class ShaderBase
{
private:
// Static members
/** Stores the context of header.txt, to avoid reading
* this file repeatedly. */
static std::string m_shader_header;
/** Maintains a list of all shaders. */
static std::vector<ShaderBase *> m_all_shaders;
enum AttributeType
{
OBJECT,
PARTICLES_SIM,
PARTICLES_RENDERING,
};
protected:
/** OpenGL's program id. */
GLuint m_program;
private:
// ------------------------------------------------------------------------
// Ends vararg template
template<typename ... Types>
void loadAndAttachShader(GLint ProgramID)
{
return;
} // loadAndAttachShader
// ------------------------------------------------------------------------
template<typename ... Types>
void loadAndAttachShader(GLint shader_type, const std::string &name,
Types ... args)
{
GLint shader_id = loadShader(name, shader_type);
glAttachShader(m_program, shader_id);
glDeleteShader(shader_id);
loadAndAttachShader(shader_type, args...);
} // loadAndAttachShader
const std::string& getHeader();
GLuint loadShader(const std::string &file, unsigned type);
void setAttribute(AttributeType type);
public:
ShaderBase();
int loadTFBProgram(const std::string &vertex_file_path,
const char **varyings,
unsigned varyingscount);
// ------------------------------------------------------------------------
/** Activates the shader calling glUseProgram. */
void use() { glUseProgram(m_program); }
}; // ShaderBase
// ============================================================================
template<typename T, typename... Args>
class Shader : public ShaderBase, public Singleton<T>
{
private:
std::vector<GLuint> m_uniforms;
/** Finds the specified uniform block and assigns a binding point to it. */
void bindPoint(const char *name, int index)
{
GLuint block_index = glGetUniformBlockIndex(m_program, name);
if (block_index != GL_INVALID_INDEX)
glUniformBlockBinding(m_program, block_index, index);
} // bindPoint
// ------------------------------------------------------------------------
/** End of recursive implementation of assignUniforms. */
void assignUniformsImpl()
{
bindPoint("MatrixData", 0);
bindPoint("LightingData", 1);
} // assignUniformsImpl
// ------------------------------------------------------------------------
/** Recursive implementation of assignniforms. It collects the unfirom
* locations in m_uniform, then recursing.
* \param name Name of the uniform.
*/
template<typename... U>
void assignUniformsImpl(const char* name, U... rest)
{
m_uniforms.push_back(glGetUniformLocation(m_program, name));
assignUniformsImpl(rest...);
} // assignUniformsImpl
// ------------------------------------------------------------------------
/** End of recursion for setUniforms implementation.
*/
template<unsigned N = 0>
void setUniformsImpl() const
{
} // setUniformImpl
// ------------------------------------------------------------------------
/** Implementation for setUniforms for a matrix uniform. */
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const irr::core::matrix4 &mat, Args... arg) const
{
glUniformMatrix4fv(m_uniforms[N], 1, GL_FALSE, mat.pointer());
setUniformsImpl<N + 1>(arg...);
} // setUniformImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const irr::video::SColorf &col, Args... arg) const
{
glUniform3f(m_uniforms[N], col.r, col.g, col.b);
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const irr::video::SColor &col, Args... arg) const
{
glUniform4i(m_uniforms[N], col.getRed(), c ol.getGreen(),
col.getBlue(), col.getAlpha());
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const irr::core::vector3df &v, Args... arg) const
{
glUniform3f(m_uniforms[N], v.X, v.Y, v.Z);
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const irr::core::vector2df &v, Args... arg) const
{
glUniform2f(m_uniforms[N], v.X, v.Y);
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const irr::core::dimension2df &v, Args... arg) const
{
glUniform2f(m_uniforms[N], v.Width, v.Height);
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(float f, Args... arg) const
{
glUniform1f(m_uniforms[N], f);
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(int f, Args... arg) const
{
glUniform1i(m_uniforms[N], f);
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
// ------------------------------------------------------------------------
template<unsigned N = 0, typename... Args>
void setUniformsImpl(const std::vector<float> &v, Args... arg) const
{
glUniform1fv(m_uniforms[N], (int)v.size(), v.data());
setUniformsImpl<N + 1>(arg...);
} // setUniformsImpl
public:
// ------------------------------------------------------------------------
/** This variadic template collects all names of uniforms in
* a std::vector. */
template<typename... U>
void assignUniforms(U... rest)
{
static_assert(sizeof...(rest) == sizeof...(Args),
"Count of Uniform's name mismatch");
assignUniformsImpl(rest...);
} // assignUniforms
// ------------------------------------------------------------------------
void setUniforms(const Args & ... args) const
{
if (needsUBO())
bypassUBO(m_program);
setUniformsImpl(args...);
}
}; // Shader
// ============================================================================
#endif

View File

@ -1491,56 +1491,6 @@ namespace LightShader
}
namespace ParticleShader
{
SimpleSimulationShader::SimpleSimulationShader()
{
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
Program = LoadTFBProgram(file_manager->getAsset("shaders/pointemitter.vert").c_str(), varyings, 4);
AssignUniforms("sourcematrix", "dt", "level", "size_increase_factor");
}
HeightmapSimulationShader::HeightmapSimulationShader()
{
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
Program = LoadTFBProgram(file_manager->getAsset("shaders/particlesimheightmap.vert").c_str(), varyings, 4);
TU_heightmap = 2;
AssignTextureUnit(Program, TexUnit(TU_heightmap, "heightmap"));
AssignUniforms("sourcematrix", "dt", "level", "size_increase_factor", "track_x", "track_x_len", "track_z", "track_z_len");
}
SimpleParticleRender::SimpleParticleRender()
{
Program = LoadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/particle.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
AssignUniforms("color_from", "color_to");
AssignSamplerNames(Program, 0, "tex", 1, "dtex");
}
FlipParticleRender::FlipParticleRender()
{
Program = LoadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/flipparticle.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex", 1, "dtex");
}
}
static GLuint createVAO(GLuint Program)
{

View File

@ -339,37 +339,6 @@ namespace LightShader
};
}
namespace ParticleShader
{
class SimpleSimulationShader : public ShaderHelperSingleton<SimpleSimulationShader, core::matrix4, int, int, float>
{
public:
SimpleSimulationShader();
};
class HeightmapSimulationShader : public ShaderHelperSingleton<HeightmapSimulationShader, core::matrix4, int, int, float, float, float, float, float>
{
public:
GLuint TU_heightmap;
HeightmapSimulationShader();
};
class SimpleParticleRender : public ShaderHelperSingleton<SimpleParticleRender, video::SColorf, video::SColorf>, public TextureRead<Trilinear_Anisotropic_Filtered, Nearest_Filtered>
{
public:
SimpleParticleRender();
};
class FlipParticleRender : public ShaderHelperSingleton<FlipParticleRender>, public TextureRead<Trilinear_Anisotropic_Filtered, Nearest_Filtered>
{
public:
FlipParticleRender();
};
}
template<typename T, typename... Args>
static void DrawFullScreenEffect(Args...args)

View File

@ -158,7 +158,16 @@ public:
{
m_music_search_path.push_back(path);
} // pushMusicSearchPath
// ------------------------------------------------------------------------
/** Returns the full path to a shader (this function could be modified
* later to allow track-specific shaders).
* \param name Name of the shader.
*/
std::string getShader(const std::string &name) const
{
return getAsset(SHADER, name);
} // getShader
}; // FileManager
extern FileManager* file_manager;