Started refactoring of shaders to follow our coding style.
One transform feedback buffer shader in particles is done.
This commit is contained in:
parent
959c86d816
commit
262fc0c373
@ -1,5 +1,5 @@
|
|||||||
# Modify this file to change the last-modified date when you add/remove a file.
|
# Modify this file to change the last-modified date when you add/remove a file.
|
||||||
# This will then trigger a new cmake run automatically.
|
# This will then trigger a new cmake run automatically.
|
||||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "graphics/glwrap.hpp"
|
#include "graphics/glwrap.hpp"
|
||||||
|
#include "graphics/shaders_util.hpp"
|
||||||
#include "gpuparticles.hpp"
|
#include "gpuparticles.hpp"
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "config/user_config.hpp"
|
#include "config/user_config.hpp"
|
||||||
@ -386,15 +387,15 @@ void ParticleSystemProxy::simulate()
|
|||||||
glEnable(GL_RASTERIZER_DISCARD);
|
glEnable(GL_RASTERIZER_DISCARD);
|
||||||
if (has_height_map)
|
if (has_height_map)
|
||||||
{
|
{
|
||||||
glUseProgram(ParticleShader::HeightmapSimulationShader::getInstance()->Program);
|
glUseProgram(HeightmapSimulationShader::getInstance()->Program);
|
||||||
glActiveTexture(GL_TEXTURE0 + ParticleShader::HeightmapSimulationShader::getInstance()->TU_heightmap);
|
glActiveTexture(GL_TEXTURE0 + HeightmapSimulationShader::getInstance()->TU_heightmap);
|
||||||
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
|
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
|
else
|
||||||
{
|
{
|
||||||
glUseProgram(ParticleShader::SimpleSimulationShader::getInstance()->Program);
|
PointEmitterShader::getInstance()->use();
|
||||||
ParticleShader::SimpleSimulationShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor);
|
PointEmitterShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindVertexArray(current_simulation_vao);
|
glBindVertexArray(current_simulation_vao);
|
||||||
@ -432,10 +433,10 @@ void ParticleSystemProxy::simulate()
|
|||||||
void ParticleSystemProxy::drawFlip()
|
void ParticleSystemProxy::drawFlip()
|
||||||
{
|
{
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
glUseProgram(ParticleShader::FlipParticleRender::getInstance()->Program);
|
glUseProgram(FlipParticleRender::getInstance()->Program);
|
||||||
|
|
||||||
ParticleShader::FlipParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
|
FlipParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
|
||||||
ParticleShader::FlipParticleRender::getInstance()->setUniforms();
|
FlipParticleRender::getInstance()->setUniforms();
|
||||||
|
|
||||||
glBindVertexArray(current_rendering_vao);
|
glBindVertexArray(current_rendering_vao);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_count);
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_count);
|
||||||
@ -447,13 +448,13 @@ void ParticleSystemProxy::drawNotFlip()
|
|||||||
glBlendFunc(GL_ONE, GL_ONE);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
else
|
else
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
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 ColorFrom = video::SColorf(getColorFrom()[0], getColorFrom()[1], getColorFrom()[2]);
|
||||||
video::SColorf ColorTo = video::SColorf(getColorTo()[0], getColorTo()[1], getColorTo()[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);
|
glBindVertexArray(current_rendering_vao);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_count);
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, m_count);
|
||||||
@ -534,3 +535,97 @@ void ParticleSystemProxy::render() {
|
|||||||
simulate();
|
simulate();
|
||||||
draw();
|
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");
|
||||||
|
}
|
||||||
|
@ -15,13 +15,45 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#ifndef GPUPARTICLES_H
|
#ifndef HEADER_GPU_PARTICLES_HPP
|
||||||
#define GPUPARTICLES_H
|
#define HEADER_GPU_PARTICLES_HPP
|
||||||
|
|
||||||
|
#include "graphics/shader.hpp"
|
||||||
#include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
|
#include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
|
||||||
#include <ISceneManager.h>
|
#include <ISceneManager.h>
|
||||||
#include <IParticleSystemSceneNode.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; } }
|
namespace irr { namespace video{ class ITexture; } }
|
||||||
|
|
||||||
class ParticleSystemProxy : public scene::CParticleSystemSceneNode
|
class ParticleSystemProxy : public scene::CParticleSystemSceneNode
|
||||||
|
200
src/graphics/shader.cpp
Normal file
200
src/graphics/shader.cpp
Normal 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
228
src/graphics/shader.hpp
Normal 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
|
@ -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)
|
static GLuint createVAO(GLuint Program)
|
||||||
{
|
{
|
||||||
|
@ -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>
|
template<typename T, typename... Args>
|
||||||
static void DrawFullScreenEffect(Args...args)
|
static void DrawFullScreenEffect(Args...args)
|
||||||
|
@ -158,7 +158,16 @@ public:
|
|||||||
{
|
{
|
||||||
m_music_search_path.push_back(path);
|
m_music_search_path.push_back(path);
|
||||||
} // pushMusicSearchPath
|
} // 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
|
}; // FileManager
|
||||||
|
|
||||||
extern FileManager* file_manager;
|
extern FileManager* file_manager;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user