From e161bba14678350de09d763658ec784f759919a8 Mon Sep 17 00:00:00 2001
From: Magnus Norddahl <dpjudas@users.noreply.github.com>
Date: Mon, 3 Jul 2017 22:30:49 +0200
Subject: [PATCH] - Specify shader uniforms from ZScript

---
 src/gl/renderer/gl_postprocess.cpp | 52 ++++++++++++++++++++++++++++++
 src/gl/renderer/gl_renderer.h      |  5 +++
 src/gl/shaders/gl_shader.cpp       |  5 +++
 wadsrc/static/zscript/base.txt     |  5 +++
 4 files changed, 67 insertions(+)

diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp
index 570a43ffc0..89a18395f6 100644
--- a/src/gl/renderer/gl_postprocess.cpp
+++ b/src/gl/renderer/gl_postprocess.cpp
@@ -178,6 +178,40 @@ void FGLRenderer::PostProcessScene(int fixedcm)
 	RunCustomPostProcessShaders("screen");
 }
 
+#include "vm.h"
+
+DEFINE_ACTION_FUNCTION(_Shader, SetUniform1f)
+{
+	PARAM_PROLOGUE;
+	PARAM_STRING(shaderName);
+	PARAM_STRING(uniformName);
+	PARAM_FLOAT_DEF(value);
+
+	for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
+	{
+		PostProcessShader &shader = PostProcessShaders[i];
+		if (shader.Name == shaderName)
+			shader.Uniform1f[uniformName] = value;
+	}
+	return 0;
+}
+
+DEFINE_ACTION_FUNCTION(_Shader, SetUniform1i)
+{
+	PARAM_PROLOGUE;
+	PARAM_STRING(shaderName);
+	PARAM_STRING(uniformName);
+	PARAM_INT_DEF(value);
+
+	for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
+	{
+		PostProcessShader &shader = PostProcessShaders[i];
+		if (shader.Name == shaderName)
+			shader.Uniform1i[uniformName] = value;
+	}
+	return 0;
+}
+
 void FGLRenderer::RunCustomPostProcessShaders(FString target)
 {
 	for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
@@ -222,6 +256,24 @@ void FGLRenderer::RunCustomPostProcessShaders(FString target)
 
 		shader.Instance->Program.Bind();
 
+		TMap<FString, float>::Iterator it1f(shader.Uniform1f);
+		TMap<FString, float>::Pair *pair1f;
+		while (it1f.NextPair(pair1f))
+		{
+			int location = glGetUniformLocation(shader.Instance->Program, pair1f->Key.GetChars());
+			if (location != -1)
+				glUniform1f(location, pair1f->Value);
+		}
+
+		TMap<FString, int>::Iterator it1i(shader.Uniform1i);
+		TMap<FString, int>::Pair *pair1i;
+		while (it1i.NextPair(pair1i))
+		{
+			int location = glGetUniformLocation(shader.Instance->Program, pair1i->Key.GetChars());
+			if (location != -1)
+				glUniform1i(location, pair1i->Value);
+		}
+
 		shader.Instance->InputTexture.Set(0);
 
 		if (shader.Instance->HWTexture)
diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h
index ce4d749a7a..9e75e13fc9 100644
--- a/src/gl/renderer/gl_renderer.h
+++ b/src/gl/renderer/gl_renderer.h
@@ -92,6 +92,11 @@ struct PostProcessShader
 	FString ShaderLumpName;
 	int ShaderVersion = 0;
 	FTexture *Texture = nullptr;
+
+	FString Name;
+	TMap<FString, int> Uniform1i;
+	TMap<FString, float> Uniform1f;
+
 	std::shared_ptr<PostProcessShaderInstance> Instance;
 };
 
diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp
index 022cec7d9a..ba4c2874c6 100644
--- a/src/gl/shaders/gl_shader.cpp
+++ b/src/gl/shaders/gl_shader.cpp
@@ -693,6 +693,11 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump)
 				sc.MustGetNumber();
 				shaderdesc.ShaderVersion = sc.Number;
 			}
+			else if (sc.Compare("name"))
+			{
+				sc.MustGetString();
+				shaderdesc.Name = sc.String;
+			}
 			else if (sc.Compare("texture"))
 			{
 				sc.MustGetString();
diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt
index 726e46fccc..c215768d14 100644
--- a/wadsrc/static/zscript/base.txt
+++ b/wadsrc/static/zscript/base.txt
@@ -775,3 +775,8 @@ 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);
+}