From ee6d7cf17e41a153cf2969dd7ff39ac98dedab3b Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 3 Jul 2017 01:26:02 +0200 Subject: [PATCH] - Add initial postprocess shader support to GLDEFS file --- src/gl/renderer/gl_postprocess.cpp | 69 +++++++++++++++ src/gl/renderer/gl_renderer.h | 13 +++ src/gl/shaders/gl_shader.cpp | 131 ++++++++++++++++++----------- 3 files changed, 165 insertions(+), 48 deletions(-) diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 06ae5d86b..5fb40b2af 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -149,6 +149,14 @@ CUSTOM_CVAR(Bool, gl_paltonemap_reverselookup, true, CVAR_ARCHIVE | CVAR_NOINITC EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_contrast) +class PostProcessShaderInstance +{ +public: + FShaderProgram Program; + FBufferedUniformSampler InputTexture; + FBufferedUniformSampler CustomTexture; + FHardwareTexture *HWTexture = nullptr; +}; void FGLRenderer::RenderScreenQuad() { @@ -166,6 +174,67 @@ void FGLRenderer::PostProcessScene(int fixedcm) ColormapScene(fixedcm); LensDistortScene(); ApplyFXAA(); + RunCustomPostProcessShaders("screen"); +} + +void FGLRenderer::RunCustomPostProcessShaders(FString target) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + + if (shader.Target != target) + continue; + + if (!shader.Instance) + { + shader.Instance = std::make_shared(); + shader.Instance->Program.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); // Hmm, should this use shader.shaderversion? + shader.Instance->Program.Compile(FShaderProgram::Fragment, shader.ShaderLumpName.GetChars(), "", shader.ShaderVersion); + shader.Instance->Program.SetFragDataLocation(0, "FragColor"); + shader.Instance->Program.Link(shader.ShaderLumpName.GetChars()); + shader.Instance->Program.SetAttribLocation(0, "PositionInProjection"); + shader.Instance->InputTexture.Init(shader.Instance->Program, "InputTexture"); + shader.Instance->CustomTexture.Init(shader.Instance->Program, "CustomTexture"); + + if (shader.Texture) + shader.Instance->HWTexture = new FHardwareTexture(shader.Texture->GetWidth(), shader.Texture->GetHeight(), false); + } + + FGLDebug::PushGroup(shader.ShaderLumpName.GetChars()); + + FGLPostProcessState savedState; + savedState.SaveTextureBindings(2); + + mBuffers->BindNextFB(); + mBuffers->BindCurrentTexture(0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + shader.Instance->Program.Bind(); + + shader.Instance->InputTexture.Set(0); + + if (shader.Instance->HWTexture) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, shader.Instance->HWTexture->GetTextureHandle(0)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glActiveTexture(GL_TEXTURE0); + + shader.Instance->CustomTexture.Set(1); + } + RenderScreenQuad(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + mBuffers->NextTexture(); + + FGLDebug::PopGroup(); + } } //----------------------------------------------------------------------------- diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 63168ff24..ce4d749a7 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -42,6 +42,7 @@ class FPresent3DRowShader; class F2DDrawer; class FHardwareTexture; class FShadowMapShader; +class PostProcessShaderInstance; inline float DEG2RAD(float deg) { @@ -85,6 +86,17 @@ enum DM_SKYPORTAL }; +struct PostProcessShader +{ + FString Target; + FString ShaderLumpName; + int ShaderVersion = 0; + FTexture *Texture = nullptr; + std::shared_ptr Instance; +}; + +extern TArray PostProcessShaders; + class FGLRenderer { public: @@ -171,6 +183,7 @@ public: void RenderScreenQuad(); void PostProcessScene(int fixedcm); + void RunCustomPostProcessShaders(FString target); void AmbientOccludeScene(); void UpdateCameraExposure(); void BloomScene(int fixedcm); diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 2fdf9fbf3..022cec7d9 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -669,63 +669,98 @@ void gl_DestroyUserShaders() // //========================================================================== +TArray PostProcessShaders; + void gl_ParseHardwareShader(FScanner &sc, int deflump) { - int type = FTexture::TEX_Any; - bool disable_fullbright=false; - bool thiswad = false; - bool iwad = false; - int maplump = -1; - FString maplumpname; - float speed = 1.f; - sc.MustGetString(); - if (sc.Compare("texture")) type = FTexture::TEX_Wall; - else if (sc.Compare("flat")) type = FTexture::TEX_Flat; - else if (sc.Compare("sprite")) type = FTexture::TEX_Sprite; - else sc.UnGet(); - - sc.MustGetString(); - FTextureID no = TexMan.CheckForTexture(sc.String, type); - FTexture *tex = TexMan[no]; - - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) + if (sc.Compare("postprocess")) { sc.MustGetString(); - if (sc.Compare("shader")) + + PostProcessShader shaderdesc; + shaderdesc.Target = sc.String; + + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) { sc.MustGetString(); - maplumpname = sc.String; - } - else if (sc.Compare("speed")) - { - sc.MustGetFloat(); - speed = float(sc.Float); - } - } - if (!tex) - { - return; - } - - if (maplumpname.IsNotEmpty()) - { - if (tex->bWarped != 0) - { - Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->Name.GetChars()); - return; - } - tex->gl_info.shaderspeed = speed; - for(unsigned i=0;igl_info.shaderindex = i + FIRST_USER_SHADER; - return; + sc.MustGetString(); + shaderdesc.ShaderLumpName = sc.String; + + sc.MustGetNumber(); + shaderdesc.ShaderVersion = sc.Number; + } + else if (sc.Compare("texture")) + { + sc.MustGetString(); + FTextureID no = TexMan.CheckForTexture(sc.String, FTexture::TEX_Wall); + shaderdesc.Texture = TexMan[no]; } } - tex->gl_info.shaderindex = usershaders.Push(maplumpname) + FIRST_USER_SHADER; - } + + PostProcessShaders.Push(shaderdesc); + } + else + { + int type = FTexture::TEX_Any; + + if (sc.Compare("texture")) type = FTexture::TEX_Wall; + else if (sc.Compare("flat")) type = FTexture::TEX_Flat; + else if (sc.Compare("sprite")) type = FTexture::TEX_Sprite; + else sc.UnGet(); + + bool disable_fullbright = false; + bool thiswad = false; + bool iwad = false; + int maplump = -1; + FString maplumpname; + float speed = 1.f; + + sc.MustGetString(); + FTextureID no = TexMan.CheckForTexture(sc.String, type); + FTexture *tex = TexMan[no]; + + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("shader")) + { + sc.MustGetString(); + maplumpname = sc.String; + } + else if (sc.Compare("speed")) + { + sc.MustGetFloat(); + speed = float(sc.Float); + } + } + if (!tex) + { + return; + } + + if (maplumpname.IsNotEmpty()) + { + if (tex->bWarped != 0) + { + Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->Name.GetChars()); + return; + } + tex->gl_info.shaderspeed = speed; + for (unsigned i = 0; i < usershaders.Size(); i++) + { + if (!usershaders[i].CompareNoCase(maplumpname)) + { + tex->gl_info.shaderindex = i + FIRST_USER_SHADER; + return; + } + } + tex->gl_info.shaderindex = usershaders.Push(maplumpname) + FIRST_USER_SHADER; + } + } }