summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-31 19:37:06 +0800
committerchai <chaifix@163.com>2021-10-31 19:37:06 +0800
commitb972cec461f6c587edd8febbc6dad45bad65046d (patch)
tree006d5b6a05652c7c9670276c146fd27e98315311
parent98d05c5030ba1c35ddfe402790702b3f44c63134 (diff)
*shader command parser
-rw-r--r--Data/Resources/Shaders/Editor-Text.glsl10
-rw-r--r--Runtime/Graphics/RenderCommands.h2
-rw-r--r--Runtime/Graphics/ShaderCompiler.cpp356
-rw-r--r--Runtime/Graphics/ShaderCompiler.h15
4 files changed, 346 insertions, 37 deletions
diff --git a/Data/Resources/Shaders/Editor-Text.glsl b/Data/Resources/Shaders/Editor-Text.glsl
index 3566b28..1624c0e 100644
--- a/Data/Resources/Shaders/Editor-Text.glsl
+++ b/Data/Resources/Shaders/Editor-Text.glsl
@@ -1,12 +1,12 @@
#version 330 core
-// CMD_BEGIN
+CMD_BEGIN
-// Cull Both
-// DepthTest Off
-// Blend SrcAlpha OneMinusSrcAlpha
+Blend SrcAlpha OneMinusSrcAlpha
+Cull Both
+DepthTest Off
-// CMD_END
+CMD_END
uniform mat4 gamelab_mat_mvp;
uniform sampler2D uiTex;
diff --git a/Runtime/Graphics/RenderCommands.h b/Runtime/Graphics/RenderCommands.h
index 3908e3a..cbffdd0 100644
--- a/Runtime/Graphics/RenderCommands.h
+++ b/Runtime/Graphics/RenderCommands.h
@@ -7,7 +7,7 @@ struct RenderCommand
virtual void Execute() = 0;
};
-typedef std::vector<RenderCommand> RenderCommandGroup;
+typedef std::vector<RenderCommand*> RenderCommandGroup;
// Cull Off|Front|Back|Both
struct Cmd_Cull : RenderCommand
diff --git a/Runtime/Graphics/ShaderCompiler.cpp b/Runtime/Graphics/ShaderCompiler.cpp
index 809c375..06ad7b0 100644
--- a/Runtime/Graphics/ShaderCompiler.cpp
+++ b/Runtime/Graphics/ShaderCompiler.cpp
@@ -1,41 +1,335 @@
#include "ShaderCompiler.h"
+#include <sstream>
+#include <algorithm>
using namespace std;
-const char* VSH_BEGIN = "VSH_BEGIN";
-const char* VSH_END = "VSH_END";
-const char* FSH_BEGIN = "FSH_BEGIN";
-const char* FSH_END = "FSH_END";
+static const char* VSH_BEGIN = "VSH_BEGIN";
+static const char* VSH_END = "VSH_END";
+static const char* FSH_BEGIN = "FSH_BEGIN";
+static const char* FSH_END = "FSH_END";
+static const char* CMD_BEGIN = "CMD_BEGIN";
+static const char* CMD_END = "CMD_END";
+
+std::string s_CompileError = "";
// GLSL分为四部分
-// * CMD_BEGIN 和 CMD_END 之间的命令
-// * VERTEX_SHADER_BEGIN 和 VERTEX_SHADER_END之间的顶点着色器
-// * FRAGMENT_SHADER_BEGIN 和 FRAGMENT_SHADER_END之间的片段着色器
-// * 两者之外的公共部分
-void GLSLCompiler::Compile(std::string& src, std::string& vsh, std::string& fsh, RenderCommandGroup& cmd)/*throw GLSLCompileException*/
-{
- int vsh_begin = src.find(VSH_BEGIN);
- if (vsh_begin == string::npos)
- throw GLSLCompileException("Compile Shader Error: No VSH_BEGIN label");
- int vsh_end = src.find(VSH_END);
- if (vsh_end == string::npos)
- throw GLSLCompileException("Compile Shader Error: No VSH_END label");
- int fsh_begin = src.find(FSH_BEGIN);
- if (fsh_begin == string::npos)
- throw GLSLCompileException("Compile Shader Error: No FSH_BEGIN label");
- int fsh_end = src.find(FSH_END);
- if (fsh_end == string::npos)
- throw GLSLCompileException("Compile Shader Error: No FSH_END label");
-
- vsh = src.substr(vsh_begin + strlen(VSH_BEGIN), vsh_end - vsh_begin - strlen(VSH_BEGIN));
- fsh = src.substr(fsh_begin + strlen(FSH_BEGIN), fsh_end - fsh_begin - strlen(FSH_BEGIN));
-
- string common;
- common = src.erase(vsh_begin, vsh_end + strlen(VSH_END) - vsh_begin);
- int fsh_begin2 = common.find(FSH_BEGIN);
- int fsh_end2 = common.find(FSH_END);
- common = common.erase(fsh_begin2, fsh_end2 + strlen(FSH_END) - fsh_begin2);
+// * CMD_BEGIN 和 CMD_END 之间的命令
+// * VERTEX_SHADER_BEGIN 和 VERTEX_SHADER_END之间的顶点着色器
+// * FRAGMENT_SHADER_BEGIN 和 FRAGMENT_SHADER_END之间的片段着色器
+// * 三者之外的公共部分
+void GLSLCompiler::Compile(std::string& src, std::string& vsh, std::string& fsh, RenderCommandGroup& group)/*throw GLSLCompileException*/
+{
+#define CheckLabel(label) {\
+int pos = src.find(label);\
+if(pos == string::npos || !IsLabelActive(src, label)) {\
+ s_CompileError = std::string("Compile Shader Error: No ") + #label + " label";\
+ throw GLSLCompileException(s_CompileError.c_str());\
+}}
+
+ CheckLabel(VSH_BEGIN);
+ CheckLabel(VSH_END);
+ CheckLabel(FSH_BEGIN);
+ CheckLabel(FSH_END);
+
+ bool hasCmd = IsLabelActive(src, CMD_BEGIN) && IsLabelActive(src, CMD_END);
+
+ vsh = GetContent(src, VSH_BEGIN, VSH_END);
+ fsh = GetContent(src, FSH_BEGIN, FSH_END);
+
+ string cmd = GetContent(src, CMD_BEGIN, CMD_END);
+ if (cmd.size() > 0)
+ ParseCmd(cmd, group);
+
+ string common;
+ common = TrimContent(src, VSH_BEGIN, VSH_END);
+ common = TrimContent(common, FSH_BEGIN, FSH_END);
+ if (hasCmd)
+ common = TrimContent(common, CMD_BEGIN, CMD_END);
vsh = common + vsh;
fsh = common + fsh;
}
+
+std::string GLSLCompiler::GetContent(std::string& src, const char* from, const char* to)
+{
+ int begin = src.find(from);
+ int end = src.find(to);
+ std::string content = src.substr(begin + strlen(from), end - begin - strlen(from));
+ return content;
+}
+
+std::string GLSLCompiler::TrimContent(std::string& src, const char* from, const char* to)
+{
+ int begin = src.find(from);
+ int end = src.find(to);
+ string result = src.erase(begin, end + strlen(to) - begin);
+ return result;
+}
+
+bool GLSLCompiler::IsLabelActive(std::string& src, const char* label)
+{
+ int pos = src.find(label);
+ if (pos == string::npos)
+ return false;
+ for (int i = pos - 1; i >= 0; --i)
+ {
+ int second = i;
+ int first = i - 1;
+ if (first < 0)
+ break;
+ if (src[second] == '\n' || src[first] == '\r')
+ break;
+ if (src[first] == '/' && src[second] == '/')
+ return false;
+ }
+ return true;
+}
+
+bool GLSLCompiler::IsCommandActive(std::string& src, const char* label)
+{
+ int pos = src.find(label);
+ if (pos == string::npos)
+ return false;
+ for (int i = pos - 1; i >= 0; --i)
+ {
+ int second = i;
+ int first = i - 1;
+ if (first < 0)
+ break;
+ if (src[second] == '\n' || src[first] == '\r')
+ break;
+ if (src[first] == '/' && src[second] == '/')
+ return false;
+ }
+ return true;
+}
+
+void GLSLCompiler::ParseCmd(std::string& cmds, RenderCommandGroup& group)
+{
+ istringstream ss = istringstream(cmds);
+ string line;
+ while (getline(ss, line))
+ {
+ if(line.find('\r') != string::npos)
+ line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
+ if (IsLineCommentd(line))
+ continue;
+ int cb, ce; // cmd begin, end
+ if (!FindCmdPos(line, &cb, &ce))
+ continue;
+ string cmdName = line.substr(cb, ce - cb + 1);
+ string cmdValue = line.substr(ce + 1, line.size() - ce - 1);
+ if (cmdName == "Cull") CommandCull(cmdValue, group);
+ else if (cmdName == "Blend") CommandBlend(cmdValue, group);
+ else if (cmdName == "DepthTest") CommandDepthTest(cmdValue, group);
+ else if (cmdName == "DepthWrite") CommandDepthWrite(cmdValue, group);
+ else
+ {
+ s_CompileError = string("Unknown command " + cmdName);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ }
+}
+
+#define IsSeperator(c) (c == ' ' || c == '\r' || c == '\n' || c == '\9')
+
+// 找到行内的第一个单词,作为命令名
+bool GLSLCompiler::FindCmdPos(std::string& line, int* start, int* end)
+{
+ for (int i = 0; i < line.size(); ++i)
+ {
+ if (IsSeperator(line[i]))
+ continue;
+ *start = i;
+ for (int j = i + 1; j < line.size(); ++j)
+ {
+ if (IsSeperator(line[j]))
+ {
+ *end = j - 1;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool GLSLCompiler::IsLineCommentd(std::string& line)
+{
+ for (int i = 0; i < line.size(); ++i)
+ {
+ if (IsSeperator(line[i]))
+ continue;
+ int first = i;
+ int second = i + 1;
+ if (second == line.size())
+ return false;
+ if (line[first] == '/' && line[second] == '/')
+ return true;
+ return false;
+ }
+ return false;
+}
+
+#define MAX_PARAM 2
+
+void GLSLCompiler::CommandCull(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[1];
+ GetParams("Cull", p, params, 1);
+
+ Cmd_Cull* pCull = new Cmd_Cull();
+ Cmd_Cull& cull = *pCull;
+ if (params[0] == "Off") cull.cull = Cmd_Cull::Cull_Disable;
+ else if (params[0] == "Front") cull.cull = Cmd_Cull::Cull_Front;
+ else if (params[0] == "Back") cull.cull = Cmd_Cull::Cull_Back;
+ else if (params[0] == "Both") cull.cull = Cmd_Cull::Cull_Both;
+ else
+ {
+ delete pCull;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Cull: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ group.push_back(pCull);
+}
+
+void GLSLCompiler::CommandBlend(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[2];
+ GetParams("Blend", p, params, 2);
+
+ Cmd_Blend* pblend = new Cmd_Blend();
+ Cmd_Blend& blend = *pblend;
+ if (params[0] == "Off")
+ {
+ blend.enable = false;
+ group.push_back(pblend);
+ return;
+ }
+
+ blend.enable = true;
+
+ if (params[0] == "Zero") blend.srcFac = Cmd_Blend::Blend_Zero;
+ else if (params[0] == "One") blend.srcFac = Cmd_Blend::Blend_One;
+ else if (params[0] == "SrcColor") blend.srcFac = Cmd_Blend::Blend_Src_Color;
+ else if (params[0] == "OneMinusSrcColor") blend.srcFac = Cmd_Blend::Blend_One_Minus_Src_Color;
+ else if (params[0] == "DstColor") blend.srcFac = Cmd_Blend::Blend_Dst_Color;
+ else if (params[0] == "OneMinusDstColor") blend.srcFac = Cmd_Blend::Blend_One_Minus_Dst_Color;
+ else if (params[0] == "SrcAlpha") blend.srcFac = Cmd_Blend::Blend_Src_Alpha;
+ else if (params[0] == "OneMinusSrcAlpha") blend.srcFac = Cmd_Blend::Blend_One_Minus_Src_Alpha;
+ else if (params[0] == "DstAlpha") blend.srcFac = Cmd_Blend::Blend_Dst_Alpha;
+ else if (params[0] == "OneMinusDstAlpha") blend.srcFac = Cmd_Blend::Blend_One_Minus_Dst_Alpha;
+ else if (params[0] == "ConstantColor") blend.srcFac = Cmd_Blend::Blend_Constant_Color;
+ else if (params[0] == "OneMinusConstantColor") blend.srcFac = Cmd_Blend::Blend_One_Minus_Constant_Color;
+ else if (params[0] == "ConstantAlpha") blend.srcFac = Cmd_Blend::Blend_Constant_Alpha;
+ else if (params[0] == "OneMinusConstantAlpha") blend.srcFac = Cmd_Blend::Blend_One_Minus_Constant_Alpha;
+ else
+ {
+ delete pblend;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Blend: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+
+ if (params[1] == "Zero") blend.dstFac = Cmd_Blend::Blend_Zero;
+ else if (params[1] == "One") blend.dstFac = Cmd_Blend::Blend_One;
+ else if (params[1] == "SrcColor") blend.dstFac = Cmd_Blend::Blend_Src_Color;
+ else if (params[1] == "OneMinusSrcColor") blend.dstFac = Cmd_Blend::Blend_One_Minus_Src_Color;
+ else if (params[1] == "DstColor") blend.dstFac = Cmd_Blend::Blend_Dst_Color;
+ else if (params[1] == "OneMinusDstColor") blend.dstFac = Cmd_Blend::Blend_One_Minus_Dst_Color;
+ else if (params[1] == "SrcAlpha") blend.dstFac = Cmd_Blend::Blend_Src_Alpha;
+ else if (params[1] == "OneMinusSrcAlpha") blend.dstFac = Cmd_Blend::Blend_One_Minus_Src_Alpha;
+ else if (params[1] == "DstAlpha") blend.dstFac = Cmd_Blend::Blend_Dst_Alpha;
+ else if (params[1] == "OneMinusDstAlpha") blend.dstFac = Cmd_Blend::Blend_One_Minus_Dst_Alpha;
+ else if (params[1] == "ConstantColor") blend.dstFac = Cmd_Blend::Blend_Constant_Color;
+ else if (params[1] == "OneMinusConstantColor") blend.dstFac = Cmd_Blend::Blend_One_Minus_Constant_Color;
+ else if (params[1] == "ConstantAlpha") blend.dstFac = Cmd_Blend::Blend_Constant_Alpha;
+ else if (params[1] == "OneMinusConstantAlpha") blend.dstFac = Cmd_Blend::Blend_One_Minus_Constant_Alpha;
+ else
+ {
+ delete pblend;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Blend: " + params[1]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+
+ group.push_back(pblend);
+}
+
+void GLSLCompiler::CommandDepthTest(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[1];
+ GetParams("DepthTest", p, params, 1);
+
+ Cmd_DepthTest* pTest = new Cmd_DepthTest();
+ Cmd_DepthTest& test = *pTest;
+ if (params[0] == "Off") test.test = Cmd_DepthTest::DepthTest_Off;
+ else if (params[0] == "Always") test.test = Cmd_DepthTest::DepthTest_Always;
+ else if (params[0] == "Never") test.test = Cmd_DepthTest::DepthTest_Never;
+ else if (params[0] == "Less") test.test = Cmd_DepthTest::DepthTest_Less;
+ else if (params[0] == "Equal") test.test = Cmd_DepthTest::DepthTest_Equal;
+ else if (params[0] == "LEqual") test.test = Cmd_DepthTest::DepthTest_Lequal;
+ else if (params[0] == "Greater") test.test = Cmd_DepthTest::DepthTest_Greater;
+ else if (params[0] == "NotEqual") test.test = Cmd_DepthTest::DepthTest_Notequal;
+ else if (params[0] == "GEqual") test.test = Cmd_DepthTest::DepthTest_Gequal;
+ else
+ {
+ delete pTest;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of DepthTest: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ group.push_back(pTest);
+}
+
+void GLSLCompiler::CommandDepthWrite(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[1];
+ GetParams("DepthWrite", p, params, 1);
+
+ Cmd_DepthWrite* pwrite = new Cmd_DepthWrite();
+ Cmd_DepthWrite& write = *pwrite;
+ if (params[0] == "Off") write.write = false;
+ else if (params[0] == "On") write.write = true;
+ else
+ {
+ delete pwrite;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Cmd_DepthWrite: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ group.push_back(pwrite);
+}
+
+void GLSLCompiler::GetParams(const char* cmdName, std::string& params, std::string* out, int n)
+{
+ int index = 0;
+ for (int i = 0; i < params.size(); ++i)
+ {
+ if (IsSeperator(params[i]))
+ continue;
+ int j = i + 1;
+ for (; j < params.size(); ++j)
+ {
+ if (j == params.size() - 1)
+ {
+ if (index >= n)
+ {
+ s_CompileError = string("Compile Shader Error: Invalid parameter count of ") + cmdName +" : " + params;
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ if(!IsSeperator(params[i]))
+ out[index++] = params.substr(i, j - i + 1);
+ else
+ out[index++] = params.substr(i, j - i);
+ return;
+ }
+ if (!IsSeperator(params[j]))
+ continue;
+ if (index >= n)
+ {
+ s_CompileError = string("Compile Shader Error: Invalid parameter count of ") + cmdName + " : " + params;
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ out[index++] = params.substr(i, j - i);
+ break;
+ }
+ i = j;
+ }
+} \ No newline at end of file
diff --git a/Runtime/Graphics/ShaderCompiler.h b/Runtime/Graphics/ShaderCompiler.h
index 56ddb45..891efb7 100644
--- a/Runtime/Graphics/ShaderCompiler.h
+++ b/Runtime/Graphics/ShaderCompiler.h
@@ -37,4 +37,19 @@ class GLSLCompiler
public:
static void Compile(std::string& src, std::string& vsh, std::string& fsh, RenderCommandGroup& cmd)/*throw GLSLCompileException*/;
+private:
+ static std::string GetContent(std::string& src, const char* from, const char* to);
+ static std::string TrimContent(std::string& src, const char* from, const char* to);
+ static bool IsLabelActive(std::string& src, const char* label);
+
+ static void ParseCmd(std::string& cmd, RenderCommandGroup& group);
+ static bool IsCommandActive(std::string& src, const char* label);
+ static bool FindCmdPos(std::string& line, int* start, int* end);
+ static bool IsLineCommentd(std::string& line);
+ static void CommandCull(std::string& params, RenderCommandGroup& group);
+ static void CommandBlend(std::string& params, RenderCommandGroup& group);
+ static void CommandDepthTest(std::string& params, RenderCommandGroup& group);
+ static void CommandDepthWrite(std::string& params, RenderCommandGroup& group);
+ static void GetParams(const char* cmdName, std::string& params, std::string* out, int n);
+
};