reimplement postprocessing and fix one shader as example

This commit is contained in:
degasus 2013-03-07 17:00:11 +01:00
parent 5dd502df3b
commit 800a58f01c
5 changed files with 140 additions and 60 deletions

View File

@ -1,7 +1,9 @@
uniform samplerRECT samp0 : register(s0); uniform sampler2D samp9;
void main(out float4 ocol0 : COLOR0, in float2 uv0 : TEXCOORD0) out vec4 ocol0;
in vec2 uv0;
void main()
{ {
float4 c0 = texRECT(samp0, uv0).rgba; ocol0 = vec4(1.0, 1.0, 1.0, 1.0) - texture(samp9, uv0);
ocol0 = float4(1.0, 1.0, 1.0, 1.0) - c0;
} }

View File

@ -21,6 +21,7 @@
#include "GLUtil.h" #include "GLUtil.h"
#include "PostProcessing.h" #include "PostProcessing.h"
#include "ProgramShaderCache.h" #include "ProgramShaderCache.h"
#include "FramebufferManager.h"
namespace OGL namespace OGL
{ {
@ -30,15 +31,67 @@ namespace PostProcessing
static std::string s_currentShader; static std::string s_currentShader;
static SHADER s_shader; static SHADER s_shader;
static bool s_enable;
static u32 s_width;
static u32 s_height;
static GLuint s_fbo;
static GLuint s_texture;
static GLuint s_vao;
static GLuint s_vbo;
static char* s_vertex_shader =
"in vec2 rawpos;\n"
"in vec2 tex0;\n"
"out vec2 uv0;\n"
"void main(void) {\n"
" gl_Position = vec4(rawpos,0,1);\n"
" uv0 = tex0;\n"
"}\n";
void Init() void Init()
{ {
s_currentShader = ""; s_currentShader = "";
s_enable = 0;
s_width = 0;
s_height = 0;
glGenFramebuffers(1, &s_fbo);
glGenTextures(1, &s_texture);
glBindTexture(GL_TEXTURE_2D, s_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s_texture, 0);
FramebufferManager::SetFramebuffer(0);
glGenBuffers(1, &s_vbo);
glBindBuffer(GL_ARRAY_BUFFER, s_vbo);
GLfloat vertices[] = {
-1.f, -1.f, 0.f, 0.f,
-1.f, 1.f, 0.f, 1.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &s_vao);
glBindVertexArray( s_vao );
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
} }
void Shutdown() void Shutdown()
{ {
s_shader.Destroy(); s_shader.Destroy();
glDeleteFramebuffers(1, &s_vbo);
glDeleteTextures(1, &s_texture);
glDeleteBuffers(1, &s_vbo);
glDeleteVertexArrays(1, &s_vao);
} }
void ReloadShader() void ReloadShader()
@ -46,45 +99,77 @@ void ReloadShader()
s_currentShader = ""; s_currentShader = "";
} }
bool ApplyShader() void BindTargetFramebuffer ()
{ {
if (s_currentShader != File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt") glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_enable ? s_fbo : 0);
{ }
// Set immediately to prevent endless recompiles on failure.
if (!g_ActiveConfig.sPostProcessingShader.empty())
s_currentShader = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
else
s_currentShader.clear();
s_shader.Destroy(); void BlitToScreen()
{
if(!s_enable) return;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, s_width, s_height);
glBindVertexArray(s_vao);
s_shader.Bind();
glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, s_texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
/* glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo);
glBlitFramebuffer(rc.left, rc.bottom, rc.right, rc.top,
rc.left, rc.bottom, rc.right, rc.top,
GL_COLOR_BUFFER_BIT, GL_NEAREST);*/
}
if (!s_currentShader.empty()) void Update ( u32 width, u32 height )
{ {
std::string code; ApplyShader();
if (File::ReadFileToString(true, s_currentShader.c_str(), code))
{
//if (!ProgramShaderCache::CompileShader(s_shader, "#version130\n...", code.c_str()))
//{
// ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
//}
}
else
{
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
}
}
}
// TODO: Convert PP shaders to GLSL if(s_enable && (width != s_width || height != s_height)) {
if (s_shader.glprogid != 0) s_width = width;
{ s_height = height;
s_shader.Bind();
return true; // alloc texture for framebuffer
glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, s_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
} }
else }
{
return false; void ApplyShader()
{
// shader didn't changed
if (s_currentShader == g_ActiveConfig.sPostProcessingShader) return;
s_currentShader = g_ActiveConfig.sPostProcessingShader;
s_enable = false;
s_shader.Destroy();
// shader disabled
if (g_ActiveConfig.sPostProcessingShader == "") return;
// so need to compile shader
// loading shader code
std::string code;
std::string path = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
if(!File::ReadFileToString(true, path.c_str(), code)) {
ERROR_LOG(VIDEO, "post-processing shader not found: %s", path.c_str());
return;
} }
// and compile it
if (!ProgramShaderCache::CompileShader(s_shader, s_vertex_shader, code.c_str())) {
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
return;
}
// successful
s_enable = true;
} }
} // namespace } // namespace

View File

@ -30,9 +30,13 @@ namespace PostProcessing
void Init(); void Init();
void Shutdown(); void Shutdown();
void BindTargetFramebuffer();
void BlitToScreen();
void Update(u32 width, u32 height);
void ReloadShader(); void ReloadShader();
// Returns false if no shader was applied.
bool ApplyShader(); void ApplyShader();
} // namespace } // namespace

View File

@ -996,6 +996,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
ResetAPIState(); ResetAPIState();
PostProcessing::Update(s_backbuffer_width, s_backbuffer_height);
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
TargetRectangle flipped_trc = GetTargetRectangle(); TargetRectangle flipped_trc = GetTargetRectangle();
@ -1003,31 +1004,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
int tmp = flipped_trc.top; int tmp = flipped_trc.top;
flipped_trc.top = flipped_trc.bottom; flipped_trc.top = flipped_trc.bottom;
flipped_trc.bottom = tmp; flipped_trc.bottom = tmp;
// Textured triangles are necessary because of post-processing shaders
// Disable all other stages
for (int i = 0; i < 8; ++i)
OGL::TextureCache::DisableStage(i);
// Update GLViewPort
glViewport(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), flipped_trc.GetHeight());
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// We must call ApplyShader here even if no post proc is selected - it takes
// care of disabling it in that case. It returns false in case of no post processing.
//bool applyShader = PostProcessing::ApplyShader();
// degasus: disabled for blitting
// Copy the framebuffer to screen. // Copy the framebuffer to screen.
const XFBSourceBase* xfbSource = NULL; const XFBSourceBase* xfbSource = NULL;
if(g_ActiveConfig.bUseXFB) if(g_ActiveConfig.bUseXFB)
{ {
// Render to the real buffer now. // Render to the real/postprocessing buffer now.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // switch to the window backbuffer PostProcessing::BindTargetFramebuffer();
// draw each xfb source // draw each xfb source
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer()); glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
@ -1085,8 +1072,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// for msaa mode, we must resolve the efb content to non-msaa // for msaa mode, we must resolve the efb content to non-msaa
FramebufferManager::ResolveAndGetRenderTarget(rc); FramebufferManager::ResolveAndGetRenderTarget(rc);
// Render to the real buffer now. (resolve have changed this in msaa mode) // Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); PostProcessing::BindTargetFramebuffer();
// always the non-msaa fbo // always the non-msaa fbo
GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer(); GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer();
@ -1096,6 +1083,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
flipped_trc.left, flipped_trc.bottom, flipped_trc.right, flipped_trc.top, flipped_trc.left, flipped_trc.bottom, flipped_trc.right, flipped_trc.top,
GL_COLOR_BUFFER_BIT, GL_LINEAR); GL_COLOR_BUFFER_BIT, GL_LINEAR);
} }
PostProcessing::BlitToScreen();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

View File

@ -199,9 +199,9 @@ void VideoBackend::Video_Prepare()
VertexShaderManager::Init(); VertexShaderManager::Init();
PixelShaderManager::Init(); PixelShaderManager::Init();
ProgramShaderCache::Init(); ProgramShaderCache::Init();
PostProcessing::Init();
g_texture_cache = new TextureCache(); g_texture_cache = new TextureCache();
g_sampler_cache = new SamplerCache(); g_sampler_cache = new SamplerCache();
PostProcessing::Init();
Renderer::Init(); Renderer::Init();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
VertexLoaderManager::Init(); VertexLoaderManager::Init();
@ -231,7 +231,6 @@ void VideoBackend::Video_Cleanup() {
DLCache::Shutdown(); DLCache::Shutdown();
#endif #endif
Fifo_Shutdown(); Fifo_Shutdown();
PostProcessing::Shutdown();
// The following calls are NOT Thread Safe // The following calls are NOT Thread Safe
// And need to be called from the video thread // And need to be called from the video thread
@ -242,6 +241,7 @@ void VideoBackend::Video_Cleanup() {
g_sampler_cache = NULL; g_sampler_cache = NULL;
delete g_texture_cache; delete g_texture_cache;
g_texture_cache = NULL; g_texture_cache = NULL;
PostProcessing::Shutdown();
ProgramShaderCache::Shutdown(); ProgramShaderCache::Shutdown();
VertexShaderManager::Shutdown(); VertexShaderManager::Shutdown();
PixelShaderManager::Shutdown(); PixelShaderManager::Shutdown();