mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 04:22:34 +00:00
Merge branch 'custom_postprocess' into qzdoom
This commit is contained in:
commit
00893763ed
4 changed files with 262 additions and 71 deletions
|
@ -69,72 +69,29 @@ void FCustomPostProcessShaders::Run(FString target)
|
|||
|
||||
void PostProcessShaderInstance::Run()
|
||||
{
|
||||
if (!Program)
|
||||
{
|
||||
const char *lumpName = Desc->ShaderLumpName.GetChars();
|
||||
int lump = Wads.CheckNumForFullName(lumpName);
|
||||
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName);
|
||||
FString code = Wads.ReadLump(lump).GetString().GetChars();
|
||||
if (!IsShaderSupported())
|
||||
return;
|
||||
|
||||
Program.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); // Hmm, should this use shader.shaderversion?
|
||||
Program.Compile(FShaderProgram::Fragment, lumpName, code, "", Desc->ShaderVersion);
|
||||
Program.SetFragDataLocation(0, "FragColor");
|
||||
Program.Link(Desc->ShaderLumpName.GetChars());
|
||||
Program.SetAttribLocation(0, "PositionInProjection");
|
||||
InputTexture.Init(Program, "InputTexture");
|
||||
CustomTexture.Init(Program, "CustomTexture");
|
||||
CompileShader();
|
||||
|
||||
if (Desc->Texture)
|
||||
{
|
||||
HWTexture = new FHardwareTexture(Desc->Texture->GetWidth(), Desc->Texture->GetHeight(), false);
|
||||
HWTexture->CreateTexture((unsigned char*)Desc->Texture->GetPixelsBgra(), Desc->Texture->GetWidth(), Desc->Texture->GetHeight(), 0, false, 0, "CustomTexture");
|
||||
}
|
||||
}
|
||||
if (!Desc->Enabled)
|
||||
return;
|
||||
|
||||
FGLDebug::PushGroup(Desc->ShaderLumpName.GetChars());
|
||||
|
||||
FGLPostProcessState savedState;
|
||||
savedState.SaveTextureBindings(2);
|
||||
|
||||
GLRenderer->mBuffers->BindNextFB();
|
||||
GLRenderer->mBuffers->BindCurrentTexture(0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
Program.Bind();
|
||||
mProgram.Bind();
|
||||
|
||||
TMap<FString, float>::Iterator it1f(Desc->Uniform1f);
|
||||
TMap<FString, float>::Pair *pair1f;
|
||||
while (it1f.NextPair(pair1f))
|
||||
{
|
||||
int location = glGetUniformLocation(Program, pair1f->Key.GetChars());
|
||||
if (location != -1)
|
||||
glUniform1f(location, pair1f->Value);
|
||||
}
|
||||
UpdateUniforms();
|
||||
|
||||
TMap<FString, int>::Iterator it1i(Desc->Uniform1i);
|
||||
TMap<FString, int>::Pair *pair1i;
|
||||
while (it1i.NextPair(pair1i))
|
||||
{
|
||||
int location = glGetUniformLocation(Program, pair1i->Key.GetChars());
|
||||
if (location != -1)
|
||||
glUniform1i(location, pair1i->Value);
|
||||
}
|
||||
mInputTexture.Set(0);
|
||||
|
||||
InputTexture.Set(0);
|
||||
|
||||
if (HWTexture)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 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);
|
||||
|
||||
CustomTexture.Set(1);
|
||||
}
|
||||
GLRenderer->RenderScreenQuad();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
@ -143,3 +100,95 @@ void PostProcessShaderInstance::Run()
|
|||
|
||||
FGLDebug::PopGroup();
|
||||
}
|
||||
|
||||
bool PostProcessShaderInstance::IsShaderSupported()
|
||||
{
|
||||
int activeShaderVersion = (int)round(gl.glslversion * 10) * 10;
|
||||
return activeShaderVersion >= Desc->ShaderVersion;
|
||||
}
|
||||
|
||||
void PostProcessShaderInstance::CompileShader()
|
||||
{
|
||||
if (mProgram)
|
||||
return;
|
||||
|
||||
// Get the custom shader
|
||||
const char *lumpName = Desc->ShaderLumpName.GetChars();
|
||||
int lump = Wads.CheckNumForFullName(lumpName);
|
||||
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName);
|
||||
FString code = Wads.ReadLump(lump).GetString().GetChars();
|
||||
|
||||
// Build an uniform block to use be used as input
|
||||
// (this is technically not an uniform block, but it could be changed into that for Vulkan GLSL support)
|
||||
FString uniformBlock;
|
||||
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
||||
TMap<FString, PostProcessUniformValue>::Pair *pair;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
FString type;
|
||||
FString name = pair->Key;
|
||||
|
||||
switch (pair->Value.Type)
|
||||
{
|
||||
case PostProcessUniformType::Float: type = "float"; break;
|
||||
case PostProcessUniformType::Int: type = "int"; break;
|
||||
case PostProcessUniformType::Vec2: type = "vec2"; break;
|
||||
case PostProcessUniformType::Vec3: type = "vec3"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (!type.IsEmpty())
|
||||
uniformBlock.AppendFormat("uniform %s %s;\n", type.GetChars(), name.GetChars());
|
||||
}
|
||||
|
||||
// Build the input textures
|
||||
FString uniformTextures;
|
||||
uniformTextures += "uniform sampler2D InputTexture;\n";
|
||||
|
||||
// Setup pipeline
|
||||
FString pipelineInOut;
|
||||
pipelineInOut += "in vec2 TexCoord;\n";
|
||||
pipelineInOut += "out vec4 FragColor;\n";
|
||||
|
||||
FString prolog;
|
||||
prolog += uniformBlock;
|
||||
prolog += uniformTextures;
|
||||
prolog += pipelineInOut;
|
||||
|
||||
mProgram.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", Desc->ShaderVersion);
|
||||
mProgram.Compile(FShaderProgram::Fragment, lumpName, code, prolog.GetChars(), Desc->ShaderVersion);
|
||||
mProgram.SetFragDataLocation(0, "FragColor");
|
||||
mProgram.Link(Desc->ShaderLumpName.GetChars());
|
||||
mProgram.SetAttribLocation(0, "PositionInProjection");
|
||||
mInputTexture.Init(mProgram, "InputTexture");
|
||||
}
|
||||
|
||||
void PostProcessShaderInstance::UpdateUniforms()
|
||||
{
|
||||
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
||||
TMap<FString, PostProcessUniformValue>::Pair *pair;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
int location = glGetUniformLocation(mProgram, pair->Key.GetChars());
|
||||
if (location != -1)
|
||||
{
|
||||
switch (pair->Value.Type)
|
||||
{
|
||||
case PostProcessUniformType::Float:
|
||||
glUniform1f(location, (float)pair->Value.Values[0]);
|
||||
break;
|
||||
case PostProcessUniformType::Int:
|
||||
glUniform1i(location, (int)pair->Value.Values[0]);
|
||||
break;
|
||||
case PostProcessUniformType::Vec2:
|
||||
glUniform2f(location, (float)pair->Value.Values[0], (float)pair->Value.Values[1]);
|
||||
break;
|
||||
case PostProcessUniformType::Vec3:
|
||||
glUniform3f(location, (float)pair->Value.Values[0], (float)pair->Value.Values[1], (float)pair->Value.Values[2]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,31 @@
|
|||
|
||||
class PostProcessShaderInstance;
|
||||
|
||||
enum class PostProcessUniformType
|
||||
{
|
||||
Undefined,
|
||||
Int,
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3
|
||||
};
|
||||
|
||||
struct PostProcessUniformValue
|
||||
{
|
||||
PostProcessUniformType Type = PostProcessUniformType::Undefined;
|
||||
double Values[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
};
|
||||
|
||||
struct PostProcessShader
|
||||
{
|
||||
FString Target;
|
||||
FString ShaderLumpName;
|
||||
int ShaderVersion = 0;
|
||||
FTexture *Texture = nullptr;
|
||||
|
||||
FString Name;
|
||||
TMap<FString, int> Uniform1i;
|
||||
TMap<FString, float> Uniform1f;
|
||||
bool Enabled = false;
|
||||
|
||||
TMap<FString, PostProcessUniformValue> Uniforms;
|
||||
};
|
||||
|
||||
extern TArray<PostProcessShader> PostProcessShaders;
|
||||
|
@ -26,10 +41,14 @@ public:
|
|||
void Run();
|
||||
|
||||
PostProcessShader *Desc;
|
||||
FShaderProgram Program;
|
||||
FBufferedUniformSampler InputTexture;
|
||||
FBufferedUniformSampler CustomTexture;
|
||||
FHardwareTexture *HWTexture = nullptr;
|
||||
|
||||
private:
|
||||
bool IsShaderSupported();
|
||||
void CompileShader();
|
||||
void UpdateUniforms();
|
||||
|
||||
FShaderProgram mProgram;
|
||||
FBufferedUniformSampler mInputTexture;
|
||||
};
|
||||
|
||||
class FCustomPostProcessShaders
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "sc_man.h"
|
||||
#include "cmdlib.h"
|
||||
#include "vm.h"
|
||||
#include "d_player.h"
|
||||
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
|
@ -698,11 +699,28 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump)
|
|||
sc.MustGetString();
|
||||
shaderdesc.Name = sc.String;
|
||||
}
|
||||
else if (sc.Compare("texture"))
|
||||
else if (sc.Compare("uniform"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FTextureID no = TexMan.CheckForTexture(sc.String, FTexture::TEX_Wall);
|
||||
shaderdesc.Texture = TexMan[no];
|
||||
FString uniformType = sc.String;
|
||||
uniformType.ToLower();
|
||||
|
||||
sc.MustGetString();
|
||||
FString uniformName = sc.String;
|
||||
|
||||
PostProcessUniformType parsedType = PostProcessUniformType::Undefined;
|
||||
|
||||
if (uniformType.Compare("int") == 0)
|
||||
parsedType = PostProcessUniformType::Int;
|
||||
else if (uniformType.Compare("float") == 0)
|
||||
parsedType = PostProcessUniformType::Float;
|
||||
else if (uniformType.Compare("vec2") == 0)
|
||||
parsedType = PostProcessUniformType::Vec2;
|
||||
else if (uniformType.Compare("vec3") == 0)
|
||||
parsedType = PostProcessUniformType::Vec3;
|
||||
|
||||
if (parsedType != PostProcessUniformType::Undefined)
|
||||
shaderdesc.Uniforms[uniformName].Type = parsedType;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,18 +787,110 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump)
|
|||
}
|
||||
}
|
||||
|
||||
static bool IsConsolePlayer(player_t *player)
|
||||
{
|
||||
AActor *activator = player ? player->mo : nullptr;
|
||||
if (activator == nullptr || activator->player == nullptr)
|
||||
return false;
|
||||
return int(activator->player - players) == consoleplayer;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Shader, SetEnabled)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER_DEF(player, player_t);
|
||||
PARAM_STRING(shaderName);
|
||||
PARAM_BOOL_DEF(value);
|
||||
|
||||
if (IsConsolePlayer(player))
|
||||
{
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
shader.Enabled = value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Shader, SetUniform1f)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER_DEF(player, player_t);
|
||||
PARAM_STRING(shaderName);
|
||||
PARAM_STRING(uniformName);
|
||||
PARAM_FLOAT_DEF(value);
|
||||
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
if (IsConsolePlayer(player))
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
shader.Uniform1f[uniformName] = value;
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = value;
|
||||
vec4[1] = 0.0;
|
||||
vec4[2] = 0.0;
|
||||
vec4[3] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Shader, SetUniform2f)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER_DEF(player, player_t);
|
||||
PARAM_STRING(shaderName);
|
||||
PARAM_STRING(uniformName);
|
||||
PARAM_FLOAT_DEF(x);
|
||||
PARAM_FLOAT_DEF(y);
|
||||
|
||||
if (IsConsolePlayer(player))
|
||||
{
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = x;
|
||||
vec4[1] = y;
|
||||
vec4[2] = 0.0;
|
||||
vec4[3] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Shader, SetUniform3f)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER_DEF(player, player_t);
|
||||
PARAM_STRING(shaderName);
|
||||
PARAM_STRING(uniformName);
|
||||
PARAM_FLOAT_DEF(x);
|
||||
PARAM_FLOAT_DEF(y);
|
||||
PARAM_FLOAT_DEF(z);
|
||||
|
||||
if (IsConsolePlayer(player))
|
||||
{
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = x;
|
||||
vec4[1] = y;
|
||||
vec4[2] = z;
|
||||
vec4[3] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -788,15 +898,25 @@ DEFINE_ACTION_FUNCTION(_Shader, SetUniform1f)
|
|||
DEFINE_ACTION_FUNCTION(_Shader, SetUniform1i)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER_DEF(player, player_t);
|
||||
PARAM_STRING(shaderName);
|
||||
PARAM_STRING(uniformName);
|
||||
PARAM_INT_DEF(value);
|
||||
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
if (IsConsolePlayer(player))
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
shader.Uniform1i[uniformName] = value;
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = (double)value;
|
||||
vec4[1] = 0.0;
|
||||
vec4[2] = 0.0;
|
||||
vec4[3] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -777,6 +777,9 @@ class Lighting : SectorEffect native
|
|||
|
||||
struct Shader native
|
||||
{
|
||||
native static void SetUniform1f(string shaderName, string uniformName, float value);
|
||||
native static void SetUniform1i(string shaderName, string uniformName, int value);
|
||||
native clearscope static void SetEnabled(PlayerInfo player, string shaderName, bool enable);
|
||||
native clearscope static void SetUniform1f(PlayerInfo player, string shaderName, string uniformName, float value);
|
||||
native clearscope static void SetUniform2f(PlayerInfo player, string shaderName, string uniformName, vector2 value);
|
||||
native clearscope static void SetUniform3f(PlayerInfo player, string shaderName, string uniformName, vector3 value);
|
||||
native clearscope static void SetUniform1i(PlayerInfo player, string shaderName, string uniformName, int value);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue