- Support binding textures for custom PP shaders

This commit is contained in:
Magnus Norddahl 2017-07-30 13:59:25 +02:00
parent 6a5bad0beb
commit d5733f515c
3 changed files with 78 additions and 0 deletions

View file

@ -34,6 +34,8 @@
#include "gl/renderer/gl_postprocessstate.h" #include "gl/renderer/gl_postprocessstate.h"
#include "gl/renderer/gl_renderbuffers.h" #include "gl/renderer/gl_renderbuffers.h"
#include "gl/shaders/gl_postprocessshader.h" #include "gl/shaders/gl_postprocessshader.h"
#include "textures/textures.h"
#include "textures/bitmap.h"
CVAR(Bool, gl_custompost, true, 0) 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() void PostProcessShaderInstance::Run()
{ {
if (!IsShaderSupported()) if (!IsShaderSupported())
@ -80,6 +88,7 @@ void PostProcessShaderInstance::Run()
FGLDebug::PushGroup(Desc->ShaderLumpName.GetChars()); FGLDebug::PushGroup(Desc->ShaderLumpName.GetChars());
FGLPostProcessState savedState; FGLPostProcessState savedState;
savedState.SaveTextureBindings(1 + Desc->Textures.CountUsed());
GLRenderer->mBuffers->BindNextFB(); GLRenderer->mBuffers->BindNextFB();
GLRenderer->mBuffers->BindCurrentTexture(0); GLRenderer->mBuffers->BindCurrentTexture(0);
@ -89,11 +98,13 @@ void PostProcessShaderInstance::Run()
mProgram.Bind(); mProgram.Bind();
UpdateUniforms(); UpdateUniforms();
BindTextures();
mInputTexture.Set(0); mInputTexture.Set(0);
GLRenderer->RenderScreenQuad(); GLRenderer->RenderScreenQuad();
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
GLRenderer->mBuffers->NextTexture(); GLRenderer->mBuffers->NextTexture();
@ -145,6 +156,13 @@ void PostProcessShaderInstance::CompileShader()
FString uniformTextures; FString uniformTextures;
uniformTextures += "uniform sampler2D InputTexture;\n"; uniformTextures += "uniform sampler2D InputTexture;\n";
TMap<FString, FString>::Iterator itTextures(Desc->Textures);
TMap<FString, FString>::Pair *pairTextures;
while (itTextures.NextPair(pairTextures))
{
uniformTextures.AppendFormat("uniform sampler2D %s;\n", pairTextures->Key.GetChars());
}
// Setup pipeline // Setup pipeline
FString pipelineInOut; FString pipelineInOut;
pipelineInOut += "in vec2 TexCoord;\n"; pipelineInOut += "in vec2 TexCoord;\n";
@ -191,4 +209,49 @@ void PostProcessShaderInstance::UpdateUniforms()
} }
} }
} }
glUniform1i(glGetUniformLocation(mProgram, "SillyTexture"), 1);
}
void PostProcessShaderInstance::BindTextures()
{
int textureUnit = 1;
TMap<FString, FString>::Iterator it(Desc->Textures);
TMap<FString, FString>::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++;
}
}
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "gl_shaderprogram.h" #include "gl_shaderprogram.h"
#include <map>
class PostProcessShaderInstance; class PostProcessShaderInstance;
@ -29,6 +30,7 @@ struct PostProcessShader
bool Enabled = false; bool Enabled = false;
TMap<FString, PostProcessUniformValue> Uniforms; TMap<FString, PostProcessUniformValue> Uniforms;
TMap<FString, FString> Textures;
}; };
extern TArray<PostProcessShader> PostProcessShaders; extern TArray<PostProcessShader> PostProcessShaders;
@ -37,6 +39,7 @@ class PostProcessShaderInstance
{ {
public: public:
PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { } PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { }
~PostProcessShaderInstance();
void Run(); void Run();
@ -46,9 +49,11 @@ private:
bool IsShaderSupported(); bool IsShaderSupported();
void CompileShader(); void CompileShader();
void UpdateUniforms(); void UpdateUniforms();
void BindTextures();
FShaderProgram mProgram; FShaderProgram mProgram;
FBufferedUniformSampler mInputTexture; FBufferedUniformSampler mInputTexture;
std::map<FTexture*, int> mTextureHandles;
}; };
class FCustomPostProcessShaders class FCustomPostProcessShaders

View file

@ -734,6 +734,16 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump)
if (parsedType != PostProcessUniformType::Undefined) if (parsedType != PostProcessUniformType::Undefined)
shaderdesc.Uniforms[uniformName].Type = parsedType; 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")) else if (sc.Compare("enabled"))
{ {
shaderdesc.Enabled = true; shaderdesc.Enabled = true;