Merge pull request #1817 from Armada651/custom-anaglyph
PostProcessing: Add support for user-supplied anaglyph shaders.
This commit is contained in:
commit
53a9df10f9
|
@ -0,0 +1,18 @@
|
||||||
|
// Anaglyph Red-Cyan shader based on Dubois algorithm
|
||||||
|
// Constants taken from the paper:
|
||||||
|
// "Conversion of a Stereo Pair to Anaglyph with
|
||||||
|
// the Least-Squares Projection Method"
|
||||||
|
// Eric Dubois, March 2009
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float4 c0 = SampleLayer(0);
|
||||||
|
float4 c1 = SampleLayer(1);
|
||||||
|
mat3 l = mat3( 0.437, 0.449, 0.164,
|
||||||
|
-0.062,-0.062,-0.024,
|
||||||
|
-0.048,-0.050,-0.017);
|
||||||
|
mat3 r = mat3(-0.011,-0.032,-0.007,
|
||||||
|
0.377, 0.761, 0.009,
|
||||||
|
-0.026,-0.093, 1.234);
|
||||||
|
SetOutput(float4(c0.rgb * l + c1.rgb * r, c0.a));
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Anaglyph Red-Cyan shader without compensation
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float4 c0 = SampleLayer(0);
|
||||||
|
float4 c1 = SampleLayer(1);
|
||||||
|
SetOutput(float4(c0.r, c1.gb, c0.a));
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Anaglyph Red-Cyan grayscale shader
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float4 c0 = SampleLayer(0);
|
||||||
|
float avg0 = (c0.r + c0.g + c0.b) / 3.0;
|
||||||
|
float4 c1 = SampleLayer(1);
|
||||||
|
float avg1 = (c1.r + c1.g + c1.b) / 3.0;
|
||||||
|
SetOutput(float4(avg0, avg1, avg1, c0.a));
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Anaglyph Red-Cyan luma grayscale shader
|
||||||
|
// Info: http://www.oreillynet.com/cs/user/view/cs_msg/8691
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float3 luma = float3(0.222, 0.707, 0.071);
|
||||||
|
float4 c0 = SampleLayer(0);
|
||||||
|
float avg0 = dot(c0.rgb, luma);
|
||||||
|
float4 c1 = SampleLayer(1);
|
||||||
|
float avg1 = dot(c1.rgb, luma);
|
||||||
|
SetOutput(float4(avg0, avg1, avg1, c0.a));
|
||||||
|
}
|
|
@ -74,6 +74,7 @@
|
||||||
#define WII_SYSCONF_DIR "shared2" DIR_SEP "sys"
|
#define WII_SYSCONF_DIR "shared2" DIR_SEP "sys"
|
||||||
#define WII_WC24CONF_DIR "shared2" DIR_SEP "wc24"
|
#define WII_WC24CONF_DIR "shared2" DIR_SEP "wc24"
|
||||||
#define THEMES_DIR "Themes"
|
#define THEMES_DIR "Themes"
|
||||||
|
#define ANAGLYPH_DIR "Anaglyph"
|
||||||
|
|
||||||
// Filenames
|
// Filenames
|
||||||
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
||||||
|
|
|
@ -395,29 +395,14 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
|
||||||
}
|
}
|
||||||
|
|
||||||
// postproc shader
|
// postproc shader
|
||||||
if (vconfig.backend_info.PPShaders.size())
|
if (vconfig.backend_info.bSupportsPostProcessing)
|
||||||
{
|
{
|
||||||
wxFlexGridSizer* const szr_pp = new wxFlexGridSizer(3, 5, 5);
|
wxFlexGridSizer* const szr_pp = new wxFlexGridSizer(3, 5, 5);
|
||||||
choice_ppshader = new wxChoice(page_enh, wxID_ANY);
|
choice_ppshader = new wxChoice(page_enh, wxID_ANY);
|
||||||
RegisterControl(choice_ppshader, wxGetTranslation(ppshader_desc));
|
RegisterControl(choice_ppshader, wxGetTranslation(ppshader_desc));
|
||||||
choice_ppshader->AppendString(_("(off)"));
|
|
||||||
|
|
||||||
button_config_pp = new wxButton(page_enh, wxID_ANY, _("Config"));
|
button_config_pp = new wxButton(page_enh, wxID_ANY, _("Config"));
|
||||||
|
|
||||||
for (const std::string& shader : vconfig.backend_info.PPShaders)
|
PopulatePostProcessingShaders();
|
||||||
{
|
|
||||||
choice_ppshader->AppendString(StrToWxStr(shader));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vconfig.sPostProcessingShader.empty() || vconfig.iStereoMode == STEREO_ANAGLYPH)
|
|
||||||
choice_ppshader->Select(0);
|
|
||||||
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);
|
choice_ppshader->Bind(wxEVT_CHOICE, &VideoConfigDiag::Event_PPShader, this);
|
||||||
button_config_pp->Bind(wxEVT_BUTTON, &VideoConfigDiag::Event_ConfigurePPShader, this);
|
button_config_pp->Bind(wxEVT_BUTTON, &VideoConfigDiag::Event_ConfigurePPShader, this);
|
||||||
|
@ -745,3 +730,38 @@ void VideoConfigDiag::CreateDescriptionArea(wxPanel* const page, wxBoxSizer* con
|
||||||
// Store description text object for later lookup
|
// Store description text object for later lookup
|
||||||
desc_texts.insert(std::pair<wxWindow*,wxStaticText*>(page, desc_text));
|
desc_texts.insert(std::pair<wxWindow*,wxStaticText*>(page, desc_text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoConfigDiag::PopulatePostProcessingShaders()
|
||||||
|
{
|
||||||
|
std::vector<std::string> &shaders = (vconfig.iStereoMode == STEREO_ANAGLYPH) ?
|
||||||
|
vconfig.backend_info.AnaglyphShaders : vconfig.backend_info.PPShaders;
|
||||||
|
|
||||||
|
if (shaders.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
choice_ppshader->AppendString(_("(off)"));
|
||||||
|
|
||||||
|
for (const std::string& shader : shaders)
|
||||||
|
{
|
||||||
|
choice_ppshader->AppendString(StrToWxStr(shader));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader)))
|
||||||
|
{
|
||||||
|
// Invalid shader, reset it to default
|
||||||
|
choice_ppshader->Select(0);
|
||||||
|
|
||||||
|
if (vconfig.iStereoMode == STEREO_ANAGLYPH)
|
||||||
|
{
|
||||||
|
vconfig.sPostProcessingShader = "dubois";
|
||||||
|
choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vconfig.sPostProcessingShader.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should the configuration button be loaded by default?
|
||||||
|
PostProcessingShaderConfiguration postprocessing_shader;
|
||||||
|
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
|
||||||
|
button_config_pp->Enable(postprocessing_shader.HasOptions());
|
||||||
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ protected:
|
||||||
// Should we enable the configuration button?
|
// Should we enable the configuration button?
|
||||||
PostProcessingShaderConfiguration postprocessing_shader;
|
PostProcessingShaderConfiguration postprocessing_shader;
|
||||||
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
|
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
|
||||||
button_config_pp->Enable(postprocessing_shader.HasOptions() && vconfig.iStereoMode != STEREO_ANAGLYPH);
|
button_config_pp->Enable(postprocessing_shader.HasOptions());
|
||||||
|
|
||||||
ev.Skip();
|
ev.Skip();
|
||||||
}
|
}
|
||||||
|
@ -181,15 +181,10 @@ protected:
|
||||||
|
|
||||||
void Event_StereoMode(wxCommandEvent &ev)
|
void Event_StereoMode(wxCommandEvent &ev)
|
||||||
{
|
{
|
||||||
if (ev.GetInt() == STEREO_ANAGLYPH && vconfig.backend_info.PPShaders.size())
|
if (vconfig.backend_info.bSupportsPostProcessing)
|
||||||
{
|
{
|
||||||
// Anaglyph overrides post-processing shaders
|
// Anaglyph overrides post-processing shaders
|
||||||
choice_ppshader->Select(0);
|
choice_ppshader->Clear();
|
||||||
choice_ppshader->Enable(false);
|
|
||||||
}
|
|
||||||
else if (vconfig.backend_info.PPShaders.size())
|
|
||||||
{
|
|
||||||
choice_ppshader->Enable(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ev.Skip();
|
ev.Skip();
|
||||||
|
@ -214,6 +209,10 @@ protected:
|
||||||
virtual_xfb->Enable(vconfig.bUseXFB);
|
virtual_xfb->Enable(vconfig.bUseXFB);
|
||||||
real_xfb->Enable(vconfig.bUseXFB);
|
real_xfb->Enable(vconfig.bUseXFB);
|
||||||
|
|
||||||
|
// Repopulating the post-processing shaders can't be done from an event
|
||||||
|
if (choice_ppshader && choice_ppshader->IsEmpty())
|
||||||
|
PopulatePostProcessingShaders();
|
||||||
|
|
||||||
// Things which shouldn't be changed during emulation
|
// Things which shouldn't be changed during emulation
|
||||||
if (Core::IsRunning())
|
if (Core::IsRunning())
|
||||||
{
|
{
|
||||||
|
@ -251,6 +250,7 @@ protected:
|
||||||
void Evt_EnterControl(wxMouseEvent& ev);
|
void Evt_EnterControl(wxMouseEvent& ev);
|
||||||
void Evt_LeaveControl(wxMouseEvent& ev);
|
void Evt_LeaveControl(wxMouseEvent& ev);
|
||||||
void CreateDescriptionArea(wxPanel* const page, wxBoxSizer* const sizer);
|
void CreateDescriptionArea(wxPanel* const page, wxBoxSizer* const sizer);
|
||||||
|
void PopulatePostProcessingShaders();
|
||||||
|
|
||||||
wxChoice* choice_backend;
|
wxChoice* choice_backend;
|
||||||
wxChoice* choice_adapter;
|
wxChoice* choice_adapter;
|
||||||
|
|
|
@ -65,6 +65,7 @@ void CreateDirectories()
|
||||||
File::CreateFullPath(File::GetUserPath(D_MAPS_IDX));
|
File::CreateFullPath(File::GetUserPath(D_MAPS_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
|
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
|
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
|
||||||
|
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX) + ANAGLYPH_DIR DIR_SEP);
|
||||||
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
|
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_THEMES_IDX));
|
File::CreateFullPath(File::GetUserPath(D_THEMES_IDX));
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ void InitBackendInfo()
|
||||||
g_Config.backend_info.bSupportsOversizedViewports = false;
|
g_Config.backend_info.bSupportsOversizedViewports = false;
|
||||||
g_Config.backend_info.bSupportsGeometryShaders = true;
|
g_Config.backend_info.bSupportsGeometryShaders = true;
|
||||||
g_Config.backend_info.bSupports3DVision = true;
|
g_Config.backend_info.bSupports3DVision = true;
|
||||||
|
g_Config.backend_info.bSupportsPostProcessing = false;
|
||||||
|
|
||||||
IDXGIFactory* factory;
|
IDXGIFactory* factory;
|
||||||
IDXGIAdapter* ad;
|
IDXGIAdapter* ad;
|
||||||
|
@ -133,6 +134,7 @@ void InitBackendInfo()
|
||||||
|
|
||||||
// Clear ppshaders string vector
|
// Clear ppshaders string vector
|
||||||
g_Config.backend_info.PPShaders.clear();
|
g_Config.backend_info.PPShaders.clear();
|
||||||
|
g_Config.backend_info.AnaglyphShaders.clear();
|
||||||
|
|
||||||
DX11::D3D::UnloadDXGI();
|
DX11::D3D::UnloadDXGI();
|
||||||
DX11::D3D::UnloadD3D();
|
DX11::D3D::UnloadD3D();
|
||||||
|
|
|
@ -36,29 +36,8 @@ static const char s_vertex_shader[] =
|
||||||
" uv0 = rawpos * src_rect.zw + src_rect.xy;\n"
|
" uv0 = rawpos * src_rect.zw + src_rect.xy;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// Anaglyph Red-Cyan shader based on Dubois algorithm
|
|
||||||
// Constants taken from the paper:
|
|
||||||
// "Conversion of a Stereo Pair to Anaglyph with
|
|
||||||
// the Least-Squares Projection Method"
|
|
||||||
// Eric Dubois, March 2009
|
|
||||||
static const char s_anaglyph_shader[] =
|
|
||||||
"void main() {\n"
|
|
||||||
" vec4 c0 = SampleLayer(0);\n"
|
|
||||||
" vec4 c1 = SampleLayer(1);\n"
|
|
||||||
" mat3 l = mat3( 0.437, 0.449, 0.164,\n"
|
|
||||||
" -0.062,-0.062,-0.024,\n"
|
|
||||||
" -0.048,-0.050,-0.017);\n"
|
|
||||||
" mat3 r = mat3(-0.011,-0.032,-0.007,\n"
|
|
||||||
" 0.377, 0.761, 0.009,\n"
|
|
||||||
" -0.026,-0.093, 1.234);\n"
|
|
||||||
" SetOutput(vec4(c0.rgb * l + c1.rgb * r, c0.a));\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
static const char s_default_shader[] = "void main() { SetOutput(Sample()); }\n";
|
|
||||||
|
|
||||||
OpenGLPostProcessing::OpenGLPostProcessing()
|
OpenGLPostProcessing::OpenGLPostProcessing()
|
||||||
: m_initialized(false)
|
: m_initialized(false)
|
||||||
, m_anaglyph(false)
|
|
||||||
{
|
{
|
||||||
CreateHeader();
|
CreateHeader();
|
||||||
|
|
||||||
|
@ -183,23 +162,14 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle
|
||||||
void OpenGLPostProcessing::ApplyShader()
|
void OpenGLPostProcessing::ApplyShader()
|
||||||
{
|
{
|
||||||
// shader didn't changed
|
// shader didn't changed
|
||||||
if (m_initialized && m_config.GetShader() == g_ActiveConfig.sPostProcessingShader &&
|
if (m_initialized && m_config.GetShader() == g_ActiveConfig.sPostProcessingShader)
|
||||||
((g_ActiveConfig.iStereoMode == STEREO_ANAGLYPH) == m_anaglyph))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_shader.Destroy();
|
m_shader.Destroy();
|
||||||
m_uniform_bindings.clear();
|
m_uniform_bindings.clear();
|
||||||
|
|
||||||
// load shader code
|
// load shader code
|
||||||
std::string code = "";
|
std::string code = m_config.LoadShader();
|
||||||
if (g_ActiveConfig.iStereoMode == STEREO_ANAGLYPH)
|
|
||||||
code = s_anaglyph_shader;
|
|
||||||
else if (g_ActiveConfig.sPostProcessingShader != "")
|
|
||||||
code = m_config.LoadShader();
|
|
||||||
|
|
||||||
if (code == "")
|
|
||||||
code = s_default_shader;
|
|
||||||
|
|
||||||
code = LoadShaderOptions(code);
|
code = LoadShaderOptions(code);
|
||||||
|
|
||||||
const char* vertex_shader = s_vertex_shader;
|
const char* vertex_shader = s_vertex_shader;
|
||||||
|
@ -211,8 +181,8 @@ void OpenGLPostProcessing::ApplyShader()
|
||||||
if (!ProgramShaderCache::CompileShader(m_shader, vertex_shader, code.c_str()))
|
if (!ProgramShaderCache::CompileShader(m_shader, vertex_shader, code.c_str()))
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str());
|
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str());
|
||||||
|
g_ActiveConfig.sPostProcessingShader.clear();
|
||||||
code = LoadShaderOptions(s_default_shader);
|
code = m_config.LoadShader();
|
||||||
ProgramShaderCache::CompileShader(m_shader, vertex_shader, code.c_str());
|
ProgramShaderCache::CompileShader(m_shader, vertex_shader, code.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +214,6 @@ void OpenGLPostProcessing::ApplyShader()
|
||||||
std::string glsl_name = "option_" + it.first;
|
std::string glsl_name = "option_" + it.first;
|
||||||
m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str());
|
m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str());
|
||||||
}
|
}
|
||||||
m_anaglyph = g_ActiveConfig.iStereoMode == STEREO_ANAGLYPH;
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
bool m_anaglyph;
|
|
||||||
SHADER m_shader;
|
SHADER m_shader;
|
||||||
GLuint m_uniform_resolution;
|
GLuint m_uniform_resolution;
|
||||||
GLuint m_uniform_src_rect;
|
GLuint m_uniform_src_rect;
|
||||||
|
|
|
@ -95,14 +95,14 @@ std::string VideoBackend::GetDisplayName() const
|
||||||
return "OpenGL";
|
return "OpenGL";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetShaders(std::vector<std::string> &shaders)
|
static void GetShaders(std::vector<std::string> &shaders, const std::string &sub_dir = "")
|
||||||
{
|
{
|
||||||
std::set<std::string> already_found;
|
std::set<std::string> already_found;
|
||||||
|
|
||||||
shaders.clear();
|
shaders.clear();
|
||||||
static const std::string directories[] = {
|
const std::string directories[] = {
|
||||||
File::GetUserPath(D_SHADERS_IDX),
|
File::GetUserPath(D_SHADERS_IDX) + sub_dir,
|
||||||
File::GetSysDirectory() + SHADERS_DIR DIR_SEP,
|
File::GetSysDirectory() + SHADERS_DIR DIR_SEP + sub_dir,
|
||||||
};
|
};
|
||||||
for (auto& directory : directories)
|
for (auto& directory : directories)
|
||||||
{
|
{
|
||||||
|
@ -139,6 +139,7 @@ static void InitBackendInfo()
|
||||||
g_Config.backend_info.bSupportsOversizedViewports = true;
|
g_Config.backend_info.bSupportsOversizedViewports = true;
|
||||||
g_Config.backend_info.bSupportsGeometryShaders = true;
|
g_Config.backend_info.bSupportsGeometryShaders = true;
|
||||||
g_Config.backend_info.bSupports3DVision = false;
|
g_Config.backend_info.bSupports3DVision = false;
|
||||||
|
g_Config.backend_info.bSupportsPostProcessing = true;
|
||||||
|
|
||||||
g_Config.backend_info.Adapters.clear();
|
g_Config.backend_info.Adapters.clear();
|
||||||
|
|
||||||
|
@ -148,6 +149,7 @@ static void InitBackendInfo()
|
||||||
|
|
||||||
// pp shaders
|
// pp shaders
|
||||||
GetShaders(g_Config.backend_info.PPShaders);
|
GetShaders(g_Config.backend_info.PPShaders);
|
||||||
|
GetShaders(g_Config.backend_info.AnaglyphShaders, std::string(ANAGLYPH_DIR DIR_SEP));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackend::ShowConfig(void *_hParent)
|
void VideoBackend::ShowConfig(void *_hParent)
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char s_default_shader[] = "void main() { SetOutput(Sample()); }\n";
|
||||||
|
|
||||||
PostProcessingShaderImplementation::PostProcessingShaderImplementation()
|
PostProcessingShaderImplementation::PostProcessingShaderImplementation()
|
||||||
{
|
{
|
||||||
m_timer.Start();
|
m_timer.Start();
|
||||||
|
@ -30,20 +32,29 @@ std::string PostProcessingShaderConfiguration::LoadShader(std::string shader)
|
||||||
shader = g_ActiveConfig.sPostProcessingShader;
|
shader = g_ActiveConfig.sPostProcessingShader;
|
||||||
m_current_shader = shader;
|
m_current_shader = shader;
|
||||||
|
|
||||||
|
const std::string sub_dir = (g_Config.iStereoMode == STEREO_ANAGLYPH) ? ANAGLYPH_DIR DIR_SEP : "";
|
||||||
|
|
||||||
// loading shader code
|
// loading shader code
|
||||||
std::string code;
|
std::string code;
|
||||||
std::string path = File::GetUserPath(D_SHADERS_IDX) + shader + ".glsl";
|
std::string path = File::GetUserPath(D_SHADERS_IDX) + sub_dir + shader + ".glsl";
|
||||||
|
|
||||||
|
if (shader == "")
|
||||||
|
{
|
||||||
|
code = s_default_shader;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (!File::Exists(path))
|
if (!File::Exists(path))
|
||||||
{
|
{
|
||||||
// Fallback to shared user dir
|
// Fallback to shared user dir
|
||||||
path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + shader + ".glsl";
|
path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + sub_dir + shader + ".glsl";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!File::ReadFileToString(path, code))
|
if (!File::ReadFileToString(path, code))
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str());
|
ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str());
|
||||||
return "";
|
code = s_default_shader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadOptions(code);
|
LoadOptions(code);
|
||||||
|
|
|
@ -147,6 +147,7 @@ struct VideoConfig final
|
||||||
std::vector<std::string> Adapters; // for D3D
|
std::vector<std::string> Adapters; // for D3D
|
||||||
std::vector<std::string> AAModes;
|
std::vector<std::string> AAModes;
|
||||||
std::vector<std::string> PPShaders; // post-processing shaders
|
std::vector<std::string> PPShaders; // post-processing shaders
|
||||||
|
std::vector<std::string> AnaglyphShaders; // anaglyph shaders
|
||||||
|
|
||||||
bool bSupportsExclusiveFullscreen;
|
bool bSupportsExclusiveFullscreen;
|
||||||
bool bSupportsDualSourceBlend;
|
bool bSupportsDualSourceBlend;
|
||||||
|
@ -158,6 +159,7 @@ struct VideoConfig final
|
||||||
bool bSupportsBindingLayout; // Needed by ShaderGen, so must stay in VideoCommon
|
bool bSupportsBindingLayout; // Needed by ShaderGen, so must stay in VideoCommon
|
||||||
bool bSupportsBBox;
|
bool bSupportsBBox;
|
||||||
bool bSupportsGSInstancing; // Needed by GeometryShaderGen, so must stay in VideoCommon
|
bool bSupportsGSInstancing; // Needed by GeometryShaderGen, so must stay in VideoCommon
|
||||||
|
bool bSupportsPostProcessing;
|
||||||
} backend_info;
|
} backend_info;
|
||||||
|
|
||||||
// Utility
|
// Utility
|
||||||
|
|
Loading…
Reference in New Issue