diff --git a/src/libprojectM/MilkdropPreset/BlurTexture.cpp b/src/libprojectM/MilkdropPreset/BlurTexture.cpp index daa1033d2..6cc33660a 100644 --- a/src/libprojectM/MilkdropPreset/BlurTexture.cpp +++ b/src/libprojectM/MilkdropPreset/BlurTexture.cpp @@ -1,9 +1,12 @@ #include "BlurTexture.hpp" #include "PerFrameContext.hpp" +#include "PresetState.hpp" #include "MilkdropStaticShaders.hpp" +#include "Renderer/ShaderCache.hpp" + #include namespace libprojectM { @@ -12,14 +15,6 @@ namespace MilkdropPreset { BlurTexture::BlurTexture() : m_blurSampler(std::make_shared(GL_CLAMP_TO_EDGE, GL_LINEAR)) { - auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); - - // Compile shader sources - m_blur1Shader.CompileProgram(staticShaders->GetBlurVertexShader(), - staticShaders->GetBlur1FragmentShader()); - m_blur2Shader.CompileProgram(staticShaders->GetBlurVertexShader(), - staticShaders->GetBlur2FragmentShader()); - m_blurFramebuffer.CreateColorAttachment(0, 0); // Initialize Blur VAO/VBO with a single fullscreen quad. @@ -65,6 +60,33 @@ BlurTexture::~BlurTexture() glDeleteVertexArrays(1, &m_vaoBlur); } +void BlurTexture::Initialize(const Renderer::RenderContext& renderContext) +{ + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); + + // Load/compile shader sources + auto blur1Shader = renderContext.shaderCache->Get("milkdrop_blur1"); + if (!blur1Shader) + { + blur1Shader = std::make_shared(); + blur1Shader->CompileProgram(staticShaders->GetBlurVertexShader(), + staticShaders->GetBlur1FragmentShader()); + renderContext.shaderCache->Insert("milkdrop_blur1", blur1Shader); + } + + auto blur2Shader = renderContext.shaderCache->Get("milkdrop_blur2"); + if (!blur2Shader) + { + blur2Shader = std::make_shared(); + blur2Shader->CompileProgram(staticShaders->GetBlurVertexShader(), + staticShaders->GetBlur2FragmentShader()); + renderContext.shaderCache->Insert("milkdrop_blur2", blur2Shader); + } + + m_blur1Shader = blur1Shader; + m_blur2Shader = blur2Shader; +} + void BlurTexture::SetRequiredBlurLevel(BlurTexture::BlurLevel level) { m_blurLevel = std::max(level, m_blurLevel); @@ -152,15 +174,20 @@ void BlurTexture::Update(const Renderer::Texture& sourceTexture, const PerFrameC } // set pixel shader - Renderer::Shader* blurShader; + std::shared_ptr blurShader; if ((pass % 2) == 0) { - blurShader = &m_blur1Shader; + blurShader = m_blur1Shader.lock(); } else { - blurShader = &m_blur2Shader; + blurShader = m_blur2Shader.lock(); } + if (!blurShader) + { + return; + } + blurShader->Bind(); blurShader->SetUniformInt("texture_sampler", 0); @@ -205,10 +232,10 @@ void BlurTexture::Update(const Renderer::Texture& sourceTexture, const PerFrameC //float4 _c2; // d1..d4 //float4 _c3; // scale, bias, w_div, 0 //------------------------------------- - m_blur1Shader.SetUniformFloat4("_c0", {srcWidth, srcHeight, 1.0f / srcWidth, 1.0f / srcHeight}); - m_blur1Shader.SetUniformFloat4("_c1", {w1, w2, w3, w4}); - m_blur1Shader.SetUniformFloat4("_c2", {d1, d2, d3, d4}); - m_blur1Shader.SetUniformFloat4("_c3", {scaleNow, biasNow, w_div, 0.0}); + blurShader->SetUniformFloat4("_c0", {srcWidth, srcHeight, 1.0f / srcWidth, 1.0f / srcHeight}); + blurShader->SetUniformFloat4("_c1", {w1, w2, w3, w4}); + blurShader->SetUniformFloat4("_c2", {d1, d2, d3, d4}); + blurShader->SetUniformFloat4("_c3", {scaleNow, biasNow, w_div, 0.0}); } else { @@ -224,19 +251,19 @@ void BlurTexture::Update(const Renderer::Texture& sourceTexture, const PerFrameC //float4 _c5; // w1,w2,d1,d2 //float4 _c6; // w_div, edge_darken_c1, edge_darken_c2, edge_darken_c3 //------------------------------------- - m_blur2Shader.SetUniformFloat4("_c0", {srcWidth, srcHeight, 1.0f / srcWidth, 1.0f / srcHeight}); - m_blur2Shader.SetUniformFloat4("_c5", {w1, w2, d1, d2}); + blurShader->SetUniformFloat4("_c0", {srcWidth, srcHeight, 1.0f / srcWidth, 1.0f / srcHeight}); + blurShader->SetUniformFloat4("_c5", {w1, w2, d1, d2}); // note: only do this first time; if you do it many times, // then the super-blurred levels will have big black lines along the top & left sides. if (pass == 1) { // Darken edges - m_blur2Shader.SetUniformFloat4("_c6", {w_div, (1 - blur1EdgeDarken), blur1EdgeDarken, 5.0f}); + blurShader->SetUniformFloat4("_c6", {w_div, (1 - blur1EdgeDarken), blur1EdgeDarken, 5.0f}); } else { // Don't darken - m_blur2Shader.SetUniformFloat4("_c6", {w_div, 1.0f, 0.0f, 5.0f}); + blurShader->SetUniformFloat4("_c6", {w_div, 1.0f, 0.0f, 5.0f}); } } diff --git a/src/libprojectM/MilkdropPreset/BlurTexture.hpp b/src/libprojectM/MilkdropPreset/BlurTexture.hpp index 2f6a7998e..edf63660e 100644 --- a/src/libprojectM/MilkdropPreset/BlurTexture.hpp +++ b/src/libprojectM/MilkdropPreset/BlurTexture.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include @@ -49,6 +50,12 @@ public: */ ~BlurTexture(); + /** + * @brief Initializes the blur texture. + * @param renderContext + */ + void Initialize(const Renderer::RenderContext& renderContext); + /** * @brief Sets the minimum required blur level. * If the current level isn't high enough, it'll be increased. @@ -101,8 +108,8 @@ private: GLuint m_vboBlur; //!< Vertex buffer object for the fullscreen blur quad. GLuint m_vaoBlur; //!< Vertex array object for the fullscreen blur quad. - Renderer::Shader m_blur1Shader; //!< The shader used on the first blur pass. - Renderer::Shader m_blur2Shader; //!< The shader used for subsequent blur passes after the initial pass. + std::weak_ptr m_blur1Shader; //!< The shader used on the first blur pass. + std::weak_ptr m_blur2Shader; //!< The shader used for subsequent blur passes after the initial pass. int m_sourceTextureWidth{}; //!< Width of the source texture used to create the blur textures. int m_sourceTextureHeight{}; //!< Height of the source texture used to create the blur textures. diff --git a/src/libprojectM/MilkdropPreset/Border.cpp b/src/libprojectM/MilkdropPreset/Border.cpp index 57b34c7cf..2cebe2a54 100644 --- a/src/libprojectM/MilkdropPreset/Border.cpp +++ b/src/libprojectM/MilkdropPreset/Border.cpp @@ -33,8 +33,9 @@ void Border::Draw(const PerFrameContext& presetPerFrameContext) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); std::array vertices{}; for (int border = 0; border < 2; border++) diff --git a/src/libprojectM/MilkdropPreset/CustomShape.cpp b/src/libprojectM/MilkdropPreset/CustomShape.cpp index d88a1e946..80d440f6a 100644 --- a/src/libprojectM/MilkdropPreset/CustomShape.cpp +++ b/src/libprojectM/MilkdropPreset/CustomShape.cpp @@ -192,9 +192,10 @@ void CustomShape::Draw() if (static_cast(*m_perFrameContext.textured) != 0) { - m_presetState.texturedShader.Bind(); - m_presetState.texturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); - m_presetState.texturedShader.SetUniformInt("texture_sampler", 0); + auto shader = m_presetState.texturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformInt("texture_sampler", 0); // Textured shape, either main texture or texture from "image" key auto textureAspectY = m_presetState.renderContext.aspectY; @@ -208,7 +209,7 @@ void CustomShape::Draw() auto desc = m_presetState.renderContext.textureManager->GetTexture(m_image); if (!desc.Empty()) { - desc.Bind(0, m_presetState.texturedShader); + desc.Bind(0, *shader); textureAspectY = 1.0f; } else @@ -251,8 +252,9 @@ void CustomShape::Draw() glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(TexturedPoint) * (sides + 2), vertexData.data()); - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); glBindVertexArray(m_vaoIdUntextured); glDrawArrays(GL_TRIANGLE_FAN, 0, sides + 2); @@ -269,8 +271,9 @@ void CustomShape::Draw() points[i].y = vertexData[i + 1].y; } - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); glVertexAttrib4f(1, static_cast(*m_perFrameContext.border_r), diff --git a/src/libprojectM/MilkdropPreset/CustomWaveform.cpp b/src/libprojectM/MilkdropPreset/CustomWaveform.cpp index d9d0937f6..f264ec8b3 100644 --- a/src/libprojectM/MilkdropPreset/CustomWaveform.cpp +++ b/src/libprojectM/MilkdropPreset/CustomWaveform.cpp @@ -182,8 +182,9 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); auto iterations = (m_drawThick && !m_useDots) ? 4 : 1; diff --git a/src/libprojectM/MilkdropPreset/DarkenCenter.cpp b/src/libprojectM/MilkdropPreset/DarkenCenter.cpp index 5e5efac74..64899b324 100644 --- a/src/libprojectM/MilkdropPreset/DarkenCenter.cpp +++ b/src/libprojectM/MilkdropPreset/DarkenCenter.cpp @@ -44,8 +44,9 @@ void DarkenCenter::Draw() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); glDrawArrays(GL_TRIANGLE_FAN, 0, 6); diff --git a/src/libprojectM/MilkdropPreset/Filters.cpp b/src/libprojectM/MilkdropPreset/Filters.cpp index 9c70904a1..472a0e70b 100644 --- a/src/libprojectM/MilkdropPreset/Filters.cpp +++ b/src/libprojectM/MilkdropPreset/Filters.cpp @@ -29,8 +29,9 @@ void Filters::Draw() glEnable(GL_BLEND); - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); glBindVertexArray(m_vaoID); glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0); diff --git a/src/libprojectM/MilkdropPreset/MilkdropPreset.cpp b/src/libprojectM/MilkdropPreset/MilkdropPreset.cpp index d2c3e5473..00023d1fa 100755 --- a/src/libprojectM/MilkdropPreset/MilkdropPreset.cpp +++ b/src/libprojectM/MilkdropPreset/MilkdropPreset.cpp @@ -59,6 +59,8 @@ void MilkdropPreset::Initialize(const Renderer::RenderContext& renderContext) { assert(renderContext.textureManager); m_state.renderContext = renderContext; + m_state.blurTexture.Initialize(renderContext); + m_state.LoadShaders(); // Initialize variables and code now we have a proper render state. CompileCodeAndRunInitExpressions(); diff --git a/src/libprojectM/MilkdropPreset/MotionVectors.cpp b/src/libprojectM/MilkdropPreset/MotionVectors.cpp index cf165cbd9..3ec34e17e 100644 --- a/src/libprojectM/MilkdropPreset/MotionVectors.cpp +++ b/src/libprojectM/MilkdropPreset/MotionVectors.cpp @@ -2,6 +2,7 @@ #include "MilkdropStaticShaders.hpp" +#include #include namespace libprojectM { @@ -11,9 +12,6 @@ MotionVectors::MotionVectors(PresetState& presetState) : RenderItem() , m_presetState(presetState) { - auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); - m_motionVectorShader.CompileProgram(staticShaders->GetPresetMotionVectorsVertexShader(), - staticShaders->GetUntexturedDrawFragmentShader()); RenderItem::Init(); } @@ -89,12 +87,13 @@ void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext, std::shar glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - m_motionVectorShader.Bind(); - m_motionVectorShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); - m_motionVectorShader.SetUniformFloat("length_multiplier", static_cast(*presetPerFrameContext.mv_l)); - m_motionVectorShader.SetUniformFloat("minimum_length", minimumLength); + auto shader = GetShader(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformFloat("length_multiplier", static_cast(*presetPerFrameContext.mv_l)); + shader->SetUniformFloat("minimum_length", minimumLength); - m_motionVectorShader.SetUniformInt("warp_coordinates", 0); + shader->SetUniformInt("warp_coordinates", 0); motionTexture->Bind(0, m_sampler); @@ -162,5 +161,29 @@ void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext, std::shar glDisable(GL_BLEND); } +std::shared_ptr MotionVectors::GetShader() +{ + auto shader = m_motionVectorShader.lock(); + if (!shader) + { + shader = m_presetState.renderContext.shaderCache->Get("milkdrop_motion_vectors"); + } + if (!shader) + { + // First use, compile and cache. + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); + + shader = std::make_shared(); + shader->CompileProgram(staticShaders->GetPresetMotionVectorsVertexShader(), + staticShaders->GetUntexturedDrawFragmentShader()); + + m_presetState.renderContext.shaderCache->Insert("milkdrop_motion_vectors", shader); + } + + m_motionVectorShader = shader; + + return shader; +} + } // namespace MilkdropPreset } // namespace libprojectM diff --git a/src/libprojectM/MilkdropPreset/MotionVectors.hpp b/src/libprojectM/MilkdropPreset/MotionVectors.hpp index 6ceb940df..4782e03ad 100644 --- a/src/libprojectM/MilkdropPreset/MotionVectors.hpp +++ b/src/libprojectM/MilkdropPreset/MotionVectors.hpp @@ -36,16 +36,17 @@ public: void Draw(const PerFrameContext& presetPerFrameContext, std::shared_ptr motionTexture); private: - struct MotionVectorVertex - { + struct MotionVectorVertex { float x{}; float y{}; int32_t index{}; }; + std::shared_ptr GetShader(); + PresetState& m_presetState; //!< The global preset state. - Renderer::Shader m_motionVectorShader; //!< The motion vector shader, calculates the trace positions in the GPU. + std::weak_ptr m_motionVectorShader; //!< The motion vector shader, calculates the trace positions in the GPU. std::shared_ptr m_sampler{std::make_shared(GL_CLAMP_TO_EDGE, GL_LINEAR)}; //!< The texture sampler. int m_lastVertexCount{}; //!< Number of vertices drawn in the previous draw call. diff --git a/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp b/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp index 8f0f49a2f..5ad57c28d 100644 --- a/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp +++ b/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp @@ -6,6 +6,8 @@ #include "PerPixelContext.hpp" #include "PresetState.hpp" +#include "Renderer/ShaderCache.hpp" + #include #include @@ -22,10 +24,6 @@ PerPixelMesh::PerPixelMesh() : RenderItem() { RenderItem::Init(); - - auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); - m_perPixelMeshShader.CompileProgram(staticShaders->GetPresetWarpVertexShader(), - staticShaders->GetPresetWarpFragmentShader()); } void PerPixelMesh::InitVertexAttrib() @@ -80,7 +78,7 @@ void PerPixelMesh::LoadWarpShader(const PresetState& presetState) #ifdef MILKDROP_PRESET_DEBUG std::cerr << "[Warp Shader] Error loading warp shader code:" << ex.message() << std::endl; #else - (void)ex; // silence unused parameter warning + (void) ex; // silence unused parameter warning #endif m_warpShader.reset(); } @@ -104,7 +102,7 @@ void PerPixelMesh::CompileWarpShader(PresetState& presetState) #ifdef MILKDROP_PRESET_DEBUG std::cerr << "[Warp Shader] Error compiling warp shader code:" << ex.message() << std::endl; #else - (void)ex; // silence unused parameter warning + (void) ex; // silence unused parameter warning #endif m_warpShader.reset(); } @@ -321,18 +319,19 @@ void PerPixelMesh::WarpedBlit(const PresetState& presetState, if (!m_warpShader) { - m_perPixelMeshShader.Bind(); - m_perPixelMeshShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); - m_perPixelMeshShader.SetUniformInt("texture_sampler", 0); - m_perPixelMeshShader.SetUniformFloat4("aspect", {presetState.renderContext.aspectX, - presetState.renderContext.aspectY, - presetState.renderContext.invAspectX, - presetState.renderContext.invAspectY}); - m_perPixelMeshShader.SetUniformFloat("warpTime", warpTime); - m_perPixelMeshShader.SetUniformFloat("warpScaleInverse", warpScaleInverse); - m_perPixelMeshShader.SetUniformFloat4("warpFactors", warpFactors); - m_perPixelMeshShader.SetUniformFloat2("texelOffset", texelOffsets); - m_perPixelMeshShader.SetUniformFloat("decay", decay); + auto perPixelMeshShader = GetDefaultWarpShader(presetState); + perPixelMeshShader->Bind(); + perPixelMeshShader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + perPixelMeshShader->SetUniformInt("texture_sampler", 0); + perPixelMeshShader->SetUniformFloat4("aspect", {presetState.renderContext.aspectX, + presetState.renderContext.aspectY, + presetState.renderContext.invAspectX, + presetState.renderContext.invAspectY}); + perPixelMeshShader->SetUniformFloat("warpTime", warpTime); + perPixelMeshShader->SetUniformFloat("warpScaleInverse", warpScaleInverse); + perPixelMeshShader->SetUniformFloat4("warpFactors", warpFactors); + perPixelMeshShader->SetUniformFloat2("texelOffset", texelOffsets); + perPixelMeshShader->SetUniformFloat("decay", decay); } else { @@ -399,5 +398,31 @@ void PerPixelMesh::WarpedBlit(const PresetState& presetState, Renderer::Shader::Unbind(); } +auto PerPixelMesh::GetDefaultWarpShader(const PresetState& presetState) -> std::shared_ptr +{ + auto perPixelMeshShader = m_perPixelMeshShader.lock(); + if (perPixelMeshShader) + { + return perPixelMeshShader; + } + + perPixelMeshShader = presetState.renderContext.shaderCache->Get("milkdrop_default_warp_shader"); + if (perPixelMeshShader) + { + return perPixelMeshShader; + } + + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); + + perPixelMeshShader = std::make_shared(); + perPixelMeshShader->CompileProgram(staticShaders->GetPresetWarpVertexShader(), + staticShaders->GetPresetWarpFragmentShader()); + + presetState.renderContext.shaderCache->Insert("milkdrop_default_warp_shader", perPixelMeshShader); + m_perPixelMeshShader = perPixelMeshShader; + + return perPixelMeshShader; +} + } // namespace MilkdropPreset } // namespace libprojectM diff --git a/src/libprojectM/MilkdropPreset/PerPixelMesh.hpp b/src/libprojectM/MilkdropPreset/PerPixelMesh.hpp index 6dcef4299..98576d30a 100644 --- a/src/libprojectM/MilkdropPreset/PerPixelMesh.hpp +++ b/src/libprojectM/MilkdropPreset/PerPixelMesh.hpp @@ -111,6 +111,13 @@ private: */ void WarpedBlit(const PresetState& presetState, const PerFrameContext& perFrameContext); + /** + * @brief Creates or retrieves the default warp shader. + * @param presetState The preset state to retrieve the rendering context from. + * @return A shared pointer to the default warp shader instance. + */ + auto GetDefaultWarpShader(const PresetState& presetState) -> std::shared_ptr; + int m_gridSizeX{}; //!< Warp mesh X resolution. int m_gridSizeY{}; //!< Warp mesh Y resolution. @@ -122,8 +129,8 @@ private: std::vector m_listIndices; //!< List of vertex indices to render. VertexList m_drawVertices; //!< Temp data buffer for the vertices to be drawn. - Renderer::Shader m_perPixelMeshShader; //!< Special shader which calculates the per-pixel UV coordinates. - std::unique_ptr m_warpShader; //!< The warp shader. Either preset-defined or a default shader. + std::weak_ptr m_perPixelMeshShader; //!< Special shader which calculates the per-pixel UV coordinates. + std::unique_ptr m_warpShader; //!< The warp shader. Either preset-defined or a default shader. Renderer::Sampler m_perPixelSampler{GL_CLAMP_TO_EDGE, GL_LINEAR}; //!< The main texture sampler. }; diff --git a/src/libprojectM/MilkdropPreset/PresetState.cpp b/src/libprojectM/MilkdropPreset/PresetState.cpp index 7ff872a55..71989fe61 100644 --- a/src/libprojectM/MilkdropPreset/PresetState.cpp +++ b/src/libprojectM/MilkdropPreset/PresetState.cpp @@ -3,6 +3,8 @@ #include "MilkdropStaticShaders.hpp" #include "PresetFileParser.hpp" +#include "Renderer/ShaderCache.hpp" + #include #include @@ -16,12 +18,6 @@ const glm::mat4 PresetState::orthogonalProjectionFlipped = glm::ortho(-1.0f, 1.0 PresetState::PresetState() : globalMemory(projectm_eval_memory_buffer_create()) { - auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); - untexturedShader.CompileProgram(staticShaders->GetUntexturedDrawVertexShader(), - staticShaders->GetUntexturedDrawFragmentShader()); - texturedShader.CompileProgram(staticShaders->GetTexturedDrawVertexShader(), - staticShaders->GetTexturedDrawFragmentShader()); - std::random_device randomDevice; std::mt19937 randomGenerator(randomDevice()); std::uniform_int_distribution<> distrib(0, std::numeric_limits::max()); @@ -164,5 +160,30 @@ void PresetState::Initialize(PresetFileParser& parsedFile) compositeShader = parsedFile.GetCode("comp_"); } +void PresetState::LoadShaders() +{ + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); + + auto untexturedShaderShared = renderContext.shaderCache->Get("milkdrop_generic_untextured"); + if (!untexturedShaderShared) + { + untexturedShaderShared = std::make_shared(); + untexturedShaderShared->CompileProgram(staticShaders->GetUntexturedDrawVertexShader(), + staticShaders->GetUntexturedDrawFragmentShader()); + renderContext.shaderCache->Insert("milkdrop_generic_untextured", untexturedShaderShared); + } + untexturedShader = untexturedShaderShared; + + auto texturedShaderShared = renderContext.shaderCache->Get("milkdrop_generic_textured"); + if (!texturedShaderShared) + { + texturedShaderShared = std::make_shared(); + texturedShaderShared->CompileProgram(staticShaders->GetTexturedDrawVertexShader(), + staticShaders->GetTexturedDrawFragmentShader()); + renderContext.shaderCache->Insert("milkdrop_generic_textured", texturedShaderShared); + } + texturedShader = texturedShaderShared; +} + } // namespace MilkdropPreset } // namespace libprojectM diff --git a/src/libprojectM/MilkdropPreset/PresetState.hpp b/src/libprojectM/MilkdropPreset/PresetState.hpp index 921b46d79..57b5faecf 100644 --- a/src/libprojectM/MilkdropPreset/PresetState.hpp +++ b/src/libprojectM/MilkdropPreset/PresetState.hpp @@ -45,6 +45,12 @@ public: */ void Initialize(PresetFileParser& parsedFile); + /** + * @brief Loads or compiles the generic shaders. + * Call after setting renderContext. + */ + void LoadShaders(); + BlendableFloat gammaAdj{2.0f}; BlendableFloat videoEchoZoom{2.0f}; BlendableFloat videoEchoAlpha{0.0f}; @@ -147,8 +153,8 @@ public: std::string warpShader; //!< Warp shader code. std::string compositeShader; //!< Composite shader code. - Renderer::Shader untexturedShader; //!< Shader used to draw untextured primitives, e.g. waveforms. - Renderer::Shader texturedShader; //!< Shader used to draw textured primitives, e.g. textured shapes and the warp mesh. + std::weak_ptr untexturedShader; //!< Shader used to draw untextured primitives, e.g. waveforms. + std::weak_ptr texturedShader; //!< Shader used to draw textured primitives, e.g. textured shapes and the warp mesh. std::weak_ptr mainTexture; //!< A weak reference to the main texture in the preset framebuffer. BlurTexture blurTexture; //!< The blur textures used in this preset. Contents depend on the shader code using GetBlurX(). diff --git a/src/libprojectM/MilkdropPreset/VideoEcho.cpp b/src/libprojectM/MilkdropPreset/VideoEcho.cpp index bf7d4af97..9bf9ae4f2 100644 --- a/src/libprojectM/MilkdropPreset/VideoEcho.cpp +++ b/src/libprojectM/MilkdropPreset/VideoEcho.cpp @@ -68,9 +68,10 @@ void VideoEcho::Draw() m_vertices[i].a = 1.0f; } - m_presetState.texturedShader.Bind(); - m_presetState.texturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); - m_presetState.texturedShader.SetUniformInt("texture_sampler", 0); + auto shader = m_presetState.texturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + shader->SetUniformInt("texture_sampler", 0); auto mainTexture = m_presetState.mainTexture.lock(); if (mainTexture) diff --git a/src/libprojectM/MilkdropPreset/Waveform.cpp b/src/libprojectM/MilkdropPreset/Waveform.cpp index 80e09e406..ce4351784 100644 --- a/src/libprojectM/MilkdropPreset/Waveform.cpp +++ b/src/libprojectM/MilkdropPreset/Waveform.cpp @@ -54,8 +54,9 @@ void Waveform::Draw(const PerFrameContext& presetPerFrameContext) #endif glLineWidth(1); - m_presetState.untexturedShader.Bind(); - m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); + auto shader = m_presetState.untexturedShader.lock(); + shader->Bind(); + shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection); glBindVertexArray(m_vaoID); glBindBuffer(GL_ARRAY_BUFFER, m_vboID);