Make EMotionFX shaders load from the Shaders directory, instead of prepending "Shaders" to all filenames (#56)

Because the `shaderPath` variable is used as a base directory, it needs
to end with the directory separator. Otherwise the parts before the data
dir become a file prefix used when loading all shaders. Attempts to load
"Line_VS.glsl" from "Shaders/" end up instead trying to load
"ShadersLine_VS.glsl".
This commit is contained in:
Chris Burel
2021-04-16 14:19:45 -07:00
committed by GitHub
parent 41981412c5
commit 0db617f4d8
10 changed files with 59 additions and 62 deletions
@@ -131,8 +131,14 @@ namespace RenderGL
void GLRenderUtil::Validate()
{
mLineShader->Validate();
mMeshShader->Validate();
if (mLineShader)
{
mLineShader->Validate();
}
if (mMeshShader)
{
mMeshShader->Validate();
}
}
// destroy the allocated memory
@@ -116,12 +116,12 @@ namespace RenderGL
}
bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, const char* filename)
bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename)
{
QFile file(filename);
QFile file(QString::fromUtf8(filename.Native().data(), aznumeric_caster(filename.Native().size())));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%s'.", filename);
AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%.*s'.", AZ_STRING_ARG(filename.Native()));
return false;
}
@@ -156,7 +156,7 @@ namespace RenderGL
if (success == false)
{
MCore::LogError("[GLSL] Failed to compile shader '%s'.", filename);
MCore::LogError("[GLSL] Failed to compile shader '%.*s'.", AZ_STRING_ARG(filename.Native()));
return false;
}
@@ -212,7 +212,7 @@ namespace RenderGL
// Init
bool GLSLShader::Init(const char* vFile, const char* pFile, MCore::Array<AZStd::string>& defines)
bool GLSLShader::Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines)
{
initializeOpenGLFunctions();
/*const char* args[] = { "unroll all",
@@ -225,24 +225,24 @@ namespace RenderGL
glUseProgram(0);
// compile shaders
if (vFile && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vFile) == false)
if (!vertexFileName.empty() && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vertexFileName) == false)
{
return false;
}
if (pFile && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pFile) == false)
if (!pixelFileName.empty() && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pixelFileName) == false)
{
return false;
}
// create program
mProgram = glCreateProgram();
if (vFile)
if (!vertexFileName.empty())
{
glAttachShader(mProgram, mVertexShader);
}
if (pFile)
if (!pixelFileName.empty())
{
glAttachShader(mProgram, mPixelShader);
}
@@ -256,7 +256,7 @@ namespace RenderGL
if (!success)
{
MCore::LogInfo("[OpenGL] Failed to link shaders '%s' and '%s' ", vFile, pFile);
MCore::LogInfo("[OpenGL] Failed to link shaders '%.*s' and '%.*s' ", AZ_STRING_ARG(vertexFileName.Native()), AZ_STRING_ARG(pixelFileName.Native()));
InfoLog(mProgram, &QOpenGLExtraFunctions::glGetProgramInfoLog);
return false;
}
@@ -14,6 +14,7 @@
#define __RENDERGL_GLSLSHADER_H
#include <AzCore/std/string/string.h>
#include <AzCore/IO/Path/Path.h>
#include "Shader.h"
// include OpenGL
@@ -45,7 +46,7 @@ namespace RenderGL
MCORE_INLINE unsigned int GetProgram() const { return mProgram; }
bool CheckIfIsDefined(const char* attributeName);
bool Init(const char* vertexFileName, const char* pixelFileName, MCore::Array<AZStd::string>& defines);
bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines);
void SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) override;
void SetUniform(const char* name, float value) override;
@@ -81,11 +82,11 @@ namespace RenderGL
ShaderParameter* FindAttribute(const char* name);
ShaderParameter* FindUniform(const char* name);
bool CompileShader(const GLenum type, unsigned int* outShader, const char* filename);
bool CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename);
template<class T>
void InfoLog(GLuint object, T func);
AZStd::string mFileName;
AZ::IO::Path mFileName;
MCore::Array<uint32> mActivatedAttribs;
MCore::Array<uint32> mActivatedTextures;
@@ -203,7 +203,7 @@ namespace RenderGL
// try to initialize the graphics system
bool GraphicsManager::Init(const char* shaderPath)
bool GraphicsManager::Init(AZ::IO::PathView shaderPath)
{
initializeOpenGLFunctions();
@@ -364,7 +364,7 @@ namespace RenderGL
// try to load a texture
Texture* GraphicsManager::LoadTexture([[maybe_unused]] const char* filename, [[maybe_unused]] bool createMipMaps)
Texture* GraphicsManager::LoadTexture([[maybe_unused]] AZ::IO::PathView filename, [[maybe_unused]] bool createMipMaps)
{
//Texture Library is no longer used
//temporarily blank
@@ -373,19 +373,19 @@ namespace RenderGL
// try to load a texture
Texture* GraphicsManager::LoadTexture(const char* filename)
Texture* GraphicsManager::LoadTexture(AZ::IO::PathView filename)
{
return LoadTexture(filename, mCreateMipMaps);
}
// LoadPostProcessShader
PostProcessShader* GraphicsManager::LoadPostProcessShader(const char* cFileName)
PostProcessShader* GraphicsManager::LoadPostProcessShader(AZ::IO::PathView cFileName)
{
AZStd::string filename = mShaderPath + AZStd::string(cFileName);
AZ::IO::PathView filename = mShaderPath / cFileName;
// check if the shader is already in the cache
Shader* s = mShaderCache.FindShader(filename.c_str());
Shader* s = mShaderCache.FindShader(filename.Native());
if (s)
{
return (PostProcessShader*)s;
@@ -393,19 +393,19 @@ namespace RenderGL
// load the shader from disk
PostProcessShader* shader = new PostProcessShader();
if (!shader->Init(filename.c_str()))
if (!shader->Init(filename))
{
delete shader;
return nullptr;
}
mShaderCache.AddShader(filename.c_str(), shader);
mShaderCache.AddShader(filename.Native(), shader);
return shader;
}
// LoadShader
GLSLShader* GraphicsManager::LoadShader(const char* vertexFileName, const char* pixelFileName)
GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName)
{
MCore::Array<AZStd::string> defines;
return LoadShader(vertexFileName, pixelFileName, defines);
@@ -413,34 +413,21 @@ namespace RenderGL
// LoadShader
GLSLShader* GraphicsManager::LoadShader(const char* vFile, const char* pFile, MCore::Array<AZStd::string>& defines)
GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines)
{
AZStd::string vStr;
AZStd::string pStr;
if (vFile)
{
vStr = AZStd::string::format("%s%s", mShaderPath.c_str(), vFile);
}
if (pFile)
{
pStr = AZStd::string::format("%s%s", mShaderPath.c_str(), pFile);
}
const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : mShaderPath / vertexFileName};
const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : mShaderPath / pixelFileName};
// construct the lookup string for the shader cache
AZStd::string dStr;
AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native();
const uint32 numDefines = defines.GetLength();
for (uint32 n = 0; n < numDefines; n++)
{
dStr += AZStd::string::format("#%s", defines[n].c_str());
cacheLookupStr += AZStd::string::format("#%s", defines[n].c_str());
}
AZStd::string cStr;
cStr = AZStd::string::format("%s%s%s", vStr.c_str(), pStr.c_str(), dStr.c_str());
// check if the shader is already in the cache
Shader* cShader = mShaderCache.FindShader(cStr.c_str());
Shader* cShader = mShaderCache.FindShader(cacheLookupStr);
if (cShader)
{
return (GLSLShader*)cShader;
@@ -448,13 +435,13 @@ namespace RenderGL
// load the shader from disk
GLSLShader* shader = new GLSLShader();
if (!shader->Init(vFile ? vStr.c_str() : nullptr, pFile ? pStr.c_str() : nullptr, defines))
if (!shader->Init(vertexPath, pixelPath, defines))
{
delete shader;
return nullptr;
}
mShaderCache.AddShader(cStr.c_str(), shader);
mShaderCache.AddShader(cacheLookupStr, shader);
return shader;
}
@@ -13,6 +13,7 @@
#ifndef __RENDERGL_GRAPHICSMANAGER__H
#define __RENDERGL_GRAPHICSMANAGER__H
#include <AzCore/IO/Path/Path.h>
#include <MCore/Source/StandardHeaders.h>
#include <MCore/Source/Vector.h>
#include <MCore/Source/Color.h>
@@ -57,21 +58,21 @@ namespace RenderGL
const char* GetDeviceName();
const char* GetDeviceVendor();
MCORE_INLINE RenderTexture* GetRenderTexture() { return mRenderTexture; }
MCORE_INLINE const char* GetShaderPath() const { return mShaderPath.c_str(); }
MCORE_INLINE AZ::IO::PathView GetShaderPath() const { return mShaderPath; }
MCORE_INLINE TextureCache* GetTextureCache() { return &mTextureCache; }
bool Init(const char* shaderPath = "Shaders/");
bool Init(AZ::IO::PathView shaderPath = "Shaders");
bool GetIsPostProcessingEnabled() const { return mPostProcessing; }
PostProcessShader* LoadPostProcessShader(const char* filename);
GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName);
GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName, MCore::Array<AZStd::string>& defines);
PostProcessShader* LoadPostProcessShader(AZ::IO::PathView filename);
GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName);
GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines);
MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { mGBuffer = gBuffer; }
MCORE_INLINE GBuffer* GetGBuffer() { return mGBuffer; }
Texture* LoadTexture(const char* filename, bool createMipMaps);
Texture* LoadTexture(const char* filename);
Texture* LoadTexture(AZ::IO::PathView filename, bool createMipMaps);
Texture* LoadTexture(AZ::IO::PathView filename);
void SetCreateMipMaps(bool createMipMaps) { mCreateMipMaps = createMipMaps; }
MCORE_INLINE bool GetCreateMipMaps() const { return mCreateMipMaps; }
@@ -96,7 +97,7 @@ namespace RenderGL
void SetShader(Shader* shader);
MCORE_INLINE void SetRenderTexture(RenderTexture* texture) { mRenderTexture = texture; }
MCORE_INLINE void SetShaderPath(const char* shaderPath) { mShaderPath = shaderPath; }
MCORE_INLINE void SetShaderPath(AZ::IO::PathView shaderPath) { mShaderPath = shaderPath; }
MCORE_INLINE void SetBloomEnabled(bool enabled) { mBloomEnabled = enabled; }
MCORE_INLINE void SetBloomThreshold(float threshold) { mBloomThreshold = threshold; }
@@ -154,7 +155,7 @@ namespace RenderGL
MCommon::Camera* mCamera; /**< The camera used for rendering. */
ShaderCache mShaderCache; /**< The shader manager used to load and manage vertex and pixel shaders. */
AZStd::string mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */
AZ::IO::Path mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */
MCore::RGBAColor mClearColor; /**< The scene background color. */
MCore::RGBAColor mGradientSourceColor; /**< The background gradient source color. */
MCore::RGBAColor mGradientTargetColor; /**< The background gradient target color. */
@@ -11,6 +11,7 @@
*/
#include <AzCore/Math/Vector2.h>
#include <AzCore/IO/Path/Path.h>
#include "PostProcessShader.h"
#include "GraphicsManager.h"
@@ -82,7 +83,7 @@ namespace RenderGL
// Init
bool PostProcessShader::Init(const char* filename)
bool PostProcessShader::Init(AZ::IO::PathView filename)
{
MCore::Array<AZStd::string> defines;
return GLSLShader::Init(nullptr, filename, defines);
@@ -13,6 +13,7 @@
#ifndef __RENDERGL_POSTPROCESS_SHADER_H
#define __RENDERGL_POSTPROCESS_SHADER_H
#include <AzCore/IO/Path/Path_fwd.h>
#include "GLSLShader.h"
#include "RenderTexture.h"
@@ -34,7 +35,7 @@ namespace RenderGL
void Deactivate() override;
bool Init(const char* filename);
bool Init(AZ::IO::PathView filename);
void Render();
private:
@@ -48,7 +48,7 @@ namespace RenderGL
// add the shader to the cache (assume there are no duplicate names)
void ShaderCache::AddShader(const char* filename, Shader* shader)
void ShaderCache::AddShader(AZStd::string_view filename, Shader* shader)
{
mEntries.AddEmpty();
mEntries.GetLast().mName = filename;
@@ -57,12 +57,12 @@ namespace RenderGL
// try to locate a shader based on its name
Shader* ShaderCache::FindShader(const char* filename) const
Shader* ShaderCache::FindShader(AZStd::string_view filename) const
{
const uint32 numEntries = mEntries.GetLength();
for (uint32 i = 0; i < numEntries; ++i)
{
if (AzFramework::StringFunc::Equal(mEntries[i].mName.c_str(), filename, false /* no case */)) // non-case-sensitive name compare
if (AzFramework::StringFunc::Equal(mEntries[i].mName, filename, false /* no case */)) // non-case-sensitive name compare
{
return mEntries[i].mShader;
}
@@ -33,8 +33,8 @@ namespace RenderGL
~ShaderCache(); // automatically calls Release
void Release();
void AddShader(const char* filename, Shader* shader);
Shader* FindShader(const char* filename) const;
void AddShader(AZStd::string_view filename, Shader* shader);
Shader* FindShader(AZStd::string_view filename) const;
bool CheckIfHasShader(Shader* shader) const;
private:
@@ -64,7 +64,7 @@ namespace EMStudio
// create graphics manager and initialize it
mGraphicsManager = new RenderGL::GraphicsManager();
if (mGraphicsManager->Init(shaderPath.c_str()) == false)
if (mGraphicsManager->Init(shaderPath) == false)
{
MCore::LogError("Could not initialize OpenGL graphics manager.");
return false;