mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 03:35:26 +00:00
Add the VideoCommon PostProcessing class.
This class loads all the common PP shader configuration options and passes those options through to a inherited class that OpenGL or D3D will have. Makes it so all the common code for PP shaders is in VideoCommon instead of duplicating the code across each backend.
This commit is contained in:
parent
3a657fe33c
commit
6bdc32c54a
@ -19,9 +19,7 @@
|
||||
#include "Common/IniFile.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
|
||||
void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
|
||||
{
|
||||
if (line[0] == '#')
|
||||
return;
|
||||
@ -40,8 +38,6 @@ void ParseLine(const std::string& line, std::string* keyOut, std::string* valueO
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::string& IniFile::NULL_STRING = "";
|
||||
|
||||
void IniFile::Section::Set(const std::string& key, const std::string& newValue)
|
||||
|
@ -116,6 +116,11 @@ public:
|
||||
|
||||
Section* GetOrCreateSection(const std::string& section);
|
||||
|
||||
// This function is related to parsing data from lines of INI files
|
||||
// It's used outside of IniFile, which is why it is exposed publicly
|
||||
// In particular it is used in PostProcessing for its configuration
|
||||
static void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut);
|
||||
|
||||
private:
|
||||
std::list<Section> sections;
|
||||
|
||||
|
@ -415,6 +415,11 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
|
||||
else
|
||||
choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader));
|
||||
|
||||
// Should the configuration button be loaded by default?
|
||||
PostProcessingShaderConfiguration postprocessing_shader;
|
||||
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
|
||||
button_config_pp->Enable(postprocessing_shader.HasOptions());
|
||||
|
||||
choice_ppshader->Bind(wxEVT_CHOICE, &VideoConfigDiag::Event_PPShader, this);
|
||||
|
||||
szr_enh->Add(new wxStaticText(page_enh, -1, _("Post-Processing Effect:")), 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
@ -142,6 +142,19 @@ protected:
|
||||
else
|
||||
vconfig.sPostProcessingShader.clear();
|
||||
|
||||
// Should we enable the configuration button?
|
||||
PostProcessingShaderConfiguration postprocessing_shader;
|
||||
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
|
||||
button_config_pp->Enable(postprocessing_shader.HasOptions());
|
||||
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void Event_ConfigurePPShader(wxCommandEvent &ev)
|
||||
{
|
||||
PostProcessingConfigDiag dialog(this, vconfig.sPostProcessingShader);
|
||||
dialog.ShowModal();
|
||||
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
|
@ -40,14 +40,13 @@ static char s_vertex_shader[] =
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_currentShader = "";
|
||||
s_enable = 0;
|
||||
s_width = 0;
|
||||
s_height = 0;
|
||||
m_enable = false;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
|
||||
glGenFramebuffers(1, &s_fbo);
|
||||
glGenTextures(1, &s_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, s_texture);
|
||||
glGenFramebuffers(1, &m_fbo);
|
||||
glGenTextures(1, &m_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
@ -59,7 +58,7 @@ void Init()
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
s_shader.Destroy();
|
||||
m_shader.Destroy();
|
||||
|
||||
glDeleteFramebuffers(1, &s_fbo);
|
||||
glDeleteTextures(1, &s_texture);
|
||||
@ -84,6 +83,9 @@ void BlitToScreen()
|
||||
|
||||
s_shader.Bind();
|
||||
|
||||
glUniform4f(m_uniform_resolution, (float)m_width, (float)m_height, 1.0f/(float)m_width, 1.0f/(float)m_height);
|
||||
glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed());
|
||||
|
||||
glUniform4f(s_uniform_resolution, (float)s_width, (float)s_height, 1.0f/(float)s_width, 1.0f/(float)s_height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
@ -145,10 +147,82 @@ void ApplyShader()
|
||||
}
|
||||
|
||||
// read uniform locations
|
||||
s_uniform_resolution = glGetUniformLocation(s_shader.glprogid, "resolution");
|
||||
m_uniform_resolution = glGetUniformLocation(m_shader.glprogid, "resolution");
|
||||
m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time");
|
||||
|
||||
for (const auto& it : m_options)
|
||||
{
|
||||
std::string glsl_name = "option_" + it.first;
|
||||
m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str());
|
||||
}
|
||||
|
||||
// successful
|
||||
s_enable = true;
|
||||
m_enable = true;
|
||||
}
|
||||
|
||||
void OpenGLPostProcessing::CreateHeader()
|
||||
{
|
||||
m_glsl_header =
|
||||
// Required variables
|
||||
// Shouldn't be accessed directly by the PP shader
|
||||
// Texture sampler
|
||||
"SAMPLER_BINDING(8) uniform sampler2D samp8;\n"
|
||||
"SAMPLER_BINDING(9) uniform sampler2D samp9;\n"
|
||||
|
||||
// Output variable
|
||||
"out float4 ocol0;\n"
|
||||
// Input coordinates
|
||||
"in float2 uv0;\n"
|
||||
// Resolution
|
||||
"uniform float4 resolution;\n"
|
||||
// Time
|
||||
"uniform uint time;\n"
|
||||
|
||||
// Interfacing functions
|
||||
"float4 Sample()\n"
|
||||
"{\n"
|
||||
"\treturn texture(samp9, uv0);\n"
|
||||
"}\n"
|
||||
|
||||
"float4 SampleLocation(float2 location)\n"
|
||||
"{\n"
|
||||
"\treturn texture(samp9, location);\n"
|
||||
"}\n"
|
||||
|
||||
"#define SampleOffset(offset) textureOffset(samp9, uv0, offset)\n"
|
||||
|
||||
"float4 SampleFontLocation(float2 location)\n"
|
||||
"{\n"
|
||||
"\treturn texture(samp8, location);\n"
|
||||
"}\n"
|
||||
|
||||
"float2 GetResolution()\n"
|
||||
"{\n"
|
||||
"\treturn resolution.xy;\n"
|
||||
"}\n"
|
||||
|
||||
"float2 GetInvResolution()\n"
|
||||
"{\n"
|
||||
"\treturn resolution.zw;\n"
|
||||
"}\n"
|
||||
|
||||
"float2 GetCoordinates()\n"
|
||||
"{\n"
|
||||
"\treturn uv0;\n"
|
||||
"}\n"
|
||||
|
||||
"uint GetTime()\n"
|
||||
"{\n"
|
||||
"\treturn time;\n"
|
||||
"}\n"
|
||||
|
||||
"void SetOutput(float4 color)\n"
|
||||
"{\n"
|
||||
"\tocol0 = color;\n"
|
||||
"}\n"
|
||||
|
||||
"#define GetOption(x) (option_#x)\n"
|
||||
"#define OptionEnabled(x) (option_#x != 0)\n";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -4,26 +4,38 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "VideoBackends/OGL/GLUtil.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace PostProcessing
|
||||
class OpenGLPostProcessing : public PostProcessingShaderImplementation
|
||||
{
|
||||
public:
|
||||
OpenGLPostProcessing();
|
||||
~OpenGLPostProcessing();
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void BindTargetFramebuffer() override;
|
||||
void BlitToScreen() override;
|
||||
void Update(u32 width, u32 height) override;
|
||||
void ApplyShader() override;
|
||||
|
||||
void BindTargetFramebuffer();
|
||||
void BlitToScreen();
|
||||
void Update(u32 width, u32 height);
|
||||
private:
|
||||
GLuint m_fbo;
|
||||
GLuint m_texture;
|
||||
SHADER m_shader;
|
||||
GLuint m_uniform_resolution;
|
||||
GLuint m_uniform_time;
|
||||
std::string m_glsl_header;
|
||||
|
||||
void ReloadShader();
|
||||
std::unordered_map<std::string, GLuint> m_uniform_bindings;
|
||||
|
||||
void ApplyShader();
|
||||
|
||||
} // namespace
|
||||
void CreateHeader();
|
||||
std::string LoadShaderOptions(const std::string& code);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -18,6 +18,7 @@ set(SRCS BPFunctions.cpp
|
||||
PixelEngine.cpp
|
||||
PixelShaderGen.cpp
|
||||
PixelShaderManager.cpp
|
||||
PostProcessing.cpp
|
||||
RenderBase.cpp
|
||||
Statistics.cpp
|
||||
TextureCacheBase.cpp
|
||||
|
304
Source/Core/VideoCommon/PostProcessing.cpp
Normal file
304
Source/Core/VideoCommon/PostProcessing.cpp
Normal file
@ -0,0 +1,304 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
|
||||
PostProcessingShaderImplementation::PostProcessingShaderImplementation()
|
||||
{
|
||||
m_timer.Start();
|
||||
}
|
||||
|
||||
PostProcessingShaderImplementation::~PostProcessingShaderImplementation()
|
||||
{
|
||||
m_timer.Stop();
|
||||
}
|
||||
|
||||
std::string PostProcessingShaderConfiguration::LoadShader(std::string shader)
|
||||
{
|
||||
// Load the shader from the configuration if there isn't one sent to us.
|
||||
if (shader == "")
|
||||
shader = g_ActiveConfig.sPostProcessingShader;
|
||||
m_current_shader = shader;
|
||||
|
||||
// loading shader code
|
||||
std::string code;
|
||||
std::string path = File::GetUserPath(D_SHADERS_IDX) + shader + ".glsl";
|
||||
|
||||
if (!File::Exists(path))
|
||||
{
|
||||
// Fallback to shared user dir
|
||||
path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + shader + ".glsl";
|
||||
}
|
||||
|
||||
if (!File::ReadFileToString(path, code))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
LoadOptions(code);
|
||||
LoadOptionsConfiguration();
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::LoadOptions(const std::string& code)
|
||||
{
|
||||
const std::string config_start_delimiter = "[configuration]";
|
||||
const std::string config_end_delimiter = "[/configuration]";
|
||||
size_t configuration_start = code.find(config_start_delimiter);
|
||||
size_t configuration_end = code.find(config_end_delimiter);
|
||||
|
||||
m_options.clear();
|
||||
m_any_options_dirty = true;
|
||||
|
||||
if (configuration_start == std::string::npos ||
|
||||
configuration_end == std::string::npos)
|
||||
{
|
||||
// Issue loading configuration or there isn't one.
|
||||
return;
|
||||
}
|
||||
|
||||
std::string configuration_string = code.substr(configuration_start + config_start_delimiter.size(),
|
||||
configuration_end - configuration_start - config_start_delimiter.size());
|
||||
|
||||
std::istringstream in(configuration_string);
|
||||
|
||||
struct GLSLStringOption
|
||||
{
|
||||
std::string m_type;
|
||||
std::vector<std::pair<std::string, std::string>> m_options;
|
||||
};
|
||||
|
||||
std::vector<GLSLStringOption> option_strings;
|
||||
GLSLStringOption* current_strings = nullptr;
|
||||
while (!in.eof())
|
||||
{
|
||||
std::string line;
|
||||
|
||||
if (std::getline(in, line))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
// Check for CRLF eol and convert it to LF
|
||||
if (!line.empty() && line.at(line.size()-1) == '\r')
|
||||
{
|
||||
line.erase(line.size()-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (line.size() > 0)
|
||||
{
|
||||
if (line[0] == '[')
|
||||
{
|
||||
size_t endpos = line.find("]");
|
||||
|
||||
if (endpos != std::string::npos)
|
||||
{
|
||||
// New section!
|
||||
std::string sub = line.substr(1, endpos - 1);
|
||||
option_strings.push_back({ sub });
|
||||
current_strings = &option_strings.back();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_strings)
|
||||
{
|
||||
std::string key, value;
|
||||
IniFile::ParseLine(line, &key, &value);
|
||||
|
||||
if (!(key == "" && value == ""))
|
||||
current_strings->m_options.push_back(std::make_pair(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& it : option_strings)
|
||||
{
|
||||
ConfigurationOption option;
|
||||
option.m_dirty = true;
|
||||
|
||||
if (it.m_type == "OptionBool")
|
||||
option.m_type = ConfigurationOption::OptionType::OPTION_BOOL;
|
||||
else if (it.m_type == "OptionRangeFloat")
|
||||
option.m_type = ConfigurationOption::OptionType::OPTION_FLOAT;
|
||||
else if (it.m_type == "OptionRangeInteger")
|
||||
option.m_type = ConfigurationOption::OptionType::OPTION_INTEGER;
|
||||
|
||||
for (const auto& string_option : it.m_options)
|
||||
{
|
||||
if (string_option.first == "GUIName")
|
||||
{
|
||||
option.m_gui_name = string_option.second;
|
||||
}
|
||||
else if (string_option.first == "OptionName")
|
||||
{
|
||||
option.m_option_name = string_option.second;
|
||||
}
|
||||
else if (string_option.first == "DependentOption")
|
||||
{
|
||||
option.m_dependent_option = string_option.second;
|
||||
}
|
||||
else if (string_option.first == "MinValue" ||
|
||||
string_option.first == "MaxValue" ||
|
||||
string_option.first == "DefaultValue" ||
|
||||
string_option.first == "StepAmount")
|
||||
{
|
||||
std::vector<s32>* output_integer = nullptr;
|
||||
std::vector<float>* output_float = nullptr;
|
||||
|
||||
if (string_option.first == "MinValue")
|
||||
{
|
||||
output_integer = &option.m_integer_min_values;
|
||||
output_float = &option.m_float_min_values;
|
||||
}
|
||||
else if (string_option.first == "MaxValue")
|
||||
{
|
||||
output_integer = &option.m_integer_max_values;
|
||||
output_float = &option.m_float_max_values;
|
||||
}
|
||||
else if (string_option.first == "DefaultValue")
|
||||
{
|
||||
output_integer = &option.m_integer_values;
|
||||
output_float = &option.m_float_values;
|
||||
}
|
||||
else if (string_option.first == "StepAmount")
|
||||
{
|
||||
output_integer = &option.m_integer_step_values;
|
||||
output_float = &option.m_float_step_values;
|
||||
}
|
||||
|
||||
if (option.m_type == ConfigurationOption::OptionType::OPTION_BOOL)
|
||||
{
|
||||
TryParse(string_option.second, &option.m_bool_value);
|
||||
}
|
||||
else if (option.m_type == ConfigurationOption::OptionType::OPTION_INTEGER)
|
||||
{
|
||||
TryParseVector(string_option.second, output_integer);
|
||||
if (output_integer->size() > 4)
|
||||
output_integer->erase(output_integer->begin() + 4, output_integer->end());
|
||||
}
|
||||
else if (option.m_type == ConfigurationOption::OptionType::OPTION_FLOAT)
|
||||
{
|
||||
TryParseVector(string_option.second, output_float);
|
||||
if (output_float->size() > 4)
|
||||
output_float->erase(output_float->begin() + 4, output_float->end());
|
||||
}
|
||||
}
|
||||
}
|
||||
m_options[option.m_option_name] = option;
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::LoadOptionsConfiguration()
|
||||
{
|
||||
IniFile ini;
|
||||
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||
std::string section = m_current_shader + "-options";
|
||||
|
||||
for (auto& it : m_options)
|
||||
{
|
||||
switch (it.second.m_type)
|
||||
{
|
||||
case ConfigurationOption::OptionType::OPTION_BOOL:
|
||||
ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &it.second.m_bool_value, it.second.m_bool_value);
|
||||
break;
|
||||
case ConfigurationOption::OptionType::OPTION_INTEGER:
|
||||
{
|
||||
std::string value;
|
||||
ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &value);
|
||||
if (value != "")
|
||||
TryParseVector(value, &it.second.m_integer_values);
|
||||
}
|
||||
break;
|
||||
case ConfigurationOption::OptionType::OPTION_FLOAT:
|
||||
{
|
||||
std::string value;
|
||||
ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &value);
|
||||
if (value != "")
|
||||
TryParseVector(value, &it.second.m_float_values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::SaveOptionsConfiguration()
|
||||
{
|
||||
IniFile ini;
|
||||
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||
std::string section = m_current_shader + "-options";
|
||||
|
||||
for (auto& it : m_options)
|
||||
{
|
||||
switch (it.second.m_type)
|
||||
{
|
||||
case ConfigurationOption::OptionType::OPTION_BOOL:
|
||||
{
|
||||
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, it.second.m_bool_value);
|
||||
}
|
||||
break;
|
||||
case ConfigurationOption::OptionType::OPTION_INTEGER:
|
||||
{
|
||||
std::string value = "";
|
||||
for (size_t i = 0; i < it.second.m_integer_values.size(); ++i)
|
||||
value += StringFromFormat("%d%s", it.second.m_integer_values[i], i == (it.second.m_integer_values.size() - 1) ? "": ", ");
|
||||
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, value);
|
||||
}
|
||||
break;
|
||||
case ConfigurationOption::OptionType::OPTION_FLOAT:
|
||||
{
|
||||
std::string value = "";
|
||||
for (size_t i = 0; i < it.second.m_float_values.size(); ++i)
|
||||
value += StringFromFormat("%f%s", it.second.m_float_values[i], i == (it.second.m_float_values.size() - 1) ? "": ", ");
|
||||
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::ReloadShader()
|
||||
{
|
||||
m_current_shader = "";
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::SetOptionf(std::string option, int index, float value)
|
||||
{
|
||||
auto it = m_options.find(option);
|
||||
|
||||
it->second.m_float_values[index] = value;
|
||||
it->second.m_dirty = true;
|
||||
m_any_options_dirty = true;
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::SetOptioni(std::string option, int index, s32 value)
|
||||
{
|
||||
auto it = m_options.find(option);
|
||||
|
||||
it->second.m_integer_values[index] = value;
|
||||
it->second.m_dirty = true;
|
||||
m_any_options_dirty = true;
|
||||
}
|
||||
|
||||
void PostProcessingShaderConfiguration::SetOptionb(std::string option, bool value)
|
||||
{
|
||||
auto it = m_options.find(option);
|
||||
|
||||
it->second.m_bool_value = value;
|
||||
it->second.m_dirty = true;
|
||||
m_any_options_dirty = true;
|
||||
}
|
104
Source/Core/VideoCommon/PostProcessing.h
Normal file
104
Source/Core/VideoCommon/PostProcessing.h
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Timer.h"
|
||||
|
||||
class PostProcessingShaderConfiguration
|
||||
{
|
||||
public:
|
||||
struct ConfigurationOption
|
||||
{
|
||||
enum OptionType
|
||||
{
|
||||
OPTION_BOOL = 0,
|
||||
OPTION_FLOAT,
|
||||
OPTION_INTEGER,
|
||||
};
|
||||
|
||||
bool m_bool_value;
|
||||
|
||||
std::vector<float> m_float_values;
|
||||
std::vector<s32> m_integer_values;
|
||||
|
||||
std::vector<float> m_float_min_values;
|
||||
std::vector<s32> m_integer_min_values;
|
||||
|
||||
std::vector<float> m_float_max_values;
|
||||
std::vector<s32> m_integer_max_values;
|
||||
|
||||
std::vector<float> m_float_step_values;
|
||||
std::vector<s32> m_integer_step_values;
|
||||
|
||||
OptionType m_type;
|
||||
|
||||
std::string m_gui_name;
|
||||
std::string m_option_name;
|
||||
std::string m_dependent_option;
|
||||
bool m_dirty;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, ConfigurationOption> ConfigMap;
|
||||
|
||||
PostProcessingShaderConfiguration() : m_current_shader("") {}
|
||||
virtual ~PostProcessingShaderConfiguration() {}
|
||||
|
||||
// Loads the configuration with a shader
|
||||
// If the argument is "" the class will load the shader from the g_activeConfig option.
|
||||
// Returns the loaded shader source from file
|
||||
std::string LoadShader(std::string shader = "");
|
||||
void SaveOptionsConfiguration();
|
||||
void ReloadShader();
|
||||
std::string GetShader() { return m_current_shader; }
|
||||
|
||||
bool IsDirty() { return m_any_options_dirty; }
|
||||
void SetDirty(bool dirty) { m_any_options_dirty = dirty; }
|
||||
|
||||
bool HasOptions() { return m_options.size() > 0; }
|
||||
ConfigMap& GetOptions() { return m_options; }
|
||||
const ConfigurationOption& GetOption(const std::string& option) { return m_options[option]; }
|
||||
|
||||
// For updating option's values
|
||||
void SetOptionf(std::string option, int index, float value);
|
||||
void SetOptioni(std::string option, int index, s32 value);
|
||||
void SetOptionb(std::string option, bool value);
|
||||
|
||||
private:
|
||||
bool m_any_options_dirty;
|
||||
std::string m_current_shader;
|
||||
ConfigMap m_options;
|
||||
|
||||
void LoadOptions(const std::string& code);
|
||||
void LoadOptionsConfiguration();
|
||||
};
|
||||
|
||||
class PostProcessingShaderImplementation
|
||||
{
|
||||
public:
|
||||
PostProcessingShaderImplementation();
|
||||
virtual ~PostProcessingShaderImplementation();
|
||||
|
||||
PostProcessingShaderConfiguration* GetConfig() { return &m_config; }
|
||||
|
||||
// Should be implemented by the backends for backend specific code
|
||||
virtual void BindTargetFramebuffer() = 0;
|
||||
virtual void BlitToScreen() = 0;
|
||||
virtual void Update(u32 width, u32 height) = 0;
|
||||
virtual void ApplyShader() = 0;
|
||||
|
||||
protected:
|
||||
bool m_enable;
|
||||
u32 m_width;
|
||||
u32 m_height;
|
||||
// Timer for determining our time value
|
||||
Common::Timer m_timer;
|
||||
|
||||
PostProcessingShaderConfiguration m_config;
|
||||
};
|
@ -59,6 +59,8 @@ int Renderer::s_target_height;
|
||||
int Renderer::s_backbuffer_width;
|
||||
int Renderer::s_backbuffer_height;
|
||||
|
||||
PostProcessingShaderImplementation* Renderer::m_post_processor;
|
||||
|
||||
TargetRectangle Renderer::target_rc;
|
||||
|
||||
int Renderer::s_LastEFBScale;
|
||||
|
@ -115,6 +115,8 @@ public:
|
||||
static PEControl::PixelFormat GetPrevPixelFormat() { return prev_efb_format; }
|
||||
static void StorePixelFormat(PEControl::PixelFormat new_format) { prev_efb_format = new_format; }
|
||||
|
||||
PostProcessingShaderImplementation* GetPostProcessor() { return m_post_processor; }
|
||||
|
||||
protected:
|
||||
|
||||
static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY);
|
||||
@ -153,6 +155,8 @@ protected:
|
||||
|
||||
FPSCounter m_fps_counter;
|
||||
|
||||
static PostProcessingShaderImplementation* m_post_processor;
|
||||
|
||||
private:
|
||||
static PEControl::PixelFormat prev_efb_format;
|
||||
static unsigned int efb_scale_numeratorX;
|
||||
|
@ -56,6 +56,7 @@
|
||||
<ClCompile Include="PixelEngine.cpp" />
|
||||
<ClCompile Include="PixelShaderGen.cpp" />
|
||||
<ClCompile Include="PixelShaderManager.cpp" />
|
||||
<ClCompile Include="PostProcessing.cpp" />
|
||||
<ClCompile Include="RenderBase.cpp" />
|
||||
<ClCompile Include="Statistics.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
@ -105,6 +106,7 @@
|
||||
<ClInclude Include="PixelEngine.h" />
|
||||
<ClInclude Include="PixelShaderGen.h" />
|
||||
<ClInclude Include="PixelShaderManager.h" />
|
||||
<ClInclude Include="PostProcessing.h" />
|
||||
<ClInclude Include="RenderBase.h" />
|
||||
<ClInclude Include="ShaderGenCommon.h" />
|
||||
<ClInclude Include="Statistics.h" />
|
||||
@ -148,4 +150,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -107,6 +107,9 @@
|
||||
<ClCompile Include="OnScreenDisplay.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PostProcessing.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Statistics.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
@ -234,6 +237,9 @@
|
||||
<ClInclude Include="OnScreenDisplay.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PostProcessing.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Statistics.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
@ -266,4 +272,4 @@
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user