diff --git a/Source/Native/RenderDevice.cpp b/Source/Native/RenderDevice.cpp index ac9e8972..3d916a5b 100644 --- a/Source/Native/RenderDevice.cpp +++ b/Source/Native/RenderDevice.cpp @@ -22,7 +22,27 @@ static void APIENTRY GLLogCallback(GLenum source, GLenum type, GLuint id, RenderDevice::RenderDevice(void* disp, void* window) { - memset(mUniforms, 0, sizeof(mUniforms)); + DeclareUniform(UniformName::projection, "projection", UniformType::Matrix); + DeclareUniform(UniformName::view, "view", UniformType::Matrix); + DeclareUniform(UniformName::world, "world", UniformType::Matrix); + DeclareUniform(UniformName::modelnormal, "modelnormal", UniformType::Matrix); + DeclareUniform(UniformName::rendersettings, "rendersettings", UniformType::Vec4f); + DeclareUniform(UniformName::highlightcolor, "highlightcolor", UniformType::Vec4f); + DeclareUniform(UniformName::FillColor, "fillColor", UniformType::Vec4f); + DeclareUniform(UniformName::vertexColor, "vertexColor", UniformType::Vec4f); + DeclareUniform(UniformName::stencilColor, "stencilColor", UniformType::Vec4f); + DeclareUniform(UniformName::lightPosAndRadius, "lightPosAndRadius", UniformType::Vec4f); + DeclareUniform(UniformName::lightColor, "lightColor", UniformType::Vec4f); + DeclareUniform(UniformName::campos, "campos", UniformType::Vec4f); + DeclareUniform(UniformName::texturefactor, "texturefactor", UniformType::Vec4f); + DeclareUniform(UniformName::fogsettings, "fogsettings", UniformType::Vec4f); + DeclareUniform(UniformName::fogcolor, "fogcolor", UniformType::Vec4f); + DeclareUniform(UniformName::lightOrientation, "lightOrientation", UniformType::Vec3f); + DeclareUniform(UniformName::light2Radius, "light2Radius", UniformType::Vec2f); + DeclareUniform(UniformName::desaturation, "desaturation", UniformType::Float); + DeclareUniform(UniformName::ignoreNormals, "ignoreNormals", UniformType::Float); + DeclareUniform(UniformName::spotLight, "spotLight", UniformType::Float); + memset(mLastError, 0, sizeof(mLastError)); memset(mReturnError, 0, sizeof(mReturnError)); @@ -592,35 +612,13 @@ void RenderDevice::SetShader(ShaderName name) } } -static const int uniformLocations[(int)UniformName::NumUniforms] = { - 64, // rendersettings - 0, // projection - 108, // desaturation - 80, // highlightcolor - 16, // view - 32, // world - 48, // modelnormal - 68, // FillColor - 72, // vertexColor - 84, // stencilColor - 92, // lightPosAndRadius - 96, // lightOrientation - 100, // light2Radius - 104, // lightColor - 109, // ignoreNormals - 110, // spotLight - 76, // campos, - 112, // texturefactor - 116, // fogsettings - 120, // fogcolor -}; - void RenderDevice::SetUniform(UniformName name, const void* values, int count) { - auto dest = &mUniforms[uniformLocations[(int)name]]; + float* dest = mUniformData.data() + mUniformInfo[(int)name].Offset; if (memcmp(dest, values, sizeof(float) * count) != 0) { memcpy(dest, values, sizeof(float) * count); + mUniformInfo[(int)name].LastUpdate++; mNeedApply = true; mUniformsChanged = true; } @@ -651,7 +649,7 @@ void RenderDevice::ApplyChanges() void RenderDevice::ApplyShader() { Shader* curShader = GetActiveShader(); - if (!curShader->CheckCompile()) + if (!curShader->CheckCompile(this)) { SetError("Failed to bind shader:\r\n%s", curShader->GetCompileError().c_str()); return; @@ -748,35 +746,40 @@ void RenderDevice::ApplyVertexBuffer() CheckGLError(); } +void RenderDevice::DeclareUniform(UniformName name, const char* glslname, UniformType type) +{ + UniformInfo& info = mUniformInfo[(int)name]; + info.Name = glslname; + info.Type = type; + info.Offset = (int)mUniformData.size(); + + mUniformData.resize(mUniformData.size() + (type == UniformType::Matrix ? 16 : 4)); +} + void RenderDevice::ApplyUniforms() { Shader* shader = GetActiveShader(); auto& locations = shader->UniformLocations; + auto& lastupdates = shader->UniformLastUpdates; - glUniformMatrix4fv(locations[(int)UniformName::projection], 1, GL_FALSE, &mUniforms[0].valuef); - glUniformMatrix4fv(locations[(int)UniformName::view], 1, GL_FALSE, &mUniforms[16].valuef); - glUniformMatrix4fv(locations[(int)UniformName::world], 1, GL_FALSE, &mUniforms[32].valuef); - glUniformMatrix4fv(locations[(int)UniformName::modelnormal], 1, GL_FALSE, &mUniforms[48].valuef); - - glUniform4fv(locations[(int)UniformName::rendersettings], 1, &mUniforms[64].valuef); - glUniform4fv(locations[(int)UniformName::FillColor], 1, &mUniforms[68].valuef); - glUniform4fv(locations[(int)UniformName::vertexColor], 1, &mUniforms[72].valuef); - glUniform4fv(locations[(int)UniformName::campos], 1, &mUniforms[76].valuef); - glUniform4fv(locations[(int)UniformName::highlightcolor], 1, &mUniforms[80].valuef); - glUniform4fv(locations[(int)UniformName::stencilColor], 1, &mUniforms[84].valuef); - glUniform4fv(locations[(int)UniformName::lightColor], 1, &mUniforms[88].valuef); - glUniform4fv(locations[(int)UniformName::lightPosAndRadius], 1, &mUniforms[92].valuef); - glUniform3fv(locations[(int)UniformName::lightOrientation], 1, &mUniforms[96].valuef); - glUniform2fv(locations[(int)UniformName::light2Radius], 1, &mUniforms[100].valuef); - glUniform4fv(locations[(int)UniformName::lightColor], 1, &mUniforms[104].valuef); - - glUniform1fv(locations[(int)UniformName::desaturation], 1, &mUniforms[108].valuef); - glUniform1fv(locations[(int)UniformName::ignoreNormals], 1, &mUniforms[109].valuef); - glUniform1fv(locations[(int)UniformName::spotLight], 1, &mUniforms[110].valuef); - - glUniform4fv(locations[(int)UniformName::texturefactor], 1, &mUniforms[112].valuef); - glUniform4fv(locations[(int)UniformName::fogsettings], 1, &mUniforms[116].valuef); - glUniform4fv(locations[(int)UniformName::fogcolor], 1, &mUniforms[120].valuef); + for (int i = 0; i < (int)UniformName::NumUniforms; i++) + { + if (lastupdates[i] != mUniformInfo[i].LastUpdate) + { + float* data = mUniformData.data() + mUniformInfo[i].Offset; + GLuint location = locations[i]; + switch (mUniformInfo[i].Type) + { + default: + case UniformType::Vec4f: glUniform4fv(location, 1, data); break; + case UniformType::Vec3f: glUniform3fv(location, 1, data); break; + case UniformType::Vec2f: glUniform2fv(location, 1, data); break; + case UniformType::Float: glUniform1fv(location, 1, data); break; + case UniformType::Matrix: glUniformMatrix4fv(location, 1, GL_FALSE, data); break; + } + lastupdates[i] = mUniformInfo[i].LastUpdate; + } + } mUniformsChanged = false; diff --git a/Source/Native/RenderDevice.h b/Source/Native/RenderDevice.h index 9c14753e..a0990712 100644 --- a/Source/Native/RenderDevice.h +++ b/Source/Native/RenderDevice.h @@ -1,6 +1,7 @@ #pragma once #include "OpenGLContext.h" +#include class SharedVertexBuffer; class VertexBuffer; @@ -176,14 +177,27 @@ public: std::unique_ptr mShaderManager; ShaderName mShaderName = ShaderName::display2d_normal; + enum class UniformType { Matrix, Vec4f, Vec3f, Vec2f, Float }; + + struct UniformInfo + { + std::string Name; + UniformType Type = {}; + int Offset = 0; + int LastUpdate = 0; + }; + + UniformInfo mUniformInfo[(int)UniformName::NumUniforms]; + std::vector mUniformData; + + void DeclareUniform(UniformName name, const char* glslname, UniformType type); + union UniformEntry { float valuef; int32_t valuei; }; - UniformEntry mUniforms[4 * 16 + 15 * 4]; - GLuint mStreamVertexBuffer = 0; GLuint mStreamVAO = 0; diff --git a/Source/Native/Shader.cpp b/Source/Native/Shader.cpp index 6bce91a7..3b5f61f2 100644 --- a/Source/Native/Shader.cpp +++ b/Source/Native/Shader.cpp @@ -12,13 +12,13 @@ void Shader::Setup(const std::string& identifier, const std::string& vertexShade mAlphatest = alphatest; } -bool Shader::CheckCompile() +bool Shader::CheckCompile(RenderDevice* device) { bool firstCall = !mProgramBuilt; if (firstCall) { mProgramBuilt = true; - CreateProgram(); + CreateProgram(device); glUseProgram(mProgram); glUniform1i(glGetUniformLocation(mProgram, "texture1"), 0); glUseProgram(0); @@ -54,7 +54,7 @@ void Shader::Bind() glUseProgram(mProgram); } -void Shader::CreateProgram() +void Shader::CreateProgram(RenderDevice* device) { const char* prefixNAT = R"( #version 150 @@ -104,32 +104,12 @@ void Shader::CreateProgram() return; } - static const char* names[(int)UniformName::NumUniforms] = { - "rendersettings", - "projection", - "desaturation", - "highlightcolor", - "view", - "world", - "modelnormal", - "fillColor", - "vertexColor", - "stencilColor", - "lightPosAndRadius", - "lightOrientation", - "light2Radius", - "lightColor", - "ignoreNormals", - "spotLight", - "campos", - "texturefactor", - "fogsettings", - "fogcolor" - }; - for (int i = 0; i < (int)UniformName::NumUniforms; i++) { - UniformLocations[i] = glGetUniformLocation(mProgram, names[i]); + if (!device->mUniformInfo[i].Name.empty()) + UniformLocations[i] = glGetUniformLocation(mProgram, device->mUniformInfo[i].Name.c_str()); + else + UniformLocations[i] = (GLuint)-1; } } diff --git a/Source/Native/Shader.h b/Source/Native/Shader.h index 7304fc62..4bea95c0 100644 --- a/Source/Native/Shader.h +++ b/Source/Native/Shader.h @@ -12,16 +12,17 @@ public: void ReleaseResources(); void Setup(const std::string& identifier, const std::string& vertexShader, const std::string& fragmentShader, bool alphatest); - bool CheckCompile(); + bool CheckCompile(RenderDevice *device); void Bind(); std::string GetIdentifier(); std::string GetCompileError(); + int UniformLastUpdates[(int)UniformName::NumUniforms] = { 0 }; GLuint UniformLocations[(int)UniformName::NumUniforms] = { 0 }; private: - void CreateProgram(); + void CreateProgram(RenderDevice* device); GLuint CompileShader(const std::string& code, GLenum type); std::string mIdentifier;