From 4f07ce9a1583713120ddac58e6b3933db7b854a9 Mon Sep 17 00:00:00 2001 From: Kevin Waldock Date: Fri, 30 Oct 2015 08:55:35 +0100 Subject: [PATCH] Add simple shader wrapper --- LunaDll/GlobalFuncs.cpp | 14 +++ LunaDll/GlobalFuncs.h | 1 + LunaDll/LunaDll.vcxproj | 2 + LunaDll/LunaDll.vcxproj.filters | 6 ++ LunaDll/Rendering/GLDraw.cpp | 6 ++ LunaDll/Rendering/GLEngine.cpp | 3 +- LunaDll/Rendering/Shaders/GLShader.cpp | 137 +++++++++++++++++++++++++ LunaDll/Rendering/Shaders/GLShader.h | 39 +++++++ 8 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 LunaDll/Rendering/Shaders/GLShader.cpp create mode 100644 LunaDll/Rendering/Shaders/GLShader.h diff --git a/LunaDll/GlobalFuncs.cpp b/LunaDll/GlobalFuncs.cpp index c5f29eb1b..f8f1f2b05 100644 --- a/LunaDll/GlobalFuncs.cpp +++ b/LunaDll/GlobalFuncs.cpp @@ -323,6 +323,20 @@ bool readFile(std::wstring &content, std::wstring path, std::wstring errMsg /*= return true; } +bool readFile(std::string &content, std::string path, std::string errMsg /*= std::string()*/) +{ + ifstream theFile(path, ios::binary | ios::in); + if (!theFile.is_open()) { + theFile.close(); + if (!errMsg.empty()) + MessageBoxA(NULL, errMsg.c_str(), "Error", NULL); + return false; + } + + content = std::string((std::istreambuf_iterator(theFile)), std::istreambuf_iterator()); + return true; +} + bool isAbsolutePath(const std::wstring& path) { return std::iswalpha(path[0]) && path[1] == L':' && path[2] == L'\\'; diff --git a/LunaDll/GlobalFuncs.h b/LunaDll/GlobalFuncs.h index 3e19270d1..7765bcc88 100644 --- a/LunaDll/GlobalFuncs.h +++ b/LunaDll/GlobalFuncs.h @@ -37,6 +37,7 @@ HMODULE getModule(std::string moduleName); // File/Path Helper Funcs bool readFile(std::wstring &content, std::wstring path, std::wstring errMsg = std::wstring()); +bool readFile(std::string &content, std::string path, std::string errMsg = std::string()); bool writeFile(const std::string &content, const std::string &path); std::vector listFilesOfDir(const std::string& path); std::vector listOfDir(const std::string& path, DWORD fileAttributes); diff --git a/LunaDll/LunaDll.vcxproj b/LunaDll/LunaDll.vcxproj index e09989e89..f5dfc96a7 100644 --- a/LunaDll/LunaDll.vcxproj +++ b/LunaDll/LunaDll.vcxproj @@ -159,6 +159,7 @@ + @@ -276,6 +277,7 @@ + diff --git a/LunaDll/LunaDll.vcxproj.filters b/LunaDll/LunaDll.vcxproj.filters index a3ed8a435..38044448e 100644 --- a/LunaDll/LunaDll.vcxproj.filters +++ b/LunaDll/LunaDll.vcxproj.filters @@ -462,6 +462,9 @@ Header Files\Rendering + + Header Files + @@ -872,6 +875,9 @@ Header Files\Misc\RuntimeHookUtils + + Source Files + diff --git a/LunaDll/Rendering/GLDraw.cpp b/LunaDll/Rendering/GLDraw.cpp index a9b7a8a71..ea553943b 100644 --- a/LunaDll/Rendering/GLDraw.cpp +++ b/LunaDll/Rendering/GLDraw.cpp @@ -162,6 +162,8 @@ void GLDraw::DrawRectangle(int nXDest, int nYDest, int nWidth, int nHeight) void GLDraw::DrawStretched(int nXDest, int nYDest, int nWidth, int nHeight, const Texture* tex, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, float opacity) { + // Bind Post-Processing Shader here + // Generate our floating point coordinates float texw = (float)tex->pw; float texh = (float)tex->ph; @@ -181,6 +183,9 @@ void GLDraw::DrawStretched(int nXDest, int nYDest, int nWidth, int nHeight, cons GLERRORCHECK(); BindTexture(tex); + GLERRORCHECK(); + + // Set Post-Processing uniforms/attributes here GLfloat Vertices[] = { x1, y1, 0, @@ -211,6 +216,7 @@ void GLDraw::DrawStretched(int nXDest, int nYDest, int nWidth, int nHeight, cons GLERRORCHECK(); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices); GLERRORCHECK(); + // Unbind Post-Processing Shader here } diff --git a/LunaDll/Rendering/GLEngine.cpp b/LunaDll/Rendering/GLEngine.cpp index 674f56154..cdadeb1f2 100644 --- a/LunaDll/Rendering/GLEngine.cpp +++ b/LunaDll/Rendering/GLEngine.cpp @@ -66,7 +66,8 @@ BOOL GLEngine::EmulatedStretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDes HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop) { - // TODO: This block of code will need to be changed once + // Load Post-Processing Shader somewhere here + // TODO: This block of code will need to be changed once // GLContextManager is modified to handle re-init // with a new hDC if (!g_GLContextManager.IsInitialized()) { diff --git a/LunaDll/Rendering/Shaders/GLShader.cpp b/LunaDll/Rendering/Shaders/GLShader.cpp new file mode 100644 index 000000000..23d332d14 --- /dev/null +++ b/LunaDll/Rendering/Shaders/GLShader.cpp @@ -0,0 +1,137 @@ +#include "GLShader.h" + +#include "../../GlobalFuncs.h" + +#include + +bool GLShader::compileShaderSource(GLuint shaderID, const std::string& source) +{ + const char* sources[] = { source.c_str() }; + glShaderSource(shaderID, 1, sources, NULL); + glCompileShader(shaderID); + + GLint result; + glGetShaderiv(shaderID, GL_COMPILE_STATUS, &result); + return result != GL_FALSE; +} + +std::string GLShader::getLastShaderError(GLuint shaderID) +{ + GLint length; + glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length); + std::string errorStr(length, ' '); + glGetShaderInfoLog(shaderID, length, &length, &errorStr[0]); + return errorStr; +} + +GLShader::GLShader(const std::string & name, const std::string & vertexSource, const std::string & fragementSource) : + m_name(name), + m_vertexSource(vertexSource), + m_fragmentSource(fragementSource), + m_isValid(false) +{ + load(); +} + +GLShader::~GLShader() +{ + glDeleteProgram(m_shaderID); +} + +void GLShader::bind() +{ + glUseProgram(m_shaderID); +} + +void GLShader::unbind() +{ + glUseProgram(0); +} + +GLuint GLShader::getAttribute(const std::string& name) +{ + std::cout << "Get Attribute: " << name << std::endl; + GLuint ret = glGetAttribLocation(m_shaderID, name.c_str()); + GLERRORCHECK(); + return ret; +} + +GLuint GLShader::getUniform(const std::string& name) +{ + std::cout << "Get Uniform: " << name << std::endl; + GLuint ret = glGetUniformLocation(m_shaderID, name.c_str()); + GLERRORCHECK(); + return ret; +} + +void GLShader::load() +{ + bool isVertexSourceValid = m_vertexSource != ""; + bool isFragmentSourceValid = m_vertexSource != ""; + if (!isVertexSourceValid && !isFragmentSourceValid) + return; + + GLuint program = glCreateProgram(); + GLuint vertex; + GLuint fragment; + if(isVertexSourceValid) + vertex = glCreateShader(GL_VERTEX_SHADER); + if (isVertexSourceValid) + fragment = glCreateShader(GL_FRAGMENT_SHADER); + + + if (isVertexSourceValid) { + if (!compileShaderSource(vertex, m_vertexSource)) + { + std::cout << "Failed to compile vertex shader: " << std::endl + << getLastShaderError(vertex) << std::endl; + glDeleteShader(vertex); + return; + } + } + if (isFragmentSourceValid) { + if (!compileShaderSource(fragment, m_fragmentSource)) + { + std::cout << "Failed to compile fragment shader: " << std::endl + << getLastShaderError(fragment) << std::endl; + glDeleteShader(fragment); + return; + } + } + + if(isVertexSourceValid) + glAttachShader(program, vertex); + GLERRORCHECK(); + if(isFragmentSourceValid) + glAttachShader(program, fragment); + GLERRORCHECK(); + + glLinkProgram(program); + GLERRORCHECK(); + glValidateProgram(program); + GLERRORCHECK(); + + if(isVertexSourceValid) + glDeleteShader(vertex); + GLERRORCHECK(); + if(isFragmentSourceValid) + glDeleteShader(fragment); + GLERRORCHECK(); + + m_isValid = true; // Success! + m_shaderID = program; +} + +GLShader* GLShader::fromData(const std::string& name, const std::string& vertexSource, const std::string& fragementSource) +{ + return new GLShader(name, vertexSource, fragementSource); +} + +GLShader* GLShader::fromFile(const std::string& name, const std::string& vertexFile, const std::string& fragmentFile) +{ + std::string vertexSource(""); + std::string fragementSource(""); + readFile(vertexSource, vertexFile); + readFile(fragementSource, fragmentFile); + return new GLShader(name, vertexSource, fragementSource); +} diff --git a/LunaDll/Rendering/Shaders/GLShader.h b/LunaDll/Rendering/Shaders/GLShader.h new file mode 100644 index 000000000..f87114e7f --- /dev/null +++ b/LunaDll/Rendering/Shaders/GLShader.h @@ -0,0 +1,39 @@ +#ifndef GLShader_hhhhh +#define GLShader_hhhhh + +#include "../GLCompat.h" +#include + +class GLShader +{ +private: + static bool compileShaderSource(GLuint shaderID, const std::string& source); + static std::string getLastShaderError(GLuint shaderID); + + GLuint m_shaderID; + std::string m_name; + std::string m_vertexSource; + std::string m_fragmentSource; + bool m_isValid; + +public: + GLShader(const std::string& name, const std::string& vertexSource, const std::string& fragmentSource); + GLShader(const GLShader& other) = delete; + ~GLShader(); + + inline bool isValid() { return m_isValid; } + void bind(); + void unbind(); + + GLuint getAttribute(const std::string& name); + GLuint getUniform(const std::string& name); +private: + void load(); + +public: + static GLShader* fromData(const std::string& name, const std::string& vertexSource, const std::string& fragementSource); + static GLShader* fromFile(const std::string& name, const std::string& vertexFile, const std::string& fragmentFile); + +}; + +#endif