From d5733f515c52119e37e67d36e1d165f98263a38d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 30 Jul 2017 13:59:25 +0200 Subject: [PATCH] - Support binding textures for custom PP shaders --- src/gl/shaders/gl_postprocessshader.cpp | 63 +++++++++++++++++++++++++ src/gl/shaders/gl_postprocessshader.h | 5 ++ src/gl/shaders/gl_shader.cpp | 10 ++++ 3 files changed, 78 insertions(+) diff --git a/src/gl/shaders/gl_postprocessshader.cpp b/src/gl/shaders/gl_postprocessshader.cpp index 0baf06531..b8011083a 100644 --- a/src/gl/shaders/gl_postprocessshader.cpp +++ b/src/gl/shaders/gl_postprocessshader.cpp @@ -34,6 +34,8 @@ #include "gl/renderer/gl_postprocessstate.h" #include "gl/renderer/gl_renderbuffers.h" #include "gl/shaders/gl_postprocessshader.h" +#include "textures/textures.h" +#include "textures/bitmap.h" CVAR(Bool, gl_custompost, true, 0) @@ -67,6 +69,12 @@ void FCustomPostProcessShaders::Run(FString target) ///////////////////////////////////////////////////////////////////////////// +PostProcessShaderInstance::~PostProcessShaderInstance() +{ + for (const auto &it : mTextureHandles) + glDeleteTextures(1, (GLuint*)&it.second); +} + void PostProcessShaderInstance::Run() { if (!IsShaderSupported()) @@ -80,6 +88,7 @@ void PostProcessShaderInstance::Run() FGLDebug::PushGroup(Desc->ShaderLumpName.GetChars()); FGLPostProcessState savedState; + savedState.SaveTextureBindings(1 + Desc->Textures.CountUsed()); GLRenderer->mBuffers->BindNextFB(); GLRenderer->mBuffers->BindCurrentTexture(0); @@ -89,11 +98,13 @@ void PostProcessShaderInstance::Run() mProgram.Bind(); UpdateUniforms(); + BindTextures(); mInputTexture.Set(0); GLRenderer->RenderScreenQuad(); + glActiveTexture(GL_TEXTURE0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLRenderer->mBuffers->NextTexture(); @@ -145,6 +156,13 @@ void PostProcessShaderInstance::CompileShader() FString uniformTextures; uniformTextures += "uniform sampler2D InputTexture;\n"; + TMap::Iterator itTextures(Desc->Textures); + TMap::Pair *pairTextures; + while (itTextures.NextPair(pairTextures)) + { + uniformTextures.AppendFormat("uniform sampler2D %s;\n", pairTextures->Key.GetChars()); + } + // Setup pipeline FString pipelineInOut; pipelineInOut += "in vec2 TexCoord;\n"; @@ -191,4 +209,49 @@ void PostProcessShaderInstance::UpdateUniforms() } } } + + glUniform1i(glGetUniformLocation(mProgram, "SillyTexture"), 1); +} + +void PostProcessShaderInstance::BindTextures() +{ + int textureUnit = 1; + TMap::Iterator it(Desc->Textures); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + int location = glGetUniformLocation(mProgram, pair->Key.GetChars()); + if (location == -1) + continue; + + FString name = pair->Value; + FTexture *tex = TexMan(TexMan.CheckForTexture(name, FTexture::TEX_Any)); + if (tex && tex->UseType != FTexture::TEX_Null) + { + glUniform1i(location, textureUnit); + + glActiveTexture(GL_TEXTURE0 + 1); + auto it = mTextureHandles.find(tex); + if (it == mTextureHandles.end()) + { + FBitmap bitmap; + bitmap.Create(tex->GetWidth(), tex->GetHeight()); + tex->CopyTrueColorPixels(&bitmap, 0, 0); + + GLuint handle = 0; + glGenTextures(1, &handle); + glBindTexture(GL_TEXTURE_2D, handle); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex->GetWidth(), tex->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.GetPixels()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + mTextureHandles[tex] = handle; + } + else + { + glBindTexture(GL_TEXTURE_2D, it->second); + } + + textureUnit++; + } + } } diff --git a/src/gl/shaders/gl_postprocessshader.h b/src/gl/shaders/gl_postprocessshader.h index 876cb9f56..23b8c1864 100644 --- a/src/gl/shaders/gl_postprocessshader.h +++ b/src/gl/shaders/gl_postprocessshader.h @@ -1,6 +1,7 @@ #pragma once #include "gl_shaderprogram.h" +#include class PostProcessShaderInstance; @@ -29,6 +30,7 @@ struct PostProcessShader bool Enabled = false; TMap Uniforms; + TMap Textures; }; extern TArray PostProcessShaders; @@ -37,6 +39,7 @@ class PostProcessShaderInstance { public: PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { } + ~PostProcessShaderInstance(); void Run(); @@ -46,9 +49,11 @@ private: bool IsShaderSupported(); void CompileShader(); void UpdateUniforms(); + void BindTextures(); FShaderProgram mProgram; FBufferedUniformSampler mInputTexture; + std::map mTextureHandles; }; class FCustomPostProcessShaders diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index c508fd301..41b6c18a1 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -734,6 +734,16 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump) if (parsedType != PostProcessUniformType::Undefined) shaderdesc.Uniforms[uniformName].Type = parsedType; } + else if (sc.Compare("texture")) + { + sc.MustGetString(); + FString textureName = sc.String; + + sc.MustGetString(); + FString textureSource = sc.String; + + shaderdesc.Textures[textureName] = textureSource; + } else if (sc.Compare("enabled")) { shaderdesc.Enabled = true;