2014-12-07 19:10:22 +01:00

2084 lines
82 KiB
C++

// SuperTuxKart - a fun racing game with go-kart
//
// 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.
/**
\page shaders_overview Shaders Overview
\section shader_declaration Shader declaration
You need to create a class for each shader in shaders.cpp
This class should inherit from the template ShaderHelper<>.
The template first parameter is the shader class being declared and the following ones are the types
of every uniform (except samplers) required by the shaders.
The template inheritance will provide the shader with a setUniforms() variadic function which calls
the glUniform*() that pass uniforms value to the shader according to the type given as parameter
to the template.
The class constructor is used to
\li \ref shader_declaration_compile
\li \ref shader_declaration_uniform_names
\li \ref shader_declaration_bind_texture_unit
Of course it's possible to use the constructor to declare others things if needed.
\subsection shader_declaration_compile Compile the shader
The LoadProgram() function is provided to ease shader compilation and link.
It takes a flat sequence of SHADER_TYPE, filename pairs that will be linked together.
This way you can add any shader stage you want (geometry, domain/hull shader)
It is highly recommended to use explicit attribute location for a program input.
However as not all hardware support this extension, default location are provided for
input whose name is either Position (location 0) or Normal (location 1) or
Texcoord (location 3) or Color (location 2) or SecondTexcoord (location 4).
You can use these predefined name and location in your vao for shader
that needs GL pre 3.3 support.
\subsection shader_declaration_uniform_names Declare uniforms
Use the AssignUniforms() function to pass name of the uniforms in the program.
The order of name declaration is the same as the argument passed to setUniforms function.
\subsection shader_declaration_bind_texture_unit Bind texture unit and name
Texture are optional but if you have one, you must give them determined texture unit (up to 32).
You can do this using the AssignTextureUnit function that takes pair of texture unit and sampler name
as argument.
\section shader_usage
Shader's class are singleton that can be retrieved using ShaderClassName::getInstance() which automatically
creates an instance the first time it is called.
As the program id of a shader instance is public it can be used to bind a program :
\code
glUseProgram(MyShaderClass::getInstance()->Program);
\endcode
To set uniforms use the automatically generated function setUniforms:
\code
MyShaderClass::getInstance()->setUniforms(Args...)
\endcode
A Vertex Array must be bound (VAO creation process is currently left to the reader) :
\code
glBindVertexAttrib(vao);
\endcode
To actually perform the rendering you also need to call a glDraw* function (left to the reader as well) :
\code
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT);
\endcode
*/
#define SHADER_NAMES
#include "graphics/callbacks.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/gpuparticles.hpp"
#include "graphics/shaders.hpp"
#include "io/file_manager.hpp"
#include "utils/log.hpp"
#include "graphics/glwrap.hpp"
#include <assert.h>
#include <IGPUProgrammingServices.h>
using namespace video;
std::vector<void(*)()> CleanTable;
Shaders::Shaders()
{
// Callbacks
memset(m_callbacks, 0, sizeof(m_callbacks));
m_callbacks[ES_WATER] = new WaterShaderProvider();
m_callbacks[ES_GRASS] = new GrassShaderProvider();
m_callbacks[ES_MOTIONBLUR] = new MotionBlurProvider();
m_callbacks[ES_MIPVIZ] = new MipVizProvider();
m_callbacks[ES_DISPLACE] = new DisplaceProvider();
for (s32 i = 0; i < ES_COUNT; i++)
m_shaders[i] = -1;
loadShaders();
}
// Shader loading related hook
static std::string LoadHeader()
{
std::string result;
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
result += "\n" + Line;
Stream.close();
}
return result;
}
// Mostly from shader tutorial
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
if (UserConfigParams::m_azdo)
Code += "#extension GL_ARB_bindless_texture : enable\n";
else
{
Code += "#extension GL_ARB_bindless_texture : disable\n";
Code += "#undef GL_ARB_bindless_texture\n";
}
std::ifstream Stream(file, std::ios::in);
Code += "//" + std::string(file) + "\n";
if (irr_driver->needUBOWorkaround())
Code += "#define UBO_DISABLED\n";
if (irr_driver->hasVSLayerExtension())
Code += "#define VSLayer\n";
if (irr_driver->needsRGBBindlessWorkaround())
Code += "#define SRGBBindlessFix\n";
Code += LoadHeader();
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
Code += "\n" + Line;
Stream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
Log::info("GLWrap", "Compiling shader : %s", file);
char const * SourcePointer = Code.c_str();
int length = (int)strlen(SourcePointer);
glShaderSource(Id, 1, &SourcePointer, &length);
glCompileShader(Id);
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE)
{
Log::error("GLWrap", "Error in shader %s", file);
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength<0)
InfoLogLength = 1024;
char *ErrorMessage = new char[InfoLogLength];
ErrorMessage[0] = 0;
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Id;
}
void setAttribute(AttributeType Tp, GLuint ProgramID)
{
switch (Tp)
{
case OBJECT:
glBindAttribLocation(ProgramID, 0, "Position");
glBindAttribLocation(ProgramID, 1, "Normal");
glBindAttribLocation(ProgramID, 2, "Color");
glBindAttribLocation(ProgramID, 3, "Texcoord");
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
glBindAttribLocation(ProgramID, 5, "Tangent");
glBindAttribLocation(ProgramID, 6, "Bitangent");
glBindAttribLocation(ProgramID, 7, "Origin");
glBindAttribLocation(ProgramID, 8, "Orientation");
glBindAttribLocation(ProgramID, 9, "Scale");
break;
case PARTICLES_SIM:
glBindAttribLocation(ProgramID, 0, "particle_position");
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "particle_velocity");
glBindAttribLocation(ProgramID, 3, "size");
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
glBindAttribLocation(ProgramID, 7, "size_initial");
break;
case PARTICLES_RENDERING:
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "size");
glBindAttribLocation(ProgramID, 4, "quadcorner");
glBindAttribLocation(ProgramID, 5, "rotationvec");
glBindAttribLocation(ProgramID, 6, "anglespeed");
break;
}
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Program = glCreateProgram();
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(PARTICLES_SIM, Program);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE)
{
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Program;
}
GLuint quad_vbo, tri_vbo;
GLuint SharedObject::FullScreenQuadVAO = 0;
GLuint SharedObject::UIVAO = 0;
static void initQuadVBO()
{
const float quad_vertex[] = {
-1., -1., 0., 0., // UpperLeft
-1., 1., 0., 1., // LowerLeft
1., -1., 1., 0., // UpperRight
1., 1., 1., 1., // LowerRight
};
glGenBuffers(1, &quad_vbo);
glBindBuffer(GL_ARRAY_BUFFER, quad_vbo);
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad_vertex, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
const float tri_vertex[] = {
-1., -1.,
-1., 3.,
3., -1.,
};
glGenBuffers(1, &tri_vbo);
glBindBuffer(GL_ARRAY_BUFFER, tri_vbo);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), tri_vertex, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &SharedObject::FullScreenQuadVAO);
glBindVertexArray(SharedObject::FullScreenQuadVAO);
glBindBuffer(GL_ARRAY_BUFFER, tri_vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
glBindVertexArray(0);
}
// It should be possible to merge it with previous one...
GLuint quad_buffer;
static void initQuadBuffer()
{
const float quad_vertex[] = {
-1., -1., -1., 1., // UpperLeft
-1., 1., -1., -1., // LowerLeft
1., -1., 1., 1., // UpperRight
1., 1., 1., -1., // LowerRight
};
glGenBuffers(1, &quad_buffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_buffer);
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad_vertex, GL_STATIC_DRAW);
glGenVertexArrays(1, &SharedObject::UIVAO);
glBindVertexArray(SharedObject::UIVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, quad_buffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float)));
glBindVertexArray(0);
}
GLuint SharedObject::billboardvbo = 0;
static void initBillboardVBO()
{
float quad[] = {
-.5, -.5, 0., 1.,
-.5, .5, 0., 0.,
.5, -.5, 1., 1.,
.5, .5, 1., 0.,
};
glGenBuffers(1, &(SharedObject::billboardvbo));
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::billboardvbo);
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad, GL_STATIC_DRAW);
}
GLuint SharedObject::cubevbo = 0;
GLuint SharedObject::cubeindexes = 0;
static void initCubeVBO()
{
// From CSkyBoxSceneNode
float corners[] =
{
// top side
1., 1., -1.,
1., 1., 1.,
-1., 1., 1.,
-1., 1., -1.,
// Bottom side
1., -1., 1.,
1., -1., -1.,
-1., -1., -1.,
-1., -1., 1.,
// right side
1., -1, -1,
1., -1, 1,
1., 1., 1.,
1., 1., -1.,
// left side
-1., -1., 1.,
-1., -1., -1.,
-1., 1., -1.,
-1., 1., 1.,
// back side
-1., -1., -1.,
1., -1, -1.,
1, 1, -1.,
-1, 1, -1.,
// front side
1., -1., 1.,
-1., -1., 1.,
-1, 1., 1.,
1., 1., 1.,
};
int indices[] = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenBuffers(1, &SharedObject::cubevbo);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof(float), corners, GL_STATIC_DRAW);
glGenBuffers(1, &SharedObject::cubeindexes);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
}
GLuint SharedObject::frustrumvbo = 0;
GLuint SharedObject::frustrumindexes = 0;
static void initFrustrumVBO()
{
glGenBuffers(1, &SharedObject::frustrumvbo);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::frustrumvbo);
glBufferData(GL_ARRAY_BUFFER, 8 * 3 * sizeof(float), 0, GL_DYNAMIC_DRAW);
int indices[24] = {
0, 1, 1, 3, 3, 2, 2, 0,
4, 5, 5, 7, 7, 6, 6, 4,
0, 4, 1, 5, 2, 6, 3, 7,
};
glGenBuffers(1, &SharedObject::frustrumindexes);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::frustrumindexes);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 12 * 2 * sizeof(int), indices, GL_STATIC_DRAW);
}
GLuint SharedObject::ViewProjectionMatrixesUBO;
static void initShadowVPMUBO()
{
glGenBuffers(1, &SharedObject::ViewProjectionMatrixesUBO);
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
glBufferData(GL_UNIFORM_BUFFER, (16 * 9 + 2) * sizeof(float), 0, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
GLuint SharedObject::ParticleQuadVBO = 0;
static void initParticleQuadVBO()
{
static const GLfloat quad_vertex[] = {
-.5, -.5, 0., 0.,
.5, -.5, 1., 0.,
-.5, .5, 0., 1.,
.5, .5, 1., 1.,
};
glGenBuffers(1, &SharedObject::ParticleQuadVBO);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::ParticleQuadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertex), quad_vertex, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Shaders::loadShaders()
{
const std::string &dir = file_manager->getAsset(FileManager::SHADER, "");
IGPUProgrammingServices * const gpu = irr_driver->getVideoDriver()->getGPUProgrammingServices();
#define glsl(a, b, c) gpu->addHighLevelShaderMaterialFromFiles((a).c_str(), (b).c_str(), (IShaderConstantSetCallBack*) c)
#define glslmat(a, b, c, d) gpu->addHighLevelShaderMaterialFromFiles((a).c_str(), (b).c_str(), (IShaderConstantSetCallBack*) c, d)
#define glsl_noinput(a, b) gpu->addHighLevelShaderMaterialFromFiles((a).c_str(), (b).c_str(), (IShaderConstantSetCallBack*) 0)
// Save previous shaders (used in case some shaders don't compile)
int saved_shaders[ES_COUNT];
memcpy(saved_shaders, m_shaders, sizeof(m_shaders));
// Ok, go
m_shaders[ES_NORMAL_MAP] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_NORMAL_MAP_LIGHTMAP] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_SKYBOX] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_SKYBOX], EMT_TRANSPARENT_ALPHA_CHANNEL);
m_shaders[ES_SPLATTING] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_WATER] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_WATER], EMT_TRANSPARENT_ALPHA_CHANNEL);
m_shaders[ES_WATER_SURFACE] = glsl(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_WATER]);
m_shaders[ES_SPHERE_MAP] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_GRASS] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_GRASS], EMT_TRANSPARENT_ALPHA_CHANNEL);
m_shaders[ES_GRASS_REF] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_GRASS], EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
m_shaders[ES_MOTIONBLUR] = glsl(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_MOTIONBLUR]);
m_shaders[ES_GAUSSIAN3H] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_GAUSSIAN3H], EMT_SOLID);
m_shaders[ES_GAUSSIAN3V] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_GAUSSIAN3V], EMT_SOLID);
m_shaders[ES_MIPVIZ] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_MIPVIZ], EMT_SOLID);
m_shaders[ES_OBJECTPASS] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_OBJECT_UNLIT] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_OBJECTPASS_REF] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_OBJECTPASS_RIMLIT] = glsl_noinput(dir + "pass.vert", dir + "pass.frag");
m_shaders[ES_DISPLACE] = glslmat(dir + "pass.vert", dir + "pass.frag",
m_callbacks[ES_DISPLACE], EMT_TRANSPARENT_ALPHA_CHANNEL);
// Check that all successfully loaded
for (s32 i = 0; i < ES_COUNT; i++) {
// Old Intel Windows drivers fail here.
// It's an artist option, so not necessary to play.
if (i == ES_MIPVIZ)
continue;
check(i);
}
#undef glsl
#undef glslmat
#undef glsl_noinput
// In case we're reloading and a shader didn't compile: keep the previous, working one
for (s32 i = 0; i < ES_COUNT; i++)
{
if (m_shaders[i] == -1)
m_shaders[i] = saved_shaders[i];
}
initGL();
CleanTable.clear();
initQuadVBO();
initQuadBuffer();
initBillboardVBO();
initCubeVBO();
initFrustrumVBO();
initShadowVPMUBO();
initParticleQuadVBO();
MeshShader::ViewFrustrumShader::init();
UtilShader::ColoredLine::init();
}
void Shaders::killShaders()
{
for (unsigned i = 0; i < CleanTable.size(); i++)
CleanTable[i]();
}
Shaders::~Shaders()
{
u32 i;
for (i = 0; i < ES_COUNT; i++)
{
if (i == ES_GAUSSIAN3V || !m_callbacks[i]) continue;
delete m_callbacks[i];
}
}
E_MATERIAL_TYPE Shaders::getShader(const ShaderType num) const
{
assert(num < ES_COUNT);
return (E_MATERIAL_TYPE)m_shaders[num];
}
void Shaders::check(const int num) const
{
if (m_shaders[num] == -1)
{
Log::error("shaders", "Shader %s failed to load. Update your drivers, if the issue "
"persists, report a bug to us.", shader_names[num] + 3);
}
}
void bypassUBO(GLuint Program)
{
GLint VM = glGetUniformLocation(Program, "ViewMatrix");
glUniformMatrix4fv(VM, 1, GL_FALSE, irr_driver->getViewMatrix().pointer());
GLint PM = glGetUniformLocation(Program, "ProjectionMatrix");
glUniformMatrix4fv(PM, 1, GL_FALSE, irr_driver->getProjMatrix().pointer());
GLint IVM = glGetUniformLocation(Program, "InverseViewMatrix");
glUniformMatrix4fv(IVM, 1, GL_FALSE, irr_driver->getInvViewMatrix().pointer());
GLint IPM = glGetUniformLocation(Program, "InverseProjectionMatrix");
glUniformMatrix4fv(IPM, 1, GL_FALSE, irr_driver->getInvProjMatrix().pointer());
GLint Screen = glGetUniformLocation(Program, "screen");
glUniform2f(Screen, irr_driver->getCurrentScreenSize().X, irr_driver->getCurrentScreenSize().Y);
}
namespace UtilShader
{
GLuint ColoredLine::Program;
GLuint ColoredLine::uniform_color;
GLuint ColoredLine::vao;
GLuint ColoredLine::vbo;
void ColoredLine::init()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str());
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 6 * 1024 * sizeof(float), 0, GL_DYNAMIC_DRAW);
GLuint attrib_position = glGetAttribLocation(Program, "Position");
glEnableVertexAttribArray(attrib_position);
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
uniform_color = glGetUniformLocation(Program, "color");
}
void ColoredLine::setUniforms(const irr::video::SColor &col)
{
if (irr_driver->needUBOWorkaround())
bypassUBO(Program);
glUniform4i(uniform_color, col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha());
glUniformMatrix4fv(glGetUniformLocation(Program, "ModelMatrix"), 1, GL_FALSE, core::IdentityMatrix.pointer());
}
struct TexUnit
{
GLuint m_index;
const char* m_uniform;
TexUnit(GLuint index, const char* uniform)
{
m_index = index;
m_uniform = uniform;
}
};
template <typename T>
std::vector<TexUnit> TexUnits(T curr) // required on older clang versions
{
std::vector<TexUnit> v;
v.push_back(curr);
return v;
}
template <typename T, typename... R>
std::vector<TexUnit> TexUnits(T curr, R... rest) // required on older clang versions
{
std::vector<TexUnit> v;
v.push_back(curr);
VTexUnits(v, rest...);
return v;
}
template <typename T, typename... R>
void VTexUnits(std::vector<TexUnit>& v, T curr, R... rest) // required on older clang versions
{
v.push_back(curr);
VTexUnits(v, rest...);
}
template <typename T>
void VTexUnits(std::vector<TexUnit>& v, T curr)
{
v.push_back(curr);
}
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...);
}
}
using namespace UtilShader;
bool needsUBO()
{
return irr_driver->needUBOWorkaround();
}
void setTextureSampler(GLenum tp, GLuint texunit, GLuint tid, GLuint sid)
{
#ifdef GL_VERSION_3_3
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(tp, tid);
glBindSampler(texunit, sid);
#endif
}
GLuint createNearestSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
}
void BindTextureNearest(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
}
GLuint createBilinearSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
}
void BindTextureBilinear(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
}
GLuint createBilinearClampedSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
}
void BindTextureBilinearClamped(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
}
GLuint createSemiTrilinearSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
}
void BindTextureSemiTrilinear(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
}
GLuint createTrilinearSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
return id;
#endif
}
void BindTextureTrilinearAnisotropic(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
}
void BindCubemapTrilinear(unsigned TU, unsigned tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
}
GLuint createShadowSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
return id;
#endif
}
void BindTextureShadow(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
void BindTextureVolume(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_3D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
}
unsigned getGLSLVersion()
{
return irr_driver->getGLSLVersion();
}
namespace UtilShader
{
SpecularIBLGenerator::SpecularIBLGenerator()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/importance_sampling_specular.frag").c_str());
AssignUniforms("PermutationMatrix", "samples[0]", "ViewportSize");
AssignSamplerNames(Program, 0, "tex");
}
}
namespace MeshShader
{
// Solid Normal and depth pass shaders
ObjectPass1Shader::ObjectPass1Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
AssignUniforms("ModelMatrix", "InverseModelMatrix");
AssignSamplerNames(Program, 0, "tex");
}
ObjectRefPass1Shader::ObjectRefPass1Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
AssignUniforms("ModelMatrix", "InverseModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "tex", 1, "glosstex");
}
GrassPass1Shader::GrassPass1Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
AssignUniforms("ModelMatrix", "InverseModelMatrix", "windDir");
AssignSamplerNames(Program, 0, "tex", 1, "glosstex");
}
NormalMapShader::NormalMapShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/normalmap.frag").c_str());
AssignUniforms("ModelMatrix", "InverseModelMatrix");
AssignSamplerNames(Program, 1, "normalMap", 0, "DiffuseForAlpha");
}
InstancedObjectPass1Shader::InstancedObjectPass1Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_object_pass1.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "glosstex");
}
InstancedObjectRefPass1Shader::InstancedObjectRefPass1Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass1.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex", 1, "glosstex");
}
InstancedGrassPass1Shader::InstancedGrassPass1Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass1.frag").c_str());
AssignUniforms("windDir");
AssignSamplerNames(Program, 0, "tex", 1, "glosstex");
}
InstancedNormalMapShader::InstancedNormalMapShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_normalmap.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "normalMap", 1, "glossMap");
}
// Solid Lit pass shaders
ObjectPass2Shader::ObjectPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
InstancedObjectPass2Shader::InstancedObjectPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_object_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
InstancedObjectRefPass2Shader::InstancedObjectRefPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
DetailledObjectPass2Shader::DetailledObjectPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str());
AssignUniforms("ModelMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "Detail", 5, "SpecMap");
}
InstancedDetailledObjectPass2Shader::InstancedDetailledObjectPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_detailledobject_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "Detail", 5, "SpecMap");
}
ObjectUnlitShader::ObjectUnlitShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "tex");
}
InstancedObjectUnlitShader::InstancedObjectUnlitShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_object_unlit.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "tex");
}
ObjectRefPass2Shader::ObjectRefPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
GrassPass2Shader::GrassPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/grass_pass2.frag").c_str());
AssignUniforms("ModelMatrix", "windDir");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
InstancedGrassPass2Shader::InstancedGrassPass2Shader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_grass_pass2.frag").c_str());
AssignUniforms("windDir", "SunDir");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "dtex", 4, "Albedo", 5, "SpecMap");
}
SphereMapShader::SphereMapShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_spheremap.frag").c_str());
AssignUniforms("ModelMatrix", "InverseModelMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "tex");
}
InstancedSphereMapShader::InstancedSphereMapShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectpass_spheremap.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "tex");
}
SplattingShader::SplattingShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/splatting.frag").c_str());
AssignUniforms("ModelMatrix");
AssignSamplerNames(Program,
0, "DiffuseMap",
1, "SpecularMap",
2, "SSAO",
3, "tex_layout",
4, "tex_detail0",
5, "tex_detail1",
6, "tex_detail2",
7, "tex_detail3");
}
TransparentShader::TransparentShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "tex");
}
TransparentFogShader::TransparentFogShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparentfog.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix", "fogmax", "startH", "endH", "start", "end", "col");
AssignSamplerNames(Program, 0, "tex");
}
BillboardShader::BillboardShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/billboard.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/billboard.frag").c_str());
AssignUniforms("ModelViewMatrix", "ProjectionMatrix", "Position", "Size");
AssignSamplerNames(Program, 0, "tex");
}
ColorizeShader::ColorizeShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/colorize.frag").c_str());
AssignUniforms("ModelMatrix", "col");
}
InstancedColorizeShader::InstancedColorizeShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/glow_object.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/glow_object.frag").c_str());
AssignUniforms();
}
ShadowShader::ShadowShader()
{
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
return;
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
}
AssignUniforms("layer", "ModelMatrix");
}
RSMShader::RSMShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/rsm.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rsm.frag").c_str());
AssignUniforms("RSMMatrix", "ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "tex");
}
InstancedRSMShader::InstancedRSMShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_rsm.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_rsm.frag").c_str());
AssignUniforms("RSMMatrix");
AssignSamplerNames(Program, 0, "tex");
}
SplattingRSMShader::SplattingRSMShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/rsm.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/splatting_rsm.frag").c_str());
AssignUniforms("RSMMatrix", "ModelMatrix");
AssignSamplerNames(Program, 0, "tex_layout", 1, "tex_detail0", 2, "tex_detail1", 3, "tex_detail2", 4, "tex_detail3");
}
InstancedShadowShader::InstancedShadowShader()
{
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
return;
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
}
AssignUniforms("layer");
}
RefShadowShader::RefShadowShader()
{
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
return;
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadowref.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadowref.frag").c_str());
}
AssignUniforms("layer", "ModelMatrix");
AssignSamplerNames(Program, 0, "tex");
}
InstancedRefShadowShader::InstancedRefShadowShader()
{
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
return;
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
AssignUniforms("layer");
AssignSamplerNames(Program, 0, "tex");
}
GrassShadowShader::GrassShadowShader()
{
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
return;
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow_grass.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
AssignUniforms("layer", "ModelMatrix", "windDir");
AssignSamplerNames(Program, 0, "tex");
}
InstancedGrassShadowShader::InstancedGrassShadowShader()
{
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
return;
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedgrassshadow.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedgrassshadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_shadowref.frag").c_str());
}
AssignSamplerNames(Program, 0, "tex");
AssignUniforms("layer", "windDir");
}
DisplaceMaskShader::DisplaceMaskShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
AssignUniforms("ModelMatrix");
}
DisplaceShader::DisplaceShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/displace.frag").c_str());
AssignUniforms("ModelMatrix", "dir", "dir2");
AssignSamplerNames(Program,
0, "displacement_tex",
1, "color_tex",
2, "mask_tex",
3, "tex");
}
SkyboxShader::SkyboxShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sky.frag").c_str());
AssignUniforms("ModelMatrix");
AssignSamplerNames(Program, 0, "tex");
glGenVertexArrays(1, &cubevao);
glBindVertexArray(cubevao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
glBindVertexArray(0);
}
NormalVisualizer::NormalVisualizer()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/normal_visualizer.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str());
AssignUniforms("color");
}
GLuint ViewFrustrumShader::Program;
GLuint ViewFrustrumShader::attrib_position;
GLuint ViewFrustrumShader::uniform_color;
GLuint ViewFrustrumShader::uniform_idx;
GLuint ViewFrustrumShader::frustrumvao;
void ViewFrustrumShader::init()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/frustrum.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_color = glGetUniformLocation(Program, "color");
uniform_idx = glGetUniformLocation(Program, "idx");
glGenVertexArrays(1, &frustrumvao);
glBindVertexArray(frustrumvao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::frustrumvbo);
glEnableVertexAttribArray(attrib_position);
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::frustrumindexes);
glBindVertexArray(0);
}
void ViewFrustrumShader::setUniforms(const video::SColor &color, unsigned idx)
{
glUniform4i(uniform_color, color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
glUniform1i(uniform_idx, idx);
}
}
namespace LightShader
{
PointLightShader::PointLightShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlight.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "ntex", 1, "dtex");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, MAXLIGHT * sizeof(PointLightInfo), 0, GL_DYNAMIC_DRAW);
GLuint attrib_Position = glGetAttribLocation(Program, "Position");
GLuint attrib_Color = glGetAttribLocation(Program, "Color");
GLuint attrib_Energy = glGetAttribLocation(Program, "Energy");
GLuint attrib_Radius = glGetAttribLocation(Program, "Radius");
glEnableVertexAttribArray(attrib_Position);
glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
glEnableVertexAttribArray(attrib_Energy);
glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
glEnableVertexAttribArray(attrib_Color);
glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
glEnableVertexAttribArray(attrib_Radius);
glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(7 * sizeof(float)));
glVertexAttribDivisorARB(attrib_Position, 1);
glVertexAttribDivisorARB(attrib_Energy, 1);
glVertexAttribDivisorARB(attrib_Color, 1);
glVertexAttribDivisorARB(attrib_Radius, 1);
}
PointLightScatterShader::PointLightScatterShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlightscatter.frag").c_str());
AssignUniforms("density", "fogcol");
AssignSamplerNames(Program, 0, "dtex");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo);
GLuint attrib_Position = glGetAttribLocation(Program, "Position");
GLuint attrib_Color = glGetAttribLocation(Program, "Color");
GLuint attrib_Energy = glGetAttribLocation(Program, "Energy");
GLuint attrib_Radius = glGetAttribLocation(Program, "Radius");
glEnableVertexAttribArray(attrib_Position);
glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
glEnableVertexAttribArray(attrib_Energy);
glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
glEnableVertexAttribArray(attrib_Color);
glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
glEnableVertexAttribArray(attrib_Radius);
glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(7 * sizeof(float)));
glVertexAttribDivisorARB(attrib_Position, 1);
glVertexAttribDivisorARB(attrib_Energy, 1);
glVertexAttribDivisorARB(attrib_Color, 1);
glVertexAttribDivisorARB(attrib_Radius, 1);
}
}
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)
{
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint attrib_position = glGetAttribLocation(Program, "Position");
GLuint attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
glBindBuffer(GL_ARRAY_BUFFER, quad_vbo);
glEnableVertexAttribArray(attrib_position);
glEnableVertexAttribArray(attrib_texcoord);
glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid*)(2 * sizeof(float)));
glBindVertexArray(0);
return vao;
}
namespace FullScreenShader
{
BloomShader::BloomShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getCIEXYZ.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getRGBfromCIEXxy.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bloom.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
}
BloomBlendShader::BloomBlendShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bloomblend.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex_128", 1, "tex_256", 2, "tex_512");
}
LensBlendShader::LensBlendShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/lensblend.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex_128", 1, "tex_256", 2, "tex_512");
}
ToneMapShader::ToneMapShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getRGBfromCIEXxy.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getCIEXYZ.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/tonemap.frag").c_str());
AssignUniforms("vignette_weight");
AssignSamplerNames(Program, 0, "text");
}
DepthOfFieldShader::DepthOfFieldShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/dof.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex", 1, "dtex");
}
SunLightShader::SunLightShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlight.frag").c_str());
AssignSamplerNames(Program, 0, "ntex", 1, "dtex");
AssignUniforms("direction", "col");
}
IBLShader::IBLShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/DiffuseIBL.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularIBL.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/IBL.frag").c_str());
AssignUniforms("TransposeViewMatrix", "blueLmn[0]", "greenLmn[0]", "redLmn[0]");
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "probe");
}
ShadowedSunLightShader::ShadowedSunLightShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlightshadow.frag").c_str());
// Use 8 to circumvent a catalyst bug when binding sampler
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 8, "shadowtex");
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
}
RadianceHintsConstructionShader::RadianceHintsConstructionShader()
{
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/slicedscreenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
}
else
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/slicedscreenquad.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/rhpassthrough.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
}
AssignUniforms("RSMMatrix", "RHMatrix", "extents", "suncol");
AssignSamplerNames(Program, 0, "ctex", 1, "ntex", 2, "dtex");
}
NVWorkaroundRadianceHintsConstructionShader::NVWorkaroundRadianceHintsConstructionShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/slicedscreenquad_nvworkaround.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/rhpassthrough.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
AssignUniforms("RSMMatrix", "RHMatrix", "extents", "slice", "suncol");
AssignSamplerNames(Program, 0, "ctex", 1, "ntex", 2, "dtex");
}
RHDebug::RHDebug()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/rhdebug.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rhdebug.frag").c_str());
AssignUniforms("RHMatrix", "extents");
TU_SHR = 0;
TU_SHG = 1;
TU_SHB = 2;
AssignTextureUnit(Program, TexUnit(TU_SHR, "SHR"), TexUnit(TU_SHG, "SHG"), TexUnit(TU_SHB, "SHB"));
}
GlobalIlluminationReconstructionShader::GlobalIlluminationReconstructionShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gi.frag").c_str());
AssignUniforms("RHMatrix", "InvRHMatrix", "extents");
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "SHR", 3, "SHG", 4, "SHB");
}
Gaussian17TapHShader::Gaussian17TapHShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bilateralH.frag").c_str());
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "tex", 1, "depth");
}
ComputeGaussian17TapHShader::ComputeGaussian17TapHShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/bilateralH.comp").c_str());
TU_dest = 2;
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "source", 1, "depth");
AssignTextureUnit(Program, TexUnit(TU_dest, "dest"));
}
ComputeGaussian6HBlurShader::ComputeGaussian6HBlurShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/gaussian6h.comp").c_str());
TU_dest = 1;
AssignUniforms("pixel", "sigma");
AssignSamplerNames(Program, 0, "source");
AssignTextureUnit(Program, TexUnit(TU_dest, "dest"));
}
ComputeShadowBlurHShader::ComputeShadowBlurHShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/blurshadowH.comp").c_str());
TU_dest = 1;
AssignUniforms("pixel", "sigma");
AssignSamplerNames(Program, 0, "source");
AssignTextureUnit(Program, TexUnit(TU_dest, "dest"));
}
Gaussian6HBlurShader::Gaussian6HBlurShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6h.frag").c_str());
AssignUniforms("pixel", "sigma");
AssignSamplerNames(Program, 0, "tex");
}
HorizontalBlurShader::HorizontalBlurShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6h.frag").c_str());
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "tex");
}
Gaussian3HBlurShader::Gaussian3HBlurShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian3h.frag").c_str());
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "tex");
}
Gaussian17TapVShader::Gaussian17TapVShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bilateralV.frag").c_str());
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "tex", 1, "depth");
}
ComputeGaussian17TapVShader::ComputeGaussian17TapVShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/bilateralV.comp").c_str());
TU_dest = 2;
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "source", 1, "depth");
AssignTextureUnit(Program, TexUnit(TU_dest, "dest"));
}
ComputeGaussian6VBlurShader::ComputeGaussian6VBlurShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/gaussian6v.comp").c_str());
TU_dest = 1;
AssignUniforms("pixel", "sigma");
AssignSamplerNames(Program, 0, "source");
AssignTextureUnit(Program, TexUnit(TU_dest, "dest"));
}
ComputeShadowBlurVShader::ComputeShadowBlurVShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/blurshadowV.comp").c_str());
TU_dest = 1;
AssignUniforms("pixel", "sigma");
AssignSamplerNames(Program, 0, "source");
AssignTextureUnit(Program, TexUnit(TU_dest, "dest"));
}
Gaussian6VBlurShader::Gaussian6VBlurShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6v.frag").c_str());
AssignUniforms("pixel", "sigma");
AssignSamplerNames(Program, 0, "tex");
}
Gaussian3VBlurShader::Gaussian3VBlurShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian3v.frag").c_str());
AssignUniforms("pixel");
AssignSamplerNames(Program, 0, "tex");
}
PassThroughShader::PassThroughShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/texturedquad.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "texture");
vao = createVAO(Program);
}
LayerPassThroughShader::LayerPassThroughShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/layertexturequad.frag").c_str());
TU_texture = 0;
AssignUniforms("layer");
AssignTextureUnit(Program, TexUnit(TU_texture, "tex"));
vao = createVAO(Program);
}
LinearizeDepthShader::LinearizeDepthShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/linearizedepth.frag").c_str());
AssignUniforms("zn", "zf");
AssignSamplerNames(Program, 0, "texture");
}
LightspaceBoundingBoxShader::LightspaceBoundingBoxShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/Lightspaceboundingbox.comp").c_str(),
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str());
AssignSamplerNames(Program, 0, "depth");
AssignUniforms("SunCamMatrix", "split0", "split1", "split2", "splitmax");
GLuint block_idx = glGetProgramResourceIndex(Program, GL_SHADER_STORAGE_BLOCK, "BoundingBoxes");
glShaderStorageBlockBinding(Program, block_idx, 2);
}
DepthHistogramShader::DepthHistogramShader()
{
Program = LoadProgram(OBJECT,
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/depthhistogram.comp").c_str(),
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str());
AssignSamplerNames(Program, 0, "depth");
GLuint block_idx = glGetProgramResourceIndex(Program, GL_SHADER_STORAGE_BLOCK, "Histogram");
glShaderStorageBlockBinding(Program, block_idx, 1);
}
GlowShader::GlowShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/glow.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
vao = createVAO(Program);
}
SSAOShader::SSAOShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/ssao.frag").c_str());
AssignSamplerNames(Program, 0, "dtex");
AssignUniforms("radius", "k", "sigma");
}
FogShader::FogShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/fog.frag").c_str());
AssignUniforms("density", "col");
AssignSamplerNames(Program, 0, "tex");
}
MotionBlurShader::MotionBlurShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/motion_blur.frag").c_str());
AssignUniforms("previous_viewproj", "center", "boost_amount", "mask_radius");
AssignSamplerNames(Program, 0, "color_buffer", 1, "dtex");
}
GodFadeShader::GodFadeShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/godfade.frag").c_str());
AssignUniforms("col");
AssignSamplerNames(Program, 0, "tex");
vao = createVAO(Program);
}
GodRayShader::GodRayShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/godray.frag").c_str());
AssignUniforms("sunpos");
AssignSamplerNames(Program, 0, "tex");
vao = createVAO(Program);
}
MLAAColorEdgeDetectionSHader::MLAAColorEdgeDetectionSHader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/mlaa_offset.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/mlaa_color1.frag").c_str());
AssignUniforms("PIXEL_SIZE");
AssignSamplerNames(Program, 0, "colorMapG");
vao = createVAO(Program);
}
MLAABlendWeightSHader::MLAABlendWeightSHader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/mlaa_blend2.frag").c_str());
AssignUniforms("PIXEL_SIZE");
AssignSamplerNames(Program, 0, "edgesMap", 1, "areaMap");
vao = createVAO(Program);
}
MLAAGatherSHader::MLAAGatherSHader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/mlaa_offset.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/mlaa_neigh3.frag").c_str());
AssignUniforms("PIXEL_SIZE");
AssignSamplerNames(Program, 0, "blendMap", 1, "colorMap");
vao = createVAO(Program);
}
}
namespace UIShader
{
Primitive2DList::Primitive2DList()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/primitive2dlist.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
}
TextureRectShader::TextureRectShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/texturedquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/texturedquad.frag").c_str());
AssignUniforms("center", "size", "texcenter", "texsize");
AssignSamplerNames(Program, 0, "tex");
}
UniformColoredTextureRectShader::UniformColoredTextureRectShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/texturedquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/uniformcolortexturedquad.frag").c_str());
AssignUniforms("center", "size", "texcenter", "texsize", "color");
AssignSamplerNames(Program, 0, "tex");
}
ColoredTextureRectShader::ColoredTextureRectShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/colortexturedquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/colortexturedquad.frag").c_str());
AssignUniforms("center", "size", "texcenter", "texsize");
AssignSamplerNames(Program, 0, "tex");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, quad_buffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float)));
const unsigned quad_color[] = {
0, 0, 0, 255,
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
};
glGenBuffers(1, &colorvbo);
glBindBuffer(GL_ARRAY_BUFFER, colorvbo);
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(unsigned), quad_color, GL_DYNAMIC_DRAW);
glVertexAttribIPointer(2, 4, GL_UNSIGNED_INT, 4 * sizeof(unsigned), 0);
glBindVertexArray(0);
}
ColoredRectShader::ColoredRectShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/coloredquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str());
AssignUniforms("center", "size", "color");
}
}