diff --git a/src/libprojectM/MilkdropPreset/BlurTexture.cpp b/src/libprojectM/MilkdropPreset/BlurTexture.cpp index 5de6e7740..b66a55fe7 100644 --- a/src/libprojectM/MilkdropPreset/BlurTexture.cpp +++ b/src/libprojectM/MilkdropPreset/BlurTexture.cpp @@ -3,18 +3,20 @@ #include "PerFrameContext.hpp" #include "PresetState.hpp" -#include +#include "MilkdropStaticShaders.hpp" #include 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(StaticGlShaders::Get()->GetBlurVertexShader(), - StaticGlShaders::Get()->GetBlur1FragmentShader()); - m_blur2Shader.CompileProgram(StaticGlShaders::Get()->GetBlurVertexShader(), - StaticGlShaders::Get()->GetBlur2FragmentShader()); + m_blur1Shader.CompileProgram(staticShaders->GetBlurVertexShader(), + staticShaders->GetBlur1FragmentShader()); + m_blur2Shader.CompileProgram(staticShaders->GetBlurVertexShader(), + staticShaders->GetBlur2FragmentShader()); m_blurFramebuffer.CreateColorAttachment(0, 0); diff --git a/src/libprojectM/MilkdropPreset/CMakeLists.txt b/src/libprojectM/MilkdropPreset/CMakeLists.txt index fdb961a19..07ed87155 100644 --- a/src/libprojectM/MilkdropPreset/CMakeLists.txt +++ b/src/libprojectM/MilkdropPreset/CMakeLists.txt @@ -1,7 +1,45 @@ # Debugging options, for development purposes. option(ENABLE_DEBUG_MILKDROP_PRESET "Enable STDERR debug output in Milkdrop preset code (Debug builds only)" OFF) +set(SHADER_FILES + Shaders/Blur1FragmentShaderGlsl330.frag + Shaders/Blur2FragmentShaderGlsl330.frag + Shaders/BlurVertexShaderGlsl330.vert + Shaders/PresetCompVertexShaderGlsl330.vert + Shaders/PresetMotionVectorsVertexShaderGlsl330.vert + Shaders/PresetShaderHeaderGlsl330.inc + Shaders/PresetWarpFragmentShaderGlsl330.frag + Shaders/PresetWarpVertexShaderGlsl330.vert + Shaders/V2fC4fFragmentShaderGlsl330.frag + Shaders/V2fC4fT2fFragmentShaderGlsl330.frag + Shaders/V2fC4fT2fVertexShaderGlsl330.vert + Shaders/V2fC4fVertexShaderGlsl330.vert + ) + +string(REPLACE ";" "\\;" SHADER_FILES_ARG "${SHADER_FILES}") +add_custom_command(OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/MilkdropStaticShaders.cpp + ${CMAKE_CURRENT_BINARY_DIR}/MilkdropStaticShaders.hpp + + COMMAND ${CMAKE_COMMAND} + + ARGS + -D SHADER_FILES="${SHADER_FILES_ARG}" + -D OUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/GenerateStaticShaders.cmake + + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS # Files watched for changes: + ${SHADER_FILES} + MilkdropStaticShaders.cpp.in + MilkdropStaticShaders.hpp.in + GenerateStaticShaders.cmake + ) + add_library(MilkdropPreset OBJECT + ${SHADER_FILES} + ${CMAKE_CURRENT_BINARY_DIR}/MilkdropStaticShaders.cpp + ${CMAKE_CURRENT_BINARY_DIR}/MilkdropStaticShaders.hpp BlurTexture.cpp BlurTexture.hpp Border.cpp @@ -16,6 +54,8 @@ add_library(MilkdropPreset OBJECT EvalLibMutex.cpp Filters.cpp Filters.hpp + FinalComposite.cpp + FinalComposite.hpp IdlePreset.cpp IdlePreset.hpp MilkdropNoise.cpp @@ -27,6 +67,8 @@ add_library(MilkdropPreset OBJECT MilkdropPresetFactory.hpp MilkdropShader.cpp MilkdropShader.hpp + MilkdropStaticShaders.cpp.in + MilkdropStaticShaders.hpp.in MotionVectors.cpp MotionVectors.hpp PerFrameContext.cpp @@ -50,13 +92,14 @@ add_library(MilkdropPreset OBJECT WaveformPerFrameContext.hpp WaveformPerPointContext.cpp WaveformPerPointContext.hpp - FinalComposite.cpp FinalComposite.hpp) + ) target_include_directories(MilkdropPreset PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/.." PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}" ) target_link_libraries(MilkdropPreset diff --git a/src/libprojectM/MilkdropPreset/Filters.cpp b/src/libprojectM/MilkdropPreset/Filters.cpp index 72c2b1770..9f86d4b2e 100644 --- a/src/libprojectM/MilkdropPreset/Filters.cpp +++ b/src/libprojectM/MilkdropPreset/Filters.cpp @@ -2,8 +2,6 @@ #include "projectM-opengl.h" -#include "Renderer/ShaderEngine.hpp" - Filters::Filters(const PresetState& presetState) : RenderItem() , m_presetState(presetState) diff --git a/src/libprojectM/MilkdropPreset/GenerateStaticShaders.cmake b/src/libprojectM/MilkdropPreset/GenerateStaticShaders.cmake new file mode 100644 index 000000000..f579f1f19 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/GenerateStaticShaders.cmake @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.20 FATAL_ERROR) + +# Run as custom command in script mode if any shader file has changed. +# Recreates the MilkdropStaticShaders.h/.cpp files accordingly. + +set(STATIC_SHADER_CONTENTS "") +set(STATIC_SHADER_ACCESSOR_DECLARATIONS "") +set(STATIC_SHADER_ACCESSOR_DEFINITIONS "") +foreach(shader_file IN LISTS SHADER_FILES) + cmake_path(GET shader_file FILENAME _shader_name) + cmake_path(GET shader_file EXTENSION _shader_type) + cmake_path(REMOVE_EXTENSION _shader_name) + file(READ "${shader_file}" _shader_contents) + + string(REGEX REPLACE "Glsl([0-9]+)" "" _accessor_name ${_shader_name}) + + string(APPEND STATIC_SHADER_CONTENTS "static std::string k${_shader_name} = R\"(\n${_shader_contents})\";\n\n") + string(APPEND STATIC_SHADER_ACCESSOR_DECLARATIONS " std::string Get${_accessor_name}();\n") + + if(_shader_type STREQUAL ".inc") + # Includes don't get the header prepended. + string(APPEND STATIC_SHADER_ACCESSOR_DEFINITIONS "DECLARE_SHADER_ACCESSOR_NO_HEADER(${_accessor_name});\n") + else() + string(APPEND STATIC_SHADER_ACCESSOR_DEFINITIONS "DECLARE_SHADER_ACCESSOR(${_accessor_name});\n") + endif() +endforeach() + +configure_file(MilkdropStaticShaders.hpp.in ${OUTPUT_DIR}/MilkdropStaticShaders.hpp @ONLY) +configure_file(MilkdropStaticShaders.cpp.in ${OUTPUT_DIR}/MilkdropStaticShaders.cpp @ONLY) diff --git a/src/libprojectM/MilkdropPreset/MilkdropShader.cpp b/src/libprojectM/MilkdropPreset/MilkdropShader.cpp index 310da3fd6..49603054d 100644 --- a/src/libprojectM/MilkdropPreset/MilkdropShader.cpp +++ b/src/libprojectM/MilkdropPreset/MilkdropShader.cpp @@ -3,7 +3,7 @@ #include "PerFrameContext.hpp" #include "PresetState.hpp" -#include "Renderer/StaticGlShaders.hpp" +#include #include #include @@ -15,6 +15,8 @@ #include #include +using libprojectM::MilkdropPreset::MilkdropStaticShaders; + static auto floatRand = []() { return static_cast(rand() % 7381) / 7380.0f; }; MilkdropShader::MilkdropShader(ShaderType type) @@ -407,7 +409,7 @@ void MilkdropShader::PreprocessPresetShader(std::string& program) // First copy the generic "header" into the shader. Includes uniforms and some defines // to unwrap the packed 4-element uniforms into single values. - fullSource.append(StaticGlShaders::Get()->GetPresetShaderHeader()); + fullSource.append(MilkdropStaticShaders::Get()->GetPresetShaderHeader()); if (m_type == ShaderType::WarpShader) { @@ -568,7 +570,7 @@ void MilkdropShader::TranspileHLSLShader(const PresetState& presetState, std::st // Then generate GLSL from the resulting parser tree if (!generator.Generate(&tree, M4::GLSLGenerator::Target_FragmentShader, - StaticGlShaders::Get()->GetGlslGeneratorVersion(), + MilkdropStaticShaders::Get()->GetGlslGeneratorVersion(), "PS")) { throw ShaderException("Error translating HLSL " + shaderTypeString + " shader: GLSL generating failes.\nSource:\n" + sourcePreprocessed); @@ -578,11 +580,11 @@ void MilkdropShader::TranspileHLSLShader(const PresetState& presetState, std::st // Compile the preset shader fragment shader with the standard vertex shader and cross our fingers. if (m_type == ShaderType::WarpShader) { - m_shader.CompileProgram(StaticGlShaders::Get()->GetPresetWarpVertexShader(), generator.GetResult()); + m_shader.CompileProgram(MilkdropStaticShaders::Get()->GetPresetWarpVertexShader(), generator.GetResult()); } else { - m_shader.CompileProgram(StaticGlShaders::Get()->GetPresetCompVertexShader(), generator.GetResult()); + m_shader.CompileProgram(MilkdropStaticShaders::Get()->GetPresetCompVertexShader(), generator.GetResult()); } } diff --git a/src/libprojectM/MilkdropPreset/MilkdropStaticShaders.cpp.in b/src/libprojectM/MilkdropPreset/MilkdropStaticShaders.cpp.in new file mode 100644 index 000000000..4f252f09b --- /dev/null +++ b/src/libprojectM/MilkdropPreset/MilkdropStaticShaders.cpp.in @@ -0,0 +1,151 @@ +#include "MilkdropStaticShaders.hpp" + +#include "projectM-opengl.h" + +#include +#include + +namespace libprojectM { +namespace MilkdropPreset { + +@STATIC_SHADER_CONTENTS@ + +MilkdropStaticShaders::MilkdropStaticShaders(bool useGLES) + : m_useGLES(useGLES) +{ + m_GLSLVersion = QueryGlslVersion(); + + if (m_GLSLVersion.major == 0) + { + throw std::runtime_error("Could not retrieve OpenGL shader language version. Is OpenGL available and the context initialized?"); + } + if (m_GLSLVersion.major < 3) + { + throw std::runtime_error("OpenGL shader language version 3 or higher is required, but not available in the current context."); + } + + if (m_useGLES) + { + // If GLES is enabled, use the embedded specification language variant. + m_versionHeader = "#version 300 es"; + m_GLSLGeneratorVersion = M4::GLSLGenerator::Version::Version_300_ES; + } + else + { + m_versionHeader = "#version 330"; + m_GLSLGeneratorVersion = M4::GLSLGenerator::Version::Version_330; + } +} + +MilkdropStaticShaders::GlslVersion MilkdropStaticShaders::QueryGlslVersion() +{ + /* In the linux desktop environment with --use-gles configured, the parsing of the GL_SHADING_LANGUAGE_VERSION + * string comes back as "OpenGL ES GLSL ES 3" + * And I think this was supposed to be parsing something like + * "3.10 etc etc" + * This caused exceptions to be raised in the std::stoi section; + * + * So - The parsing will look for ['.' ] [] + * and will default to 3.0 for the version in case of errors + */ + int major = 3; /* 3.0 is default */ + int minor = 0; + + const char* shaderLanguageVersion = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); + + if (shaderLanguageVersion == nullptr) + { + return GlslVersion{0, 0}; + } + + std::string glslVersionString{shaderLanguageVersion}; + + size_t versionLength = glslVersionString.length(); + /* make a c version of the string and do the conversion to integers manually just for this case */ + if (versionLength) + { // find the number + size_t position = 0; + char* cstr = new char[versionLength + 1]; + + strcpy(cstr, glslVersionString.c_str()); + + /* scan the anything before the number */ + while (position < versionLength) + { + char ch = cstr[position]; + if ((ch >= '0') && (ch <= '9')) + { + break; + } + position++; + } + + /* scan the first number */ + { + int possible_major = 0; + while (position < versionLength) + { + char ch = cstr[position]; + if ((ch >= '0') && (ch <= '9')) + { + possible_major = (possible_major * 10) + ch - '0'; + } + else if (ch == '.') + { /* got the minor */ + int possible_minor = 0; + position++; + while (position < versionLength) + { + ch = cstr[position]; + if ((ch >= '0') && (ch <= '9')) + { + possible_minor = (possible_minor * 10) + ch - '0'; + } + else + break; + position++; + } /* while scanning the minor version */ + if (possible_major) + { /* set the minor version only if the major number is valid */ + minor = possible_minor; + } + break; // We scanned it + } + else + { /* not a number or period */ + break; + } + position++; + } /* while scanning the major number */ + if (possible_major) + { + major = possible_major; + } + } /* scanning block */ + delete[] cstr; + } /* if there is a string to parse */ + + return {major, minor}; +} + +std::string MilkdropStaticShaders::AddVersionHeader(std::string shader_text) +{ + return m_versionHeader + "\n" + shader_text; +} + +#define DECLARE_SHADER_ACCESSOR(name) \ + std::string MilkdropStaticShaders::Get##name() \ + { \ + return AddVersionHeader(k##name##Glsl330); \ + } + +#define DECLARE_SHADER_ACCESSOR_NO_HEADER(name) \ + std::string MilkdropStaticShaders::Get##name() \ + { \ + return k##name##Glsl330; \ + } + +@STATIC_SHADER_ACCESSOR_DEFINITIONS@ + +} // namespace MilkdropPreset +} // namespace libprojectM \ No newline at end of file diff --git a/src/libprojectM/MilkdropPreset/MilkdropStaticShaders.hpp.in b/src/libprojectM/MilkdropPreset/MilkdropStaticShaders.hpp.in new file mode 100644 index 000000000..b55cd554c --- /dev/null +++ b/src/libprojectM/MilkdropPreset/MilkdropStaticShaders.hpp.in @@ -0,0 +1,86 @@ +#pragma once + +#include + +#include "GLSLGenerator.h" + +namespace libprojectM { +namespace MilkdropPreset { + +/** + * @brief Singleton manager for static Milkdrop GL shaders + * + * The manager provides shaders through its accessor methods, and selects the appropriate shader + * version to be compatible with the system GLSL version. + */ +class MilkdropStaticShaders +{ +public: + /** + * Returns the singleton MilkdropStaticShaders instance. + * @return The singleton instance of the MilkdropStaticShaders class. + */ + static std::shared_ptr Get() + { + bool useGLES = false; +#if USE_GLES + useGLES = true; +#endif + + static std::shared_ptr instance( + new MilkdropStaticShaders(useGLES)); + return instance; + } + + /** + * Returns the GLSLGenerator version enum value corresponding to the queried OpenGL shader version. + * @return The GLSLGenerator version enum value corresponding to the queried OpenGL shader version. + */ + M4::GLSLGenerator::Version GetGlslGeneratorVersion() + { + return m_GLSLGeneratorVersion; + } + + // Accessors for the named static GL shader resources. +@STATIC_SHADER_ACCESSOR_DECLARATIONS@ + +private: + /** + * POD struct to store parsed GLSL version numbers. + */ + struct GlslVersion { + int major{}; //!< Major OpenGL shading language version + int minor{}; //!< Minor OpenGL shading language version + }; + + /** + * @brief Queries the system GLSL version. + * Uses `glGetString(GL_SHADING_LANGUAGE_VERSION)`. + * @return The parsed major and minor version numbers. + */ + GlslVersion QueryGlslVersion(); + + /** + * @brief Constructor, overriding the version to GLES3 if `use_gles` is true. + * Note - this happens after GlslVersion is called, because it uses the version to determine things. + * @param use_gles Set to true if GLES is being used. + */ + MilkdropStaticShaders(bool useGLES); + + /** + * @brief Prepends a string of the form "#version \n" to the provided shader text. + * is derived from the queried GLSL version (or overridden when the manager was + * constructed with `use_gles` = true). + * @param shader_text The shader text to prepend the header to. + * @return A "full" shader with header prepended. + */ + std::string AddVersionHeader(std::string shader_text); + + bool m_useGLES{false}; //!< Whether or not to use GLES shaders. + GlslVersion m_GLSLVersion{0, 0}; //!< The queried GLSL version. + std::string m_versionHeader; //!< The version header to prepended by AddVersionHeader. + M4::GLSLGenerator::Version m_GLSLGeneratorVersion; //!< The GLSL generator version to pass to the hlslparser generator. +}; + +} // namespace MilkdropPreset +} // namespace libprojectM \ No newline at end of file diff --git a/src/libprojectM/MilkdropPreset/MotionVectors.cpp b/src/libprojectM/MilkdropPreset/MotionVectors.cpp index 9f7eecf45..d46fb74bd 100644 --- a/src/libprojectM/MilkdropPreset/MotionVectors.cpp +++ b/src/libprojectM/MilkdropPreset/MotionVectors.cpp @@ -1,13 +1,14 @@ #include "MotionVectors.hpp" -#include +#include + #include MotionVectors::MotionVectors(PresetState& presetState) : RenderItem() , m_presetState(presetState) { - auto staticShaders = StaticGlShaders::Get(); + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); m_motionVectorShader.CompileProgram(staticShaders->GetPresetMotionVectorsVertexShader(), staticShaders->GetV2fC4fFragmentShader()); RenderItem::Init(); diff --git a/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp b/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp index e9de17fc2..64b2a2706 100644 --- a/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp +++ b/src/libprojectM/MilkdropPreset/PerPixelMesh.cpp @@ -5,7 +5,7 @@ #include "PerPixelContext.hpp" #include "PresetState.hpp" -#include +#include #include #include @@ -15,7 +15,7 @@ PerPixelMesh::PerPixelMesh() { RenderItem::Init(); - auto staticShaders = StaticGlShaders::Get(); + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); m_perPixelMeshShader.CompileProgram(staticShaders->GetPresetWarpVertexShader(), staticShaders->GetPresetWarpFragmentShader()); } diff --git a/src/libprojectM/MilkdropPreset/PresetState.cpp b/src/libprojectM/MilkdropPreset/PresetState.cpp index 68dea1108..49fa752e1 100644 --- a/src/libprojectM/MilkdropPreset/PresetState.cpp +++ b/src/libprojectM/MilkdropPreset/PresetState.cpp @@ -2,7 +2,7 @@ #include "PresetFileParser.hpp" -#include "Renderer/StaticGlShaders.hpp" +#include #include @@ -12,7 +12,7 @@ const glm::mat4 PresetState::orthogonalProjectionFlipped = glm::ortho(-1.0f, 1.0 PresetState::PresetState() : globalMemory(projectm_eval_memory_buffer_create()) { - auto staticShaders = StaticGlShaders::Get(); + auto staticShaders = libprojectM::MilkdropPreset::MilkdropStaticShaders::Get(); untexturedShader.CompileProgram(staticShaders->GetV2fC4fVertexShader(), staticShaders->GetV2fC4fFragmentShader()); texturedShader.CompileProgram(staticShaders->GetV2fC4fT2fVertexShader(), diff --git a/src/libprojectM/MilkdropPreset/Shaders/Blur1FragmentShaderGlsl330.frag b/src/libprojectM/MilkdropPreset/Shaders/Blur1FragmentShaderGlsl330.frag new file mode 100644 index 000000000..0bc87fb4e --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/Blur1FragmentShaderGlsl330.frag @@ -0,0 +1,54 @@ +precision mediump float; + +in vec2 fragment_texture; + +uniform sampler2D texture_sampler; +uniform vec4 _c0; // source texsize (.xy), and inverse (.zw) +uniform vec4 _c1; // w1..w4 +uniform vec4 _c2; // d1..d4 +uniform vec4 _c3; // scale, bias, w_div + +out vec4 color; + +void main(){ + // LONG HORIZ. PASS 1: + #define srctexsize _c0 + #define w1 _c1.x + #define w2 _c1.y + #define w3 _c1.z + #define w4 _c1.w + #define d1 _c2.x + #define d2 _c2.y + #define d3 _c2.z + #define d4 _c2.w + #define fscale _c3.x + #define fbias _c3.y + #define w_div _c3.z + + // note: if you just take one sample at exactly uv.xy, you get an avg of 4 + // pixels. + + // + moves blur UP, LEFT by 1-pixel increments + vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(1.0,1.0); + + vec3 blur = + (texture(texture_sampler, uv2 + vec2(d1 * srctexsize.z, 0)).xyz + + texture(texture_sampler, uv2 + vec2(-d1 * srctexsize.z, 0)).xyz) * + w1 + + (texture(texture_sampler, uv2 + vec2(d2 * srctexsize.z, 0)).xyz + + texture(texture_sampler, uv2 + vec2(-d2 * srctexsize.z, 0)).xyz) * + w2 + + (texture(texture_sampler, uv2 + vec2(d3 * srctexsize.z, 0)).xyz + + texture(texture_sampler, uv2 + vec2(-d3 * srctexsize.z, 0)).xyz) * + w3 + + (texture(texture_sampler, uv2 + vec2(d4 * srctexsize.z, 0)).xyz + + texture(texture_sampler, uv2 + vec2(-d4 * srctexsize.z, 0)).xyz) * + w4; + + blur.xyz *= w_div; + + blur.xyz = blur.xyz*fscale + fbias; + + color.xyz = blur; + color.w = 1.0; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/Blur2FragmentShaderGlsl330.frag b/src/libprojectM/MilkdropPreset/Shaders/Blur2FragmentShaderGlsl330.frag new file mode 100644 index 000000000..ebfa882e4 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/Blur2FragmentShaderGlsl330.frag @@ -0,0 +1,49 @@ +precision mediump float; + +in vec2 fragment_texture; + +uniform sampler2D texture_sampler; +uniform vec4 _c0; // source texsize (.xy), and inverse (.zw) +uniform vec4 _c5; // w1,w2,d1,d2 +uniform vec4 _c6; // w_div, edge_darken_c1, edge_darken_c2, edge_darken_c3 + +out vec4 color; + +void main(){ + // SHORT VERTICAL PASS 2: + #define srctexsize _c0 + #define w1 _c5.x + #define w2 _c5.y + #define d1 _c5.z + #define d2 _c5.w + #define edge_darken_c1 _c6.y + #define edge_darken_c2 _c6.z + #define edge_darken_c3 _c6.w + #define w_div _c6.x + + // note: if you just take one sample at exactly uv.xy, you get an avg of 4 + // pixels. + + // + moves blur UP, LEFT by TWO-pixel increments! (since texture is 1/2 the + // size of blur1_ps) + vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(0,0); + + vec3 blur = + (texture(texture_sampler, uv2 + vec2(0, d1 * srctexsize.w)).xyz + + texture(texture_sampler, uv2 + vec2(0, -d1 * srctexsize.w)).xyz) * + w1 + + (texture(texture_sampler, uv2 + vec2(0, d2 * srctexsize.w)).xyz + + texture(texture_sampler, uv2 + vec2(0, -d2 * srctexsize.w)).xyz) * + w2; + blur.xyz *= w_div; + + // tone it down at the edges (only happens on 1st X pass!) + float t = min(min(fragment_texture.x, fragment_texture.y), + 1.0 - max(fragment_texture.x, fragment_texture.y)); + t = sqrt(t); + t = edge_darken_c1 + edge_darken_c2 * clamp(t * edge_darken_c3, 0.0, 1.0); + blur.xyz *= t; + + color.xyz = blur; + color.w = 1.0; +} \ No newline at end of file diff --git a/src/libprojectM/MilkdropPreset/Shaders/BlurVertexShaderGlsl330.vert b/src/libprojectM/MilkdropPreset/Shaders/BlurVertexShaderGlsl330.vert new file mode 100644 index 000000000..9d8c69560 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/BlurVertexShaderGlsl330.vert @@ -0,0 +1,9 @@ +layout(location = 0) in vec2 vertex_position; +layout(location = 1) in vec2 vertex_texture; + +out vec2 fragment_texture; + +void main(){ + gl_Position = vec4(vertex_position, 0.0, 1.0); + fragment_texture = vertex_texture; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/PresetCompVertexShaderGlsl330.vert b/src/libprojectM/MilkdropPreset/Shaders/PresetCompVertexShaderGlsl330.vert new file mode 100644 index 000000000..ce97bf333 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/PresetCompVertexShaderGlsl330.vert @@ -0,0 +1,16 @@ +layout(location = 0) in vec2 vertex_position; +layout(location = 1) in vec4 vertex_color; +layout(location = 2) in vec2 vertex_texture; +layout(location = 3) in vec2 vertex_rad_ang; + +out vec4 frag_COLOR; +out vec2 frag_TEXCOORD0; +out vec2 frag_TEXCOORD1; + +void main(){ + vec4 position = vec4(vertex_position, 0.0, 1.0); + gl_Position = position; + frag_COLOR = vertex_color; + frag_TEXCOORD0 = vertex_texture; + frag_TEXCOORD1 = vertex_rad_ang; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/PresetMotionVectorsVertexShaderGlsl330.vert b/src/libprojectM/MilkdropPreset/Shaders/PresetMotionVectorsVertexShaderGlsl330.vert new file mode 100644 index 000000000..7f7b7ab8d --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/PresetMotionVectorsVertexShaderGlsl330.vert @@ -0,0 +1,54 @@ +layout(location = 0) in vec2 vertex_position; +layout(location = 1) in vec4 vertex_color; +layout(location = 2) in int vertex_index; + +uniform mat4 vertex_transformation; +uniform float length_multiplier; +uniform float minimum_length; + +uniform sampler2D warp_coordinates; + +out vec4 fragment_color; + +void main() { + // Input positions are given in texture coordinates (0...1), not the usual + // screen coordinates. + vec2 pos = vertex_position; + + if (vertex_index % 2 == 1) + { + // Reverse propagation using the u/v texture written in the previous frame. + // Milkdrop's original code did a simple bilinear interpolation, but here it was already + // done by the fragment shader during the warp mesh drawing. We just need to look up the + // motion vector coordinate. + vec2 oldUV = texture(warp_coordinates, pos.xy).xy; + + // Enforce minimum trail length + vec2 dist = oldUV - pos; + dist *= length_multiplier; + float len = length(dist); + if (len > minimum_length) + {} + else if (len > 0.00000001f) + { + len = minimum_length / len; + dist *= len; + } + else + { + dist = vec2(minimum_length); + } + + pos += dist; + } + + // Transform positions from 0...1 to -1...1 in each direction. + pos = pos * 2.0 - 1.0; + + // Flip final Y, as we draw this top-down, which is bottom-up in OpenGL. + pos.y = -pos.y; + + // Now we've got the usual coordinates, apply our orthogonal transformation. + gl_Position = vertex_transformation * vec4(pos, 0.0, 1.0); + fragment_color = vertex_color; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/PresetShaderHeaderGlsl330.inc b/src/libprojectM/MilkdropPreset/Shaders/PresetShaderHeaderGlsl330.inc new file mode 100644 index 000000000..283829193 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/PresetShaderHeaderGlsl330.inc @@ -0,0 +1,155 @@ +#define M_PI 3.14159265359 +#define M_PI_2 6.28318530718 +#define M_INV_PI_2 0.159154943091895 + +uniform float4 rand_frame; // random float4, updated each frame +uniform float4 rand_preset; // random float4, updated once per *preset* +uniform float4 _c0; // .xy: multiplier to use on UV's to paste + // an image fullscreen, *aspect-aware* + // .zw = inverse. +uniform float4 _c1, _c2, _c3, _c4; +uniform float4 _c5; // .xy = scale, bias for reading blur1 + // .zw = scale, bias for reading blur2 +uniform float4 _c6; // .xy = scale, bias for reading blur3 + // .zw = blur1_min, blur1_max +uniform float4 _c7; // .xy ~= float2(1024,768) + // .zw ~= float2(1/1024.0, 1/768.0) +uniform float4 _c8; // .xyzw ~= 0.5 + 0.5 * cos( + // time * float4(~0.3, ~1.3, ~5, ~20)) +uniform float4 _c9; // .xyzw ~= same, but using sin() +uniform float4 _c10; // .xyzw ~= 0.5 + 0.5 * cos( + // time * float4(~0.005, ~0.008, ~0.013, + // ~0.022)) +uniform float4 _c11; // .xyzw ~= same, but using sin() +uniform float4 _c12; // .xyz = mip info for main image + // (.x=#across, .y=#down, .z=avg) + // .w = unused +uniform float4 _c13; // .xy = blur2_min, blur2_max + // .zw = blur3_min, blur3_max +uniform float4 _qa; // q vars bank 1 [q1-q4] +uniform float4 _qb; // q vars bank 2 [q5-q8] +uniform float4 _qc; // q vars ... +uniform float4 _qd; // q vars +uniform float4 _qe; // q vars +uniform float4 _qf; // q vars +uniform float4 _qg; // q vars +uniform float4 _qh; // q vars bank 8 [q29-q32] + +// note: in general, don't use the current time w/the *dynamic* rotations! + +// four random, static rotations, randomized at preset load time. +// minor translation component (<1). +uniform float4x3 rot_s1; +uniform float4x3 rot_s2; +uniform float4x3 rot_s3; +uniform float4x3 rot_s4; + +// four random, slowly changing rotations. +uniform float4x3 rot_d1; +uniform float4x3 rot_d2; +uniform float4x3 rot_d3; +uniform float4x3 rot_d4; + +// faster-changing. +uniform float4x3 rot_f1; +uniform float4x3 rot_f2; +uniform float4x3 rot_f3; +uniform float4x3 rot_f4; + +// very-fast-changing. +uniform float4x3 rot_vf1; +uniform float4x3 rot_vf2; +uniform float4x3 rot_vf3; +uniform float4x3 rot_vf4; + +// ultra-fast-changing. +uniform float4x3 rot_uf1; +uniform float4x3 rot_uf2; +uniform float4x3 rot_uf3; +uniform float4x3 rot_uf4; + +// Random every frame. +uniform float4x3 rot_rand1; +uniform float4x3 rot_rand2; +uniform float4x3 rot_rand3; +uniform float4x3 rot_rand4; + +#define time _c2.x +#define fps _c2.y +#define frame _c2.z +#define progress _c2.w +#define bass _c3.x +#define mid _c3.y +#define treb _c3.z +#define vol _c3.w +#define bass_att _c4.x +#define mid_att _c4.y +#define treb_att _c4.z +#define vol_att _c4.w +#define q1 _qa.x +#define q2 _qa.y +#define q3 _qa.z +#define q4 _qa.w +#define q5 _qb.x +#define q6 _qb.y +#define q7 _qb.z +#define q8 _qb.w +#define q9 _qc.x +#define q10 _qc.y +#define q11 _qc.z +#define q12 _qc.w +#define q13 _qd.x +#define q14 _qd.y +#define q15 _qd.z +#define q16 _qd.w +#define q17 _qe.x +#define q18 _qe.y +#define q19 _qe.z +#define q20 _qe.w +#define q21 _qf.x +#define q22 _qf.y +#define q23 _qf.z +#define q24 _qf.w +#define q25 _qg.x +#define q26 _qg.y +#define q27 _qg.z +#define q28 _qg.w +#define q29 _qh.x +#define q30 _qh.y +#define q31 _qh.z +#define q32 _qh.w + +#define aspect _c0 + +// .xy = (w,h); .zw = (1/(float)w, 1/(float)h) +#define texsize _c7 + +#define roam_cos _c8 +#define roam_sin _c9 +#define slow_roam_cos _c10 +#define slow_roam_sin _c11 +#define mip_x _c12.x +#define mip_y _c12.y +#define mip_xy _c12.xy +#define mip_avg _c12.z +#define blur1_min _c6.z +#define blur1_max _c6.w +#define blur2_min _c13.x +#define blur2_max _c13.y +#define blur3_min _c13.z +#define blur3_max _c13.w + +#define sampler_FC_main sampler_fc_main +#define sampler_PC_main sampler_pc_main +#define sampler_FW_main sampler_fw_main +#define sampler_PW_main sampler_pw_main + +#define GetMain(uv) (tex2D(sampler_main,uv).xyz) +#define GetPixel(uv) (tex2D(sampler_main,uv).xyz) +#define GetBlur1(uv) (tex2D(sampler_blur1,uv).xyz*_c5.x + _c5.y) +#define GetBlur2(uv) (tex2D(sampler_blur2,uv).xyz*_c5.z + _c5.w) +#define GetBlur3(uv) (tex2D(sampler_blur3,uv).xyz*_c6.x + _c6.y) + +#define lum(x) (dot(x,float3(0.32,0.49,0.29))) +#define tex2d tex2D +#define tex3d tex3D diff --git a/src/libprojectM/MilkdropPreset/Shaders/PresetWarpFragmentShaderGlsl330.frag b/src/libprojectM/MilkdropPreset/Shaders/PresetWarpFragmentShaderGlsl330.frag new file mode 100644 index 000000000..cfdeaa592 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/PresetWarpFragmentShaderGlsl330.frag @@ -0,0 +1,15 @@ +in vec4 frag_COLOR; +in vec4 frag_TEXCOORD0; +in vec2 frag_TEXCOORD1; + +uniform sampler2D texture_sampler; + +layout(location = 0) out vec4 color; +layout(location = 1) out vec2 texCoords; + +void main() { + // Main image + color = frag_COLOR * texture(texture_sampler, frag_TEXCOORD0.xy); + // Motion vector grid u/v coords for the next frame + texCoords = frag_TEXCOORD0.xy; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/PresetWarpVertexShaderGlsl330.vert b/src/libprojectM/MilkdropPreset/Shaders/PresetWarpVertexShaderGlsl330.vert new file mode 100644 index 000000000..f0768af13 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/PresetWarpVertexShaderGlsl330.vert @@ -0,0 +1,82 @@ +#define pos vertex_position +#define radius rad_ang.x +#define angle rad_ang.y +#define zoom transforms.x +#define zoomExp transforms.y +#define rot transforms.z +#define warp transforms.w + +#define aspectX aspect.x +#define aspectY aspect.y +#define invAspectX aspect.z +#define invAspectY aspect.w + +layout(location = 0) in vec2 vertex_position; +layout(location = 1) in vec2 rad_ang; +layout(location = 2) in vec4 transforms; +layout(location = 3) in vec2 center; +layout(location = 4) in vec2 distance; +layout(location = 5) in vec2 stretch; + +uniform mat4 vertex_transformation; +uniform vec4 aspect; +uniform float warpTime; +uniform float warpScaleInverse; +uniform vec4 warpFactors; +uniform vec2 texelOffset; +uniform float decay; + +out vec4 frag_COLOR; +out vec4 frag_TEXCOORD0; +out vec2 frag_TEXCOORD1; + +void main() { + gl_Position = vertex_transformation * vec4(pos, 0.0, 1.0); + + float zoom2 = pow(zoom, pow(zoomExp, radius * 2.0 - 1.0)); + float zoom2Inverse = 1.0 / zoom2; + + // Initial texture coordinates, with built-in zoom factor + float u = pos.x * aspectX * 0.5 * zoom2Inverse + 0.5; + float v = -pos.y * aspectY * 0.5 * zoom2Inverse + 0.5; + + // original UV coordinates + vec2 uv_original = vec2(pos.x * 0.5 + 0.5 + texelOffset.x, + -pos.y * 0.5 + 0.5 + texelOffset.y); + + // Stretch on X, Y + u = (u - center.x) / stretch.x + center.x; + v = (v - center.y) / stretch.y + center.y; + + // Warping + u += warp * 0.0035 * sin(warpTime * 0.333 + warpScaleInverse * (pos.x * warpFactors.x - pos.y * warpFactors.w)); + v += warp * 0.0035 * cos(warpTime * 0.375 - warpScaleInverse * (pos.x * warpFactors.z + pos.y * warpFactors.y)); + u += warp * 0.0035 * cos(warpTime * 0.753 - warpScaleInverse * (pos.x * warpFactors.y - pos.y * warpFactors.z)); + v += warp * 0.0035 * sin(warpTime * 0.825 + warpScaleInverse * (pos.x * warpFactors.x + pos.y * warpFactors.w)); + + // Rotation + float u2 = u - center.x; + float v2 = v - center.y; + + float cosRotation = cos(rot); + float sinRotation = sin(rot); + u = u2 * cosRotation - v2 * sinRotation + center.x; + v = u2 * sinRotation + v2 * cosRotation + center.y; + + // Translation + u -= distance.x; + v -= distance.y; + + // Undo aspect ratio fix + u = (u - 0.5) * invAspectX + 0.5; + v = (v - 0.5) * invAspectY + 0.5; + + // Final half-texel translation + u += texelOffset.x; + v += texelOffset.y; + + frag_COLOR = vec4(decay, decay, decay, 1.0); + frag_TEXCOORD0.xy = vec2(u, v); + frag_TEXCOORD0.zw = uv_original; + frag_TEXCOORD1 = rad_ang; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/V2fC4fFragmentShaderGlsl330.frag b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fFragmentShaderGlsl330.frag new file mode 100644 index 000000000..f05fb7bf5 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fFragmentShaderGlsl330.frag @@ -0,0 +1,9 @@ +precision mediump float; + +in vec4 fragment_color; + +out vec4 color; + +void main(){ + color = fragment_color; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/V2fC4fT2fFragmentShaderGlsl330.frag b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fT2fFragmentShaderGlsl330.frag new file mode 100644 index 000000000..55cb92e93 --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fT2fFragmentShaderGlsl330.frag @@ -0,0 +1,12 @@ +precision mediump float; + +in vec4 fragment_color; +in vec2 fragment_texture; + +uniform sampler2D texture_sampler; + +out vec4 color; + +void main(){ + color = fragment_color * texture(texture_sampler, fragment_texture.st); +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/V2fC4fT2fVertexShaderGlsl330.vert b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fT2fVertexShaderGlsl330.vert new file mode 100644 index 000000000..1b59d3b5e --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fT2fVertexShaderGlsl330.vert @@ -0,0 +1,14 @@ +layout(location = 0) in vec2 vertex_position; +layout(location = 1) in vec4 vertex_color; +layout(location = 2) in vec2 vertex_texture; + +uniform mat4 vertex_transformation; + +out vec4 fragment_color; +out vec2 fragment_texture; + +void main(){ + gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); + fragment_color = vertex_color; + fragment_texture = vertex_texture; +} diff --git a/src/libprojectM/MilkdropPreset/Shaders/V2fC4fVertexShaderGlsl330.vert b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fVertexShaderGlsl330.vert new file mode 100644 index 000000000..48f0aad8a --- /dev/null +++ b/src/libprojectM/MilkdropPreset/Shaders/V2fC4fVertexShaderGlsl330.vert @@ -0,0 +1,13 @@ +layout(location = 0) in vec2 vertex_position; +layout(location = 1) in vec4 vertex_color; + +uniform mat4 vertex_transformation; +uniform float vertex_point_size; + +out vec4 fragment_color; + +void main(){ + gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); + gl_PointSize = vertex_point_size; + fragment_color = vertex_color; +} diff --git a/src/libprojectM/MilkdropPreset/VideoEcho.cpp b/src/libprojectM/MilkdropPreset/VideoEcho.cpp index 5b53a33b4..17763986a 100644 --- a/src/libprojectM/MilkdropPreset/VideoEcho.cpp +++ b/src/libprojectM/MilkdropPreset/VideoEcho.cpp @@ -1,6 +1,5 @@ #include "VideoEcho.hpp" -#include "Renderer/ShaderEngine.hpp" #include VideoEcho::VideoEcho(const PresetState& presetState) diff --git a/src/libprojectM/ProjectM.cpp b/src/libprojectM/ProjectM.cpp index 5f3056380..88a1aca88 100644 --- a/src/libprojectM/ProjectM.cpp +++ b/src/libprojectM/ProjectM.cpp @@ -24,6 +24,7 @@ #include "Preset.hpp" #include "PresetFactoryManager.hpp" #include "Renderer.hpp" +#include "TextureManager.hpp" #include "TimeKeeper.hpp" #include "libprojectM/Audio/BeatDetect.hpp" #include "libprojectM/Audio/PCM.hpp" //Sound data handler (buffering, FFT, etc.) diff --git a/src/libprojectM/Renderer/CMakeLists.txt b/src/libprojectM/Renderer/CMakeLists.txt index 83049ec95..ce46d1bbe 100644 --- a/src/libprojectM/Renderer/CMakeLists.txt +++ b/src/libprojectM/Renderer/CMakeLists.txt @@ -12,16 +12,15 @@ add_library(Renderer OBJECT Sampler.hpp Shader.cpp Shader.hpp - ShaderEngine.cpp - ShaderEngine.hpp - StaticGlShaders.cpp Texture.cpp Texture.hpp TextureAttachment.cpp TextureAttachment.hpp TextureManager.cpp TextureManager.hpp - TextureSamplerDescriptor.cpp TextureSamplerDescriptor.hpp) + TextureSamplerDescriptor.cpp + TextureSamplerDescriptor.hpp + ) target_include_directories(Renderer PRIVATE diff --git a/src/libprojectM/Renderer/Renderer.cpp b/src/libprojectM/Renderer/Renderer.cpp index fc971f638..e2401bd7d 100644 --- a/src/libprojectM/Renderer/Renderer.cpp +++ b/src/libprojectM/Renderer/Renderer.cpp @@ -165,8 +165,6 @@ void Renderer::reset(int viewportWidth, int viewportHeight) m_fInvAspectX = 1.0f / m_fAspectX; m_fInvAspectY = 1.0f / m_fAspectY; - m_shaderEngine.reset(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClear(GL_COLOR_BUFFER_BIT); diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index 54dab1afa..86bb44cec 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -2,7 +2,6 @@ #include "Audio/BeatDetect.hpp" -#include "ShaderEngine.hpp" #include "projectM-opengl.h" #include @@ -109,7 +108,6 @@ private: int nearestPower2(int value); libprojectM::Audio::BeatDetect& m_beatDetect; - ShaderEngine m_shaderEngine; std::string m_fps; diff --git a/src/libprojectM/Renderer/ShaderEngine.cpp b/src/libprojectM/Renderer/ShaderEngine.cpp deleted file mode 100644 index 1c129daae..000000000 --- a/src/libprojectM/Renderer/ShaderEngine.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "ShaderEngine.hpp" - -#include "StaticGlShaders.hpp" -#include "Texture.hpp" -#include - -ShaderEngine::ShaderEngine() - : presetCompShaderLoaded(false) - , presetWarpShaderLoaded(false) -{ - std::shared_ptr static_gl_shaders = StaticGlShaders::Get(); - - m_untexturedDraw.CompileProgram(static_gl_shaders->GetV2fC4fVertexShader(), - static_gl_shaders->GetV2fC4fFragmentShader()); - m_texturedDraw.CompileProgram(static_gl_shaders->GetV2fC4fT2fVertexShader(), - static_gl_shaders->GetV2fC4fT2fFragmentShader()); -} - -ShaderEngine::~ShaderEngine() -{ - disablePresetShaders(); -} - -// deactivate preset shaders -void ShaderEngine::disablePresetShaders() -{ - if (presetCompShaderLoaded) - glDeleteProgram(programID_presetComp); - - if (presetWarpShaderLoaded) - glDeleteProgram(programID_presetWarp); - - presetCompShaderLoaded = false; - presetWarpShaderLoaded = false; -} - -void ShaderEngine::reset() -{ - disablePresetShaders(); -} diff --git a/src/libprojectM/Renderer/ShaderEngine.hpp b/src/libprojectM/Renderer/ShaderEngine.hpp deleted file mode 100644 index 806a54ee8..000000000 --- a/src/libprojectM/Renderer/ShaderEngine.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "Shader.hpp" -#include "TextureManager.hpp" -#include "projectM-opengl.h" - -#include "Audio/BeatDetect.hpp" - -#include - -class ShaderEngine -{ -public: - ShaderEngine(); - virtual ~ShaderEngine(); - - void reset(); - - Shader m_untexturedDraw; - Shader m_texturedDraw; - -private: - GLint uniform_vertex_transf_warp_shader; - - void disablePresetShaders(); - - // programs generated from preset shader code - GLuint programID_presetComp, programID_presetWarp; - - bool presetCompShaderLoaded, presetWarpShaderLoaded; -}; diff --git a/src/libprojectM/Renderer/StaticGlShaders.cpp b/src/libprojectM/Renderer/StaticGlShaders.cpp deleted file mode 100644 index c3b2368f3..000000000 --- a/src/libprojectM/Renderer/StaticGlShaders.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -#include "StaticGlShaders.hpp" - -#include "projectM-opengl.h" - -#include -#include - - -namespace { -// Variants of shaders for GLSL1.2 -const std::string kPresetMotionVectorsVertexShaderGlsl120 = R"( -)"; - -const std::string kPresetWarpVertexShaderGlsl120 = R"( -#define pos vertex_position.xy -#define radius vertex_position.z -#define angle vertex_position.w -#define zoom transforms.x -#define zoomExp transforms.y -#define rot transforms.z -#define warp transforms.w - -#define aspectX aspect.x -#define aspectY aspect.y -#define invAspectX aspect.z -#define invAspectY aspect.w - -attribute vec4 vertex_position; -attribute vec4 transforms; -attribute vec2 center; -attribute vec2 distance; -attribute vec2 stretch; - -uniform mat4 vertex_transformation; -uniform vec4 aspect; -uniform float warpTime; -uniform float warpScaleInverse; -uniform vec4 warpFactors; -uniform vec2 texelOffset; -uniform float decay; - -varying vec4 frag_COLOR; -varying vec2 frag_TEXCOORD0; -varying vec2 frag_TEXCOORD1; - -void main(){ - gl_Position = vertex_transformation * vec4(vec2(pos.x, -pos.y), 0.0, 1.0); - - float zoom2 = pow(zoom, pow(zoomExp, radius * 2.0 - 1.0)); - float zoom2Inverse = 1.0 / zoom2; - - // Initial texture coordinates, with built-in zoom factor - vec2 uv = vec2(pos.x * aspectX * 0.5 * zoom2Inverse + 0.5, - pos.y * aspectY * 0.5 * zoom2Inverse + 0.5); - - // original UV coordinates - vec2 uv_original = vec2(pos.x * 0.5 + 0.5 + texelOffset.x, - pos.y * 0.5 + 0.5 + texelOffset.y); - - // Stretch on X, Y - uv.x = (uv.x - center.x) / stretch.x + center.x; - uv.y = (uv.y - center.y) / stretch.y + center.y; - - // Warping - uv.x += warp * 0.0035 * sin(warpTime * 0.333 + warpScaleInverse * (pos.x * warpFactors.x - pos.y * warpFactors.w)); - uv.y += warp * 0.0035 * cos(warpTime * 0.375 - warpScaleInverse * (pos.x * warpFactors.z + pos.y * warpFactors.y)); - uv.x += warp * 0.0035 * cos(warpTime * 0.753 - warpScaleInverse * (pos.x * warpFactors.y - pos.y * warpFactors.z)); - uv.y += warp * 0.0035 * sin(warpTime * 0.825 + warpScaleInverse * (pos.x * warpFactors.x + pos.y * warpFactors.w)); - - // Rotation - vec2 uv2 = vec2(uv.x - center.x, - uv.y - center.y); - - float cosRotation = cos(rot); - float sinRotation = sin(rot); - uv.x = uv2.x * cosRotation - uv2.y * sinRotation + center.x; - uv.y = uv2.x * sinRotation + uv2.y * cosRotation + center.y; - - // Translation - uv -= distance; - - // Undo aspect ratio fix - uv.x = (uv.x - 0.5) * invAspectX + 0.5; - uv.y = (uv.y - 0.5) * invAspectY + 0.5; - - // Final half-texel translation - uv += texelOffset; - - frag_COLOR = vec4(decay, decay, decay, 1.0); - frag_TEXCOORD0.xy = uv; - frag_TEXCOORD0.zw = gl_Position.xy; - frag_TEXCOORD1 = uv_original; -} -)"; - -const std::string kPresetWarpFragmentShaderGlsl120 = R"( -varying vec4 frag_COLOR; -varying vec2 frag_TEXCOORD0; -varying vec2 frag_TEXCOORD1; - -uniform sampler2D texture_sampler; - -void main(){ - gl_FragColor = frag_COLOR * texture2D(texture_sampler, frag_TEXCOORD0); -} -)"; - -const std::string kPresetCompVertexShaderGlsl120 = R"( -attribute vec2 vertex_position; -attribute vec4 vertex_color; -attribute vec2 vertex_texture; -attribute vec2 vertex_rad_ang; - -varying vec4 frag_COLOR; -varying vec2 frag_TEXCOORD0; -varying vec2 frag_TEXCOORD1; - -void main(){ - vec4 position = vec4(vertex_position, 0.0, 1.0); - gl_Position = position; - frag_COLOR = vertex_color; - frag_TEXCOORD0 = vertex_texture; - frag_TEXCOORD1 = vertex_rad_ang; -} -)"; - -const std::string kV2fC4fVertexShaderGlsl120 = R"( -attribute vec2 vertex_position; -attribute vec4 vertex_color; - -uniform mat4 vertex_transformation; -uniform float vertex_point_size; - -varying vec4 fragment_color; - -void main(){ - gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); - gl_PointSize = vertex_point_size; - fragment_color = vertex_color; -} -)"; - -const std::string kV2fC4fFragmentShaderGlsl120 = R"( -varying vec4 fragment_color; - -void main(){ - gl_FragColor = fragment_color; -} -)"; - -const std::string kV2fC4fT2fVertexShaderGlsl120 = R"( -attribute vec2 vertex_position; -attribute vec4 vertex_color; -attribute vec2 vertex_texture; - -uniform mat4 vertex_transformation; - -varying vec4 fragment_color; -varying vec2 fragment_texture; - -void main(){ - gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); - fragment_color = vertex_color; - fragment_texture = vertex_texture; -} -)"; - -const std::string kV2fC4fT2fFragmentShaderGlsl120 = R"( -varying vec4 fragment_color; -varying vec2 fragment_texture; - -uniform sampler2D texture_sampler; - -varying vec4 color; - -void main(){ - gl_FragColor = fragment_color * texture2D(texture_sampler, - fragment_texture.st); -} -)"; - -const std::string kPresetShaderHeaderGlsl120 = R"( -#define M_PI 3.14159265359 -#define M_PI_2 6.28318530718 -#define M_INV_PI_2 0.159154943091895 - -uniform float4 rand_frame; // random float4, updated each frame -uniform float4 rand_preset; // random float4, updated once per *preset* -uniform float4 _c0; // .xy: multiplier to use on UV's to paste - // an image fullscreen, *aspect-aware* - // .zw = inverse. -uniform float4 _c1, _c2, _c3, _c4; -uniform float4 _c5; // .xy = scale, bias for reading blur1 - // .zw = scale, bias for reading blur2 -uniform float4 _c6; // .xy = scale, bias for reading blur3 - // .zw = blur1_min, blur1_max -uniform float4 _c7; // .xy ~= float2(1024,768) - // .zw ~= float2(1/1024.0, 1/768.0) -uniform float4 _c8; // .xyzw ~= 0.5 + 0.5 * cos( - // time * float4(~0.3, ~1.3, ~5, ~20)) -uniform float4 _c9; // .xyzw ~= same, but using sin() -uniform float4 _c10; // .xyzw ~= 0.5 + 0.5 * cos( - // time * float4(~0.005, ~0.008, ~0.013, - // ~0.022)) -uniform float4 _c11; // .xyzw ~= same, but using sin() -uniform float4 _c12; // .xyz = mip info for main image - // (.x=#across, .y=#down, .z=avg) - // .w = unused -uniform float4 _c13; // .xy = blur2_min, blur2_max - // .zw = blur3_min, blur3_max -uniform float4 _qa; // q vars bank 1 [q1-q4] -uniform float4 _qb; // q vars bank 2 [q5-q8] -uniform float4 _qc; // q vars ... -uniform float4 _qd; // q vars -uniform float4 _qe; // q vars -uniform float4 _qf; // q vars -uniform float4 _qg; // q vars -uniform float4 _qh; // q vars bank 8 [q29-q32] - -// note: in general, don't use the current time w/the *dynamic* rotations! - -// four random, static rotations, randomized at preset load time. -// minor translation component (<1). -uniform float4x3 rot_s1; -uniform float4x3 rot_s2; -uniform float4x3 rot_s3; -uniform float4x3 rot_s4; - -// four random, slowly changing rotations. -uniform float4x3 rot_d1; -uniform float4x3 rot_d2; -uniform float4x3 rot_d3; -uniform float4x3 rot_d4; - -// faster-changing. -uniform float4x3 rot_f1; -uniform float4x3 rot_f2; -uniform float4x3 rot_f3; -uniform float4x3 rot_f4; - -// very-fast-changing. -uniform float4x3 rot_vf1; -uniform float4x3 rot_vf2; -uniform float4x3 rot_vf3; -uniform float4x3 rot_vf4; - -// ultra-fast-changing. -uniform float4x3 rot_uf1; -uniform float4x3 rot_uf2; -uniform float4x3 rot_uf3; -uniform float4x3 rot_uf4; - -// Random every frame. -uniform float4x3 rot_rand1; -uniform float4x3 rot_rand2; -uniform float4x3 rot_rand3; -uniform float4x3 rot_rand4; - -#define time _c2.x -#define fps _c2.y -#define frame _c2.z -#define progress _c2.w -#define bass _c3.x -#define mid _c3.y -#define treb _c3.z -#define vol _c3.w -#define bass_att _c4.x -#define mid_att _c4.y -#define treb_att _c4.z -#define vol_att _c4.w -#define q1 _qa.x -#define q2 _qa.y -#define q3 _qa.z -#define q4 _qa.w -#define q5 _qb.x -#define q6 _qb.y -#define q7 _qb.z -#define q8 _qb.w -#define q9 _qc.x -#define q10 _qc.y -#define q11 _qc.z -#define q12 _qc.w -#define q13 _qd.x -#define q14 _qd.y -#define q15 _qd.z -#define q16 _qd.w -#define q17 _qe.x -#define q18 _qe.y -#define q19 _qe.z -#define q20 _qe.w -#define q21 _qf.x -#define q22 _qf.y -#define q23 _qf.z -#define q24 _qf.w -#define q25 _qg.x -#define q26 _qg.y -#define q27 _qg.z -#define q28 _qg.w -#define q29 _qh.x -#define q30 _qh.y -#define q31 _qh.z -#define q32 _qh.w - -#define aspect _c0 - -// .xy = (w,h); .zw = (1/(float)w, 1/(float)h) -#define texsize _c7 - -#define roam_cos _c8 -#define roam_sin _c9 -#define slow_roam_cos _c10 -#define slow_roam_sin _c11 -#define mip_x _c12.x -#define mip_y _c12.y -#define mip_xy _c12.xy -#define mip_avg _c12.z -#define blur1_min _c6.z -#define blur1_max _c6.w -#define blur2_min _c13.x -#define blur2_max _c13.y -#define blur3_min _c13.z -#define blur3_max _c13.w - -#define sampler_FC_main sampler_fc_main -#define sampler_PC_main sampler_pc_main -#define sampler_FW_main sampler_fw_main -#define sampler_PW_main sampler_pw_main - -#define GetMain(uv) (tex2D(sampler_main,uv).xyz) -#define GetPixel(uv) (tex2D(sampler_main,uv).xyz) -#define GetBlur1(uv) (tex2D(sampler_blur1,uv).xyz*_c5.x + _c5.y) -#define GetBlur2(uv) (tex2D(sampler_blur2,uv).xyz*_c5.z + _c5.w) -#define GetBlur3(uv) (tex2D(sampler_blur3,uv).xyz*_c6.x + _c6.y) - -#define lum(x) (dot(x,float3(0.32,0.49,0.29))) -#define tex2d tex2D -#define tex3d tex3D -)"; - -const std::string kBlurVertexShaderGlsl120 = R"( -attribute vec2 vertex_position; -attribute vec2 vertex_texture; - -varying vec2 fragment_texture; - -void main(){ - gl_Position = vec4(vertex_position, 0.0, 1.0); - fragment_texture = vertex_texture; -} -)"; - -std::string kBlur1FragmentShaderGlsl120 = R"( -varying vec2 fragment_texture; - -uniform sampler2D texture_sampler; -uniform vec4 _c0; // source texsize (.xy), and inverse (.zw) -uniform vec4 _c1; // w1..w4 -uniform vec4 _c2; // d1..d4 -uniform vec4 _c3; // scale, bias, w_div - -void main(){ - // LONG HORIZ. PASS 1: - #define srctexsize _c0 - #define w1 _c1.x - #define w2 _c1.y - #define w3 _c1.z - #define w4 _c1.w - #define d1 _c2.x - #define d2 _c2.y - #define d3 _c2.z - #define d4 _c2.w - #define fscale _c3.x - #define fbias _c3.y - #define w_div _c3.z - - // note: if you just take one sample at exactly uv.xy, you get an avg of 4 - // pixels. - - // + moves blur UP, LEFT by 1-pixel increments - vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(1.0,1.0); - - vec3 blur = - (texture2D(texture_sampler, uv2 + vec2(d1 * srctexsize.z, 0)).xyz + - texture2D(texture_sampler, uv2 + vec2(-d1 * srctexsize.z, 0)).xyz) * - w1 + - (texture2D(texture_sampler, uv2 + vec2(d2 * srctexsize.z, 0)).xyz + - texture2D(texture_sampler, uv2 + vec2(-d2 * srctexsize.z, 0)).xyz) * - w2 + - (texture2D(texture_sampler, uv2 + vec2(d3 * srctexsize.z, 0)).xyz + - texture2D(texture_sampler, uv2 + vec2(-d3 * srctexsize.z, 0)).xyz) * - w3 + - (texture2D(texture_sampler, uv2 + vec2(d4 * srctexsize.z, 0)).xyz + - texture2D(texture_sampler, uv2 + vec2(-d4 * srctexsize.z, 0)).xyz) * - w4; - - blur.xyz *= w_div; - - blur.xyz = blur.xyz*fscale + fbias; - - gl_FragColor.xyz = blur; - gl_FragColor.w = 1.0; -} -)"; - -std::string kBlur2FragmentShaderGlsl120 = R"( -varying vec2 fragment_texture; - -uniform sampler2D texture_sampler; -uniform vec4 _c0; // source texsize (.xy), and inverse (.zw) -uniform vec4 _c5; // w1,w2,d1,d2 -uniform vec4 _c6; // w_div, edge_darken_c1, edge_darken_c2, edge_darken_c3 - -void main(){ - // SHORT VERTICAL PASS 2: - #define srctexsize _c0 - #define w1 _c5.x - #define w2 _c5.y - #define d1 _c5.z - #define d2 _c5.w - #define edge_darken_c1 _c6.y - #define edge_darken_c2 _c6.z - #define edge_darken_c3 _c6.w - #define w_div _c6.x - - // note: if you just take one sample at exactly uv.xy, you get an avg of 4 - // pixels. - - // + moves blur UP, LEFT by TWO-pixel increments! (since texture is 1/2 the - // size of blur1_ps) - vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(0,0); - - vec3 blur = - (texture2D(texture_sampler, uv2 + vec2(0, d1 * srctexsize.w)).xyz + - texture2D(texture_sampler, uv2 + vec2(0, -d1 * srctexsize.w)).xyz) * - w1 + - (texture2D(texture_sampler, uv2 + vec2(0, d2 * srctexsize.w)).xyz + - texture2D(texture_sampler, uv2 + vec2(0, -d2 * srctexsize.w)).xyz) * - w2; - blur.xyz *= w_div; - - // tone it down at the edges (only happens on 1st X pass!) - float t = min(min(fragment_texture.x, fragment_texture.y), - 1.0 - max(fragment_texture.x, fragment_texture.y)); - t = sqrt(t); - t = edge_darken_c1 + edge_darken_c2 * clamp(t * edge_darken_c3, 0.0, 1.0); - blur.xyz *= t; - - gl_FragColor.xyz = blur; - gl_FragColor.w = 1.0; -} -)"; - -// Variants of shaders for GLSL3.3 -const std::string kPresetMotionVectorsVertexShaderGlsl330 = R"( -layout(location = 0) in vec2 vertex_position; -layout(location = 1) in vec4 vertex_color; -layout(location = 2) in int vertex_index; - -uniform mat4 vertex_transformation; -uniform float length_multiplier; -uniform float minimum_length; - -uniform sampler2D warp_coordinates; - -out vec4 fragment_color; - -void main() { - // Input positions are given in texture coordinates (0...1), not the usual - // screen coordinates. - vec2 pos = vertex_position; - - if (vertex_index % 2 == 1) - { - // Reverse propagation using the u/v texture written in the previous frame. - // Milkdrop's original code did a simple bilinear interpolation, but here it was already - // done by the fragment shader during the warp mesh drawing. We just need to look up the - // motion vector coordinate. - vec2 oldUV = texture(warp_coordinates, pos.xy).xy; - - // Enforce minimum trail length - vec2 dist = oldUV - pos; - dist *= length_multiplier; - float len = length(dist); - if (len > minimum_length) - {} - else if (len > 0.00000001f) - { - len = minimum_length / len; - dist *= len; - } - else - { - dist = vec2(minimum_length); - } - - pos += dist; - } - - // Transform positions from 0...1 to -1...1 in each direction. - pos = pos * 2.0 - 1.0; - - // Flip final Y, as we draw this top-down, which is bottom-up in OpenGL. - pos.y = -pos.y; - - // Now we've got the usual coordinates, apply our orthogonal transformation. - gl_Position = vertex_transformation * vec4(pos, 0.0, 1.0); - fragment_color = vertex_color; -} -)"; - -const std::string kPresetWarpVertexShaderGlsl330 = R"( -#define pos vertex_position -#define radius rad_ang.x -#define angle rad_ang.y -#define zoom transforms.x -#define zoomExp transforms.y -#define rot transforms.z -#define warp transforms.w - -#define aspectX aspect.x -#define aspectY aspect.y -#define invAspectX aspect.z -#define invAspectY aspect.w - -layout(location = 0) in vec2 vertex_position; -layout(location = 1) in vec2 rad_ang; -layout(location = 2) in vec4 transforms; -layout(location = 3) in vec2 center; -layout(location = 4) in vec2 distance; -layout(location = 5) in vec2 stretch; - -uniform mat4 vertex_transformation; -uniform vec4 aspect; -uniform float warpTime; -uniform float warpScaleInverse; -uniform vec4 warpFactors; -uniform vec2 texelOffset; -uniform float decay; - -out vec4 frag_COLOR; -out vec4 frag_TEXCOORD0; -out vec2 frag_TEXCOORD1; - -void main() { - gl_Position = vertex_transformation * vec4(pos, 0.0, 1.0); - - float zoom2 = pow(zoom, pow(zoomExp, radius * 2.0 - 1.0)); - float zoom2Inverse = 1.0 / zoom2; - - // Initial texture coordinates, with built-in zoom factor - float u = pos.x * aspectX * 0.5 * zoom2Inverse + 0.5; - float v = -pos.y * aspectY * 0.5 * zoom2Inverse + 0.5; - - // original UV coordinates - vec2 uv_original = vec2(pos.x * 0.5 + 0.5 + texelOffset.x, - -pos.y * 0.5 + 0.5 + texelOffset.y); - - // Stretch on X, Y - u = (u - center.x) / stretch.x + center.x; - v = (v - center.y) / stretch.y + center.y; - - // Warping - u += warp * 0.0035 * sin(warpTime * 0.333 + warpScaleInverse * (pos.x * warpFactors.x - pos.y * warpFactors.w)); - v += warp * 0.0035 * cos(warpTime * 0.375 - warpScaleInverse * (pos.x * warpFactors.z + pos.y * warpFactors.y)); - u += warp * 0.0035 * cos(warpTime * 0.753 - warpScaleInverse * (pos.x * warpFactors.y - pos.y * warpFactors.z)); - v += warp * 0.0035 * sin(warpTime * 0.825 + warpScaleInverse * (pos.x * warpFactors.x + pos.y * warpFactors.w)); - - // Rotation - float u2 = u - center.x; - float v2 = v - center.y; - - float cosRotation = cos(rot); - float sinRotation = sin(rot); - u = u2 * cosRotation - v2 * sinRotation + center.x; - v = u2 * sinRotation + v2 * cosRotation + center.y; - - // Translation - u -= distance.x; - v -= distance.y; - - // Undo aspect ratio fix - u = (u - 0.5) * invAspectX + 0.5; - v = (v - 0.5) * invAspectY + 0.5; - - // Final half-texel translation - u += texelOffset.x; - v += texelOffset.y; - - frag_COLOR = vec4(decay, decay, decay, 1.0); - frag_TEXCOORD0.xy = vec2(u, v); - frag_TEXCOORD0.zw = uv_original; - frag_TEXCOORD1 = rad_ang; -} -)"; - -const std::string kPresetWarpFragmentShaderGlsl330 = R"( -in vec4 frag_COLOR; -in vec4 frag_TEXCOORD0; -in vec2 frag_TEXCOORD1; - -uniform sampler2D texture_sampler; - -layout(location = 0) out vec4 color; -layout(location = 1) out vec2 texCoords; - -void main() { - // Main image - color = frag_COLOR * texture(texture_sampler, frag_TEXCOORD0.xy); - // Motion vector grid u/v coords for the next frame - texCoords = frag_TEXCOORD0.xy; -} -)"; - -const std::string kPresetCompVertexShaderGlsl330 = R"( -layout(location = 0) in vec2 vertex_position; -layout(location = 1) in vec4 vertex_color; -layout(location = 2) in vec2 vertex_texture; -layout(location = 3) in vec2 vertex_rad_ang; - -out vec4 frag_COLOR; -out vec2 frag_TEXCOORD0; -out vec2 frag_TEXCOORD1; - -void main(){ - vec4 position = vec4(vertex_position, 0.0, 1.0); - gl_Position = position; - frag_COLOR = vertex_color; - frag_TEXCOORD0 = vertex_texture; - frag_TEXCOORD1 = vertex_rad_ang; -} -)"; - -const std::string kV2fC4fVertexShaderGlsl330 = R"( -layout(location = 0) in vec2 vertex_position; -layout(location = 1) in vec4 vertex_color; - -uniform mat4 vertex_transformation; -uniform float vertex_point_size; - -out vec4 fragment_color; - -void main(){ - gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); - gl_PointSize = vertex_point_size; - fragment_color = vertex_color; -} -)"; - -const std::string kV2fC4fFragmentShaderGlsl330 = R"( -precision mediump float; - -in vec4 fragment_color; - -out vec4 color; - -void main(){ - color = fragment_color; -} -)"; - -const std::string kV2fC4fT2fVertexShaderGlsl330 = R"( -layout(location = 0) in vec2 vertex_position; -layout(location = 1) in vec4 vertex_color; -layout(location = 2) in vec2 vertex_texture; - -uniform mat4 vertex_transformation; - -out vec4 fragment_color; -out vec2 fragment_texture; - -void main(){ - gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); - fragment_color = vertex_color; - fragment_texture = vertex_texture; -} -)"; - -const std::string kV2fC4fT2fFragmentShaderGlsl330 = R"( -precision mediump float; - -in vec4 fragment_color; -in vec2 fragment_texture; - -uniform sampler2D texture_sampler; - -out vec4 color; - -void main(){ - color = fragment_color * texture(texture_sampler, fragment_texture.st); -} -)"; - -const std::string kPresetShaderHeaderGlsl330 = R"( -#define M_PI 3.14159265359 -#define M_PI_2 6.28318530718 -#define M_INV_PI_2 0.159154943091895 - -uniform float4 rand_frame; // random float4, updated each frame -uniform float4 rand_preset; // random float4, updated once per *preset* -uniform float4 _c0; // .xy: multiplier to use on UV's to paste - // an image fullscreen, *aspect-aware* - // .zw = inverse. -uniform float4 _c1, _c2, _c3, _c4; -uniform float4 _c5; // .xy = scale, bias for reading blur1 - // .zw = scale, bias for reading blur2 -uniform float4 _c6; // .xy = scale, bias for reading blur3 - // .zw = blur1_min, blur1_max -uniform float4 _c7; // .xy ~= float2(1024,768) - // .zw ~= float2(1/1024.0, 1/768.0) -uniform float4 _c8; // .xyzw ~= 0.5 + 0.5 * cos( - // time * float4(~0.3, ~1.3, ~5, ~20)) -uniform float4 _c9; // .xyzw ~= same, but using sin() -uniform float4 _c10; // .xyzw ~= 0.5 + 0.5 * cos( - // time * float4(~0.005, ~0.008, ~0.013, - // ~0.022)) -uniform float4 _c11; // .xyzw ~= same, but using sin() -uniform float4 _c12; // .xyz = mip info for main image - // (.x=#across, .y=#down, .z=avg) - // .w = unused -uniform float4 _c13; // .xy = blur2_min, blur2_max - // .zw = blur3_min, blur3_max -uniform float4 _qa; // q vars bank 1 [q1-q4] -uniform float4 _qb; // q vars bank 2 [q5-q8] -uniform float4 _qc; // q vars ... -uniform float4 _qd; // q vars -uniform float4 _qe; // q vars -uniform float4 _qf; // q vars -uniform float4 _qg; // q vars -uniform float4 _qh; // q vars bank 8 [q29-q32] - -// note: in general, don't use the current time w/the *dynamic* rotations! - -// four random, static rotations, randomized at preset load time. -// minor translation component (<1). -uniform float4x3 rot_s1; -uniform float4x3 rot_s2; -uniform float4x3 rot_s3; -uniform float4x3 rot_s4; - -// four random, slowly changing rotations. -uniform float4x3 rot_d1; -uniform float4x3 rot_d2; -uniform float4x3 rot_d3; -uniform float4x3 rot_d4; - -// faster-changing. -uniform float4x3 rot_f1; -uniform float4x3 rot_f2; -uniform float4x3 rot_f3; -uniform float4x3 rot_f4; - -// very-fast-changing. -uniform float4x3 rot_vf1; -uniform float4x3 rot_vf2; -uniform float4x3 rot_vf3; -uniform float4x3 rot_vf4; - -// ultra-fast-changing. -uniform float4x3 rot_uf1; -uniform float4x3 rot_uf2; -uniform float4x3 rot_uf3; -uniform float4x3 rot_uf4; - -// Random every frame. -uniform float4x3 rot_rand1; -uniform float4x3 rot_rand2; -uniform float4x3 rot_rand3; -uniform float4x3 rot_rand4; - -#define time _c2.x -#define fps _c2.y -#define frame _c2.z -#define progress _c2.w -#define bass _c3.x -#define mid _c3.y -#define treb _c3.z -#define vol _c3.w -#define bass_att _c4.x -#define mid_att _c4.y -#define treb_att _c4.z -#define vol_att _c4.w -#define q1 _qa.x -#define q2 _qa.y -#define q3 _qa.z -#define q4 _qa.w -#define q5 _qb.x -#define q6 _qb.y -#define q7 _qb.z -#define q8 _qb.w -#define q9 _qc.x -#define q10 _qc.y -#define q11 _qc.z -#define q12 _qc.w -#define q13 _qd.x -#define q14 _qd.y -#define q15 _qd.z -#define q16 _qd.w -#define q17 _qe.x -#define q18 _qe.y -#define q19 _qe.z -#define q20 _qe.w -#define q21 _qf.x -#define q22 _qf.y -#define q23 _qf.z -#define q24 _qf.w -#define q25 _qg.x -#define q26 _qg.y -#define q27 _qg.z -#define q28 _qg.w -#define q29 _qh.x -#define q30 _qh.y -#define q31 _qh.z -#define q32 _qh.w - -#define aspect _c0 - -// .xy = (w,h); .zw = (1/(float)w, 1/(float)h) -#define texsize _c7 - -#define roam_cos _c8 -#define roam_sin _c9 -#define slow_roam_cos _c10 -#define slow_roam_sin _c11 -#define mip_x _c12.x -#define mip_y _c12.y -#define mip_xy _c12.xy -#define mip_avg _c12.z -#define blur1_min _c6.z -#define blur1_max _c6.w -#define blur2_min _c13.x -#define blur2_max _c13.y -#define blur3_min _c13.z -#define blur3_max _c13.w - -#define sampler_FC_main sampler_fc_main -#define sampler_PC_main sampler_pc_main -#define sampler_FW_main sampler_fw_main -#define sampler_PW_main sampler_pw_main - -#define GetMain(uv) (tex2D(sampler_main,uv).xyz) -#define GetPixel(uv) (tex2D(sampler_main,uv).xyz) -#define GetBlur1(uv) (tex2D(sampler_blur1,uv).xyz*_c5.x + _c5.y) -#define GetBlur2(uv) (tex2D(sampler_blur2,uv).xyz*_c5.z + _c5.w) -#define GetBlur3(uv) (tex2D(sampler_blur3,uv).xyz*_c6.x + _c6.y) - -#define lum(x) (dot(x,float3(0.32,0.49,0.29))) -#define tex2d tex2D -#define tex3d tex3D -)"; - -const std::string kBlurVertexShaderGlsl330 = R"( -layout(location = 0) in vec2 vertex_position; -layout(location = 1) in vec2 vertex_texture; - -out vec2 fragment_texture; - -void main(){ - gl_Position = vec4(vertex_position, 0.0, 1.0); - fragment_texture = vertex_texture; -} -)"; - -std::string kBlur1FragmentShaderGlsl330 = R"( -precision mediump float; - -in vec2 fragment_texture; - -uniform sampler2D texture_sampler; -uniform vec4 _c0; // source texsize (.xy), and inverse (.zw) -uniform vec4 _c1; // w1..w4 -uniform vec4 _c2; // d1..d4 -uniform vec4 _c3; // scale, bias, w_div - -out vec4 color; - -void main(){ - // LONG HORIZ. PASS 1: - #define srctexsize _c0 - #define w1 _c1.x - #define w2 _c1.y - #define w3 _c1.z - #define w4 _c1.w - #define d1 _c2.x - #define d2 _c2.y - #define d3 _c2.z - #define d4 _c2.w - #define fscale _c3.x - #define fbias _c3.y - #define w_div _c3.z - - // note: if you just take one sample at exactly uv.xy, you get an avg of 4 - // pixels. - - // + moves blur UP, LEFT by 1-pixel increments - vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(1.0,1.0); - - vec3 blur = - (texture(texture_sampler, uv2 + vec2(d1 * srctexsize.z, 0)).xyz + - texture(texture_sampler, uv2 + vec2(-d1 * srctexsize.z, 0)).xyz) * - w1 + - (texture(texture_sampler, uv2 + vec2(d2 * srctexsize.z, 0)).xyz + - texture(texture_sampler, uv2 + vec2(-d2 * srctexsize.z, 0)).xyz) * - w2 + - (texture(texture_sampler, uv2 + vec2(d3 * srctexsize.z, 0)).xyz + - texture(texture_sampler, uv2 + vec2(-d3 * srctexsize.z, 0)).xyz) * - w3 + - (texture(texture_sampler, uv2 + vec2(d4 * srctexsize.z, 0)).xyz + - texture(texture_sampler, uv2 + vec2(-d4 * srctexsize.z, 0)).xyz) * - w4; - - blur.xyz *= w_div; - - blur.xyz = blur.xyz*fscale + fbias; - - color.xyz = blur; - color.w = 1.0; -} -)"; - -std::string kBlur2FragmentShaderGlsl330 = R"( -precision mediump float; - -in vec2 fragment_texture; - -uniform sampler2D texture_sampler; -uniform vec4 _c0; // source texsize (.xy), and inverse (.zw) -uniform vec4 _c5; // w1,w2,d1,d2 -uniform vec4 _c6; // w_div, edge_darken_c1, edge_darken_c2, edge_darken_c3 - -out vec4 color; - -void main(){ - // SHORT VERTICAL PASS 2: - #define srctexsize _c0 - #define w1 _c5.x - #define w2 _c5.y - #define d1 _c5.z - #define d2 _c5.w - #define edge_darken_c1 _c6.y - #define edge_darken_c2 _c6.z - #define edge_darken_c3 _c6.w - #define w_div _c6.x - - // note: if you just take one sample at exactly uv.xy, you get an avg of 4 - // pixels. - - // + moves blur UP, LEFT by TWO-pixel increments! (since texture is 1/2 the - // size of blur1_ps) - vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(0,0); - - vec3 blur = - (texture(texture_sampler, uv2 + vec2(0, d1 * srctexsize.w)).xyz + - texture(texture_sampler, uv2 + vec2(0, -d1 * srctexsize.w)).xyz) * - w1 + - (texture(texture_sampler, uv2 + vec2(0, d2 * srctexsize.w)).xyz + - texture(texture_sampler, uv2 + vec2(0, -d2 * srctexsize.w)).xyz) * - w2; - blur.xyz *= w_div; - - // tone it down at the edges (only happens on 1st X pass!) - float t = min(min(fragment_texture.x, fragment_texture.y), - 1.0 - max(fragment_texture.x, fragment_texture.y)); - t = sqrt(t); - t = edge_darken_c1 + edge_darken_c2 * clamp(t * edge_darken_c3, 0.0, 1.0); - blur.xyz *= t; - - color.xyz = blur; - color.w = 1.0; -} -)"; - -} // namespace - -StaticGlShaders::StaticGlShaders(bool use_gles) : use_gles_(use_gles) { - version_ = QueryGlslVersion(); - - if (version_.major == 0) - { - throw std::runtime_error("Could not retrieve OpenGL shader language version. Is OpenGL available and the context initialized?"); - } - - if (use_gles_) { - // If GLES is specified, override the version header. - version_header_ = "#version 300 es"; - glsl_generator_version_ = M4::GLSLGenerator::Version::Version_300_ES; - } else { - if (version_.major < 3) { - // For all GLSL versions less than 3.*, use the GLSL1.2 shaders. - version_header_ = "#version 120"; - glsl_generator_version_ = M4::GLSLGenerator::Version::Version_120; - } else { - version_header_ = "#version 330"; - glsl_generator_version_ = M4::GLSLGenerator::Version::Version_330; - } - } -} - -StaticGlShaders::GlslVersion StaticGlShaders::QueryGlslVersion() { - /* In the linux desktop environment with --use-gles configured, the parsing of the GL_SHADING_LANGUAGE_VERSION - string comes back as "OpenGL ES GLSL ES 3" - And I think this was supposed to be parsing somethign like - "3.10 etc etc" - This caused exceptions to be raised in the std::stoi section; - - So - The parsing will look for ['.' ] [] - and will default to 3.0 for the version in case of errors - */ - - int major = 3; /* 3.0 is default */ - int minor = 0; - - const char* shaderLanguageVersion = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); - - if (shaderLanguageVersion == nullptr) - { - return GlslVersion{0, 0}; - } - - std::string glsl_version_string{shaderLanguageVersion}; - - size_t version_len = glsl_version_string.length(); - /* make a c version of the string and do the conversion to integers manually just for this case */ - if (version_len) { // find the number - size_t position = 0; - char *cstr = new char [version_len+1]; - - strcpy(cstr,glsl_version_string.c_str()); - - /* scan the anything before the number */ - while (position= '0') && (ch <= '9')) { - break; - } - position++; - } - - /* scan the first number */ - { - int possible_major = 0; - while (position= '0') && (ch <= '9')) { - possible_major = (possible_major * 10) + ch - '0'; - } - else if (ch == '.') { /* got the minor */ - int possible_minor = 0; - position++; - while (position= '0') && (ch <= '9')) { - possible_minor = (possible_minor * 10) + ch - '0'; - } - else break; - position++; - } /* while scanning the minor version */ - if (possible_major) { /* set the minor version only if the major number is valid */ - minor = possible_minor; - } - break; // We scanned it - } - else { /* not a number or period */ - break; - } - position++; - } /* while scanning the major number */ - if (possible_major) { - major = possible_major; - } - } /* scanning block */ - delete[] cstr; - } /* if there is a string to parse */ - - return GlslVersion{major, minor}; -} - -std::string StaticGlShaders::AddVersionHeader(std::string shader_text) { - return version_header_ + "\n" + shader_text; -} - -#define DECLARE_SHADER_ACCESSOR(name) \ - std::string StaticGlShaders::Get##name() { \ - if (use_gles_) { \ - return AddVersionHeader(k##name##Glsl330); \ - } \ - if (version_.major < 3) { \ - return AddVersionHeader(k##name##Glsl120); \ - } \ - return AddVersionHeader(k##name##Glsl330); \ - } - -#define DECLARE_SHADER_ACCESSOR_NO_HEADER(name) \ - std::string StaticGlShaders::Get##name() { \ - if (use_gles_) { \ - return k##name##Glsl330; \ - } \ - if (version_.major < 3) { \ - return k##name##Glsl120; \ - } \ - return k##name##Glsl330; \ - } - -DECLARE_SHADER_ACCESSOR(PresetMotionVectorsVertexShader); -DECLARE_SHADER_ACCESSOR(PresetWarpVertexShader); -DECLARE_SHADER_ACCESSOR(PresetWarpFragmentShader); -DECLARE_SHADER_ACCESSOR(PresetCompVertexShader); -DECLARE_SHADER_ACCESSOR(V2fC4fVertexShader); -DECLARE_SHADER_ACCESSOR(V2fC4fFragmentShader); -DECLARE_SHADER_ACCESSOR(V2fC4fT2fVertexShader); -DECLARE_SHADER_ACCESSOR(V2fC4fT2fFragmentShader); -DECLARE_SHADER_ACCESSOR(BlurVertexShader); -DECLARE_SHADER_ACCESSOR(Blur1FragmentShader); -DECLARE_SHADER_ACCESSOR(Blur2FragmentShader); -DECLARE_SHADER_ACCESSOR_NO_HEADER(PresetShaderHeader); diff --git a/src/libprojectM/Renderer/StaticGlShaders.hpp b/src/libprojectM/Renderer/StaticGlShaders.hpp deleted file mode 100644 index b3f6cd08f..000000000 --- a/src/libprojectM/Renderer/StaticGlShaders.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#include - -#include "GLSLGenerator.h" - -// Singleton manager for static resource GL shaders. The manager provides -// shaders through its accessor methods, and selects the appropriate shader -// version to be compatible with the system GLSL version. -class StaticGlShaders { - public: - // Returns the singleton StaticGlShaders instance. - static std::shared_ptr Get() { - bool use_gles = false; -#if USE_GLES - use_gles = true; -#endif - - static std::shared_ptr instance( - new StaticGlShaders(use_gles)); - return instance; - } - - // Returns the GLSLGenerator version enum value corresponding to the queried - // OpenGL shader version. - M4::GLSLGenerator::Version GetGlslGeneratorVersion() { - return glsl_generator_version_; - } - - // Returns the named static GL shader resource. - std::string GetPresetMotionVectorsVertexShader(); - std::string GetPresetWarpVertexShader(); - std::string GetPresetWarpFragmentShader(); - std::string GetPresetCompVertexShader(); - std::string GetV2fC4fVertexShader(); - std::string GetV2fC4fFragmentShader(); - std::string GetV2fC4fT2fVertexShader(); - std::string GetV2fC4fT2fFragmentShader(); - std::string GetBlurVertexShader(); - std::string GetBlur1FragmentShader(); - std::string GetBlur2FragmentShader(); - std::string GetPresetShaderHeader(); - - private: - // POD struct to store parsed GLSL version numbers. - struct GlslVersion { - int major, minor; - }; - - // Queries the system GLSL version using - // `glGetString(GL_SHADING_LANGUAGE_VERSION)` and returns the major and - // minor numbers. - GlslVersion QueryGlslVersion(); - - // Constructs a StaticGlShaders, overriding the version to GLES3 if - // `use_gles` is true. - // Note - this happens after GlslVersion is called, because it uses the - // version to determine things. - StaticGlShaders(bool use_gles); - - - // Prepends a string of the form "#version \n" to the provided - // shader text, where is derived from the queried GLSL version (or - // overridden when the manager was constructed with `use_gles` = true). - std::string AddVersionHeader(std::string shader_text); - - // Whether or not to use GLES shaders. - bool use_gles_; - - // The queried GLSL version. - GlslVersion version_; - - // The version header to prepended by AddVersionHeader. - std::string version_header_; - - // The GLSL generator version to pass to the hlslparser generator. - M4::GLSLGenerator::Version glsl_generator_version_; -}; diff --git a/src/libprojectM/Renderer/TextureManager.cpp b/src/libprojectM/Renderer/TextureManager.cpp index eb3ea52bd..3100b4ad9 100644 --- a/src/libprojectM/Renderer/TextureManager.cpp +++ b/src/libprojectM/Renderer/TextureManager.cpp @@ -1,5 +1,4 @@ #include "TextureManager.hpp" -#include "Common.hpp" #include "IdleTextures.hpp" #include "SOIL2/SOIL2.h" #include "Texture.hpp" @@ -23,6 +22,10 @@ TextureManager::TextureManager(const std::vector& textureSearchPath Preload(); } +void TextureManager::SetCurrentPresetPath(const std::string& path) +{ +} + TextureSamplerDescriptor TextureManager::GetTexture(const std::string& fullName) { std::string unqualifiedName; @@ -388,4 +391,3 @@ void TextureManager::ExtractTextureSettings(const std::string& qualifiedName, GL wrapMode = GL_REPEAT; } } -