diff --git a/src/libprojectM/Renderer/Makefile.am b/src/libprojectM/Renderer/Makefile.am index 60a2c2820..f5b4cc371 100644 --- a/src/libprojectM/Renderer/Makefile.am +++ b/src/libprojectM/Renderer/Makefile.am @@ -11,6 +11,7 @@ libRenderer_la_SOURCES = \ Pipeline.cpp \ Renderer.cpp \ ShaderEngine.cpp \ + StaticGlShaders.cpp \ Texture.cpp \ Waveform.cpp \ Filters.cpp \ diff --git a/src/libprojectM/Renderer/ShaderEngine.cpp b/src/libprojectM/Renderer/ShaderEngine.cpp index 72f41177d..0db4d4c4e 100644 --- a/src/libprojectM/Renderer/ShaderEngine.cpp +++ b/src/libprojectM/Renderer/ShaderEngine.cpp @@ -11,389 +11,32 @@ #include "Texture.hpp" #include "HLSLParser.h" #include "GLSLGenerator.h" +#include "StaticGlShaders.h" #include // glm::mat4 #include // glm::translate, glm::rotate, glm::scale, glm::perspective #include #include #include -#ifdef USE_GLES - #define GLSL_VERSION "300 es" - #define SHADER_VERSION M4::GLSLGenerator::Version_300_ES -#else - #define GLSL_VERSION "120" - #define SHADER_VERSION M4::GLSLGenerator::Version_120 -#endif - - #define FRAND ((rand() % 7381)/7380.0f) - -std::string presetWarpVertexShader( - "#version " - GLSL_VERSION - "\n" - "attribute vec2 vertex_position;\n" - "attribute vec4 vertex_color;\n" - "attribute vec2 vertex_texture;\n" - "" - "uniform mat4 vertex_transformation;\n" - "" - "varying vec4 frag_COLOR;\n" - "varying vec4 frag_TEXCOORD0;\n" - "varying vec2 frag_TEXCOORD1;\n" - "" - "void main(){\n" - " vec4 position = vertex_transformation * vec4(vertex_position, 0.0, 1.0);\n" - " gl_Position = position;\n" - " frag_COLOR = vertex_color;\n" - " frag_TEXCOORD0.xy = vertex_texture;\n" - " frag_TEXCOORD0.zw = position.xy;\n" - " frag_TEXCOORD1 = vec2(0.0, 0.0);\n" - "}\n"); - -std::string presetCompVertexShader( - "#version " - GLSL_VERSION - "\n" - "attribute vec2 vertex_position;\n" - "attribute vec4 vertex_color;\n" - "attribute vec2 vertex_texture;\n" - "attribute vec2 vertex_rad_ang;\n" - "" - "varying vec4 frag_COLOR;\n" - "varying vec2 frag_TEXCOORD0;\n" - "varying vec2 frag_TEXCOORD1;\n" - "" - "void main(){\n" - " vec4 position = vec4(vertex_position, 0.0, 1.0);\n" - " gl_Position = position;\n" - " frag_COLOR = vertex_color;\n" - " frag_TEXCOORD0 = vertex_texture;\n" - " frag_TEXCOORD1 = vertex_rad_ang;\n" - "}\n"); - - -const std::string ShaderEngine::v2f_c4f_vert( - "#version " - GLSL_VERSION - "\n" - "" - "attribute vec2 vertex_position;\n" - "attribute vec4 vertex_color;\n" - "" - "uniform mat4 vertex_transformation;\n" - "uniform float vertex_point_size;\n" - "" - "varying vec4 fragment_color;\n" - "" - "void main(){\n" - " gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0);\n" - " gl_PointSize = vertex_point_size;\n" - " fragment_color = vertex_color;\n" - "}\n"); - -const std::string ShaderEngine::v2f_c4f_frag( - "#version " - GLSL_VERSION - "\n" - "" - "varying vec4 fragment_color;\n" - "" - "void main(){\n" - " gl_FragColor = fragment_color;\n" - "}\n"); - -const std::string ShaderEngine::v2f_c4f_t2f_vert( - "#version " - GLSL_VERSION - "\n" - "attribute vec2 vertex_position;\n" - "attribute vec4 vertex_color;\n" - "attribute vec2 vertex_texture;\n" - "" - "uniform mat4 vertex_transformation;\n" - "" - "varying vec4 fragment_color;\n" - "varying vec2 fragment_texture;\n" - "" - "void main(){\n" - " gl_Position = vertex_transformation * vec4(vertex_position, 0.0, 1.0);\n" - " fragment_color = vertex_color;\n" - " fragment_texture = vertex_texture;\n" - "}\n"); - -const std::string ShaderEngine::v2f_c4f_t2f_frag( - "#version " - GLSL_VERSION - "\n" - "" - "varying vec4 fragment_color;\n" - "varying vec2 fragment_texture;\n" - "" - "uniform sampler2D texture_sampler;\n" - "" - "varying vec4 color;\n" - "" - "void main(){\n" - " gl_FragColor = fragment_color * texture2D(texture_sampler, fragment_texture.st);\n" - "}\n"); - - -std::string PresetShaderIncludes = "" -"#define M_PI 3.14159265359\n" -"#define M_PI_2 6.28318530718\n" -"#define M_INV_PI_2 0.159154943091895\n" - -"uniform float4 rand_frame; // random float4, updated each frame\n" -"uniform float4 rand_preset; // random float4, updated once per *preset*\n" -"uniform float4 _c0; // .xy: multiplier to use on UV's to paste an image fullscreen, *aspect-aware*; .zw = inverse.\n" -"uniform float4 _c1, _c2, _c3, _c4;\n" -"uniform float4 _c5; //.xy = scale,bias for reading blur1; .zw = scale,bias for reading blur2; \n" -"uniform float4 _c6; //.xy = scale,bias for reading blur3; .zw = blur1_min,blur1_max\n" -"uniform float4 _c7; // .xy ~= float2(1024,768); .zw ~= float2(1/1024.0, 1/768.0)\n" -"uniform float4 _c8; // .xyzw ~= 0.5 + 0.5*cos(time * float4(~0.3, ~1.3, ~5, ~20))\n" -"uniform float4 _c9; // .xyzw ~= same, but using sin()\n" -"uniform float4 _c10; // .xyzw ~= 0.5 + 0.5*cos(time * float4(~0.005, ~0.008, ~0.013, ~0.022))\n" -"uniform float4 _c11; // .xyzw ~= same, but using sin()\n" -"uniform float4 _c12; // .xyz = mip info for main image (.x=#across, .y=#down, .z=avg); .w = unused\n" -"uniform float4 _c13; //.xy = blur2_min,blur2_max; .zw = blur3_min, blur3_max.\n" -"uniform float4 _qa; // q vars bank 1 [q1-q4]\n" -"uniform float4 _qb; // q vars bank 2 [q5-q8]\n" -"uniform float4 _qc; // q vars ...\n" -"uniform float4 _qd; // q vars\n" -"uniform float4 _qe; // q vars\n" -"uniform float4 _qf; // q vars\n" -"uniform float4 _qg; // q vars\n" -"uniform float4 _qh; // q vars bank 8 [q29-q32]\n" - -"// note: in general, don't use the current time w/the *dynamic* rotations!\n" -"uniform float4 rot_s1; // four random, static rotations. randomized @ preset load time.\n" -"uniform float4 rot_s2; // minor translation component (<1).\n" -"uniform float4 rot_s3;\n" -"uniform float4 rot_s4;\n" - -"uniform float4 rot_d1; // four random, slowly changing rotations.\n" -"uniform float4 rot_d2; \n" -"uniform float4 rot_d3;\n" -"uniform float4 rot_d4;\n" -"uniform float4 rot_f1; // faster-changing.\n" -"uniform float4 rot_f2;\n" -"uniform float4 rot_f3;\n" -"uniform float4 rot_f4;\n" -"uniform float4 rot_vf1; // very-fast-changing.\n" -"uniform float4 rot_vf2;\n" -"uniform float4 rot_vf3;\n" -"uniform float4 rot_vf4;\n" -"uniform float4 rot_uf1; // ultra-fast-changing.\n" -"uniform float4 rot_uf2;\n" -"uniform float4 rot_uf3;\n" -"uniform float4 rot_uf4;\n" - -"uniform float4 rot_rand1; // random every frame\n" -"uniform float4 rot_rand2;\n" -"uniform float4 rot_rand3;\n" -"uniform float4 rot_rand4;\n" - -"#define time _c2.x\n" -"#define fps _c2.y\n" -"#define frame _c2.z\n" -"#define progress _c2.w\n" -"#define bass _c3.x\n" -"#define mid _c3.y\n" -"#define treb _c3.z\n" -"#define vol _c3.w\n" -"#define bass_att _c4.x\n" -"#define mid_att _c4.y\n" -"#define treb_att _c4.z\n" -"#define vol_att _c4.w\n" -"#define q1 _qa.x\n" -"#define q2 _qa.y\n" -"#define q3 _qa.z\n" -"#define q4 _qa.w\n" -"#define q5 _qb.x\n" -"#define q6 _qb.y\n" -"#define q7 _qb.z\n" -"#define q8 _qb.w\n" -"#define q9 _qc.x\n" -"#define q10 _qc.y\n" -"#define q11 _qc.z\n" -"#define q12 _qc.w\n" -"#define q13 _qd.x\n" -"#define q14 _qd.y\n" -"#define q15 _qd.z\n" -"#define q16 _qd.w\n" -"#define q17 _qe.x\n" -"#define q18 _qe.y\n" -"#define q19 _qe.z\n" -"#define q20 _qe.w\n" -"#define q21 _qf.x\n" -"#define q22 _qf.y\n" -"#define q23 _qf.z\n" -"#define q24 _qf.w\n" -"#define q25 _qg.x\n" -"#define q26 _qg.y\n" -"#define q27 _qg.z\n" -"#define q28 _qg.w\n" -"#define q29 _qh.x\n" -"#define q30 _qh.y\n" -"#define q31 _qh.z\n" -"#define q32 _qh.w\n" - -"#define aspect _c0\n" -"#define texsize _c7 // .xy = (w,h); .zw = (1/(float)w, 1/(float)h)\n" -"#define roam_cos _c8\n" -"#define roam_sin _c9\n" -"#define slow_roam_cos _c10\n" -"#define slow_roam_sin _c11\n" -"#define mip_x _c12.x\n" -"#define mip_y _c12.y\n" -"#define mip_xy _c12.xy\n" -"#define mip_avg _c12.z\n" -"#define blur1_min _c6.z\n" -"#define blur1_max _c6.w\n" -"#define blur2_min _c13.x\n" -"#define blur2_max _c13.y\n" -"#define blur3_min _c13.z\n" -"#define blur3_max _c13.w\n" - -"#define sampler_FC_main sampler_fc_main\n" -"#define sampler_PC_main sampler_pc_main\n" -"#define sampler_FW_main sampler_fw_main\n" -"#define sampler_PW_main sampler_pw_main\n" - -"#define GetMain(uv) (tex2D(sampler_main,uv).xyz)\n" -"#define GetPixel(uv) (tex2D(sampler_main,uv).xyz)\n" -"#define GetBlur1(uv) (tex2D(sampler_blur1,uv).xyz*_c5.x + _c5.y)\n" -"#define GetBlur2(uv) (tex2D(sampler_blur2,uv).xyz*_c5.z + _c5.w)\n" -"#define GetBlur3(uv) (tex2D(sampler_blur3,uv).xyz*_c6.x + _c6.y)\n" - -"#define lum(x) (dot(x,float3(0.32,0.49,0.29)))\n" -"#define tex2d tex2D\n" -"#define tex3d tex3D\n" -; - - -std::string blur_vert( - "#version " - GLSL_VERSION - "\n" - "attribute vec2 vertex_position;\n" - "attribute vec2 vertex_texture;\n" - "" - "varying vec2 fragment_texture;\n" - "" - "void main(){\n" - " gl_Position = vec4(vertex_position, 0.0, 1.0);\n" - " fragment_texture = vertex_texture;\n" - "}\n"); - - -std::string blur1_frag( - "#version " - GLSL_VERSION - "\n" - "" - "varying vec2 fragment_texture;\n" - "" - "uniform sampler2D texture_sampler;\n" - "uniform vec4 _c0; // source texsize (.xy), and inverse (.zw)\n" - "uniform vec4 _c1; // w1..w4\n" - "uniform vec4 _c2; // d1..d4\n" - "uniform vec4 _c3; // scale, bias, w_div\n" - "" - "void main(){\n" - "" - " // LONG HORIZ. PASS 1:\n" - " #define srctexsize _c0\n" - " #define w1 _c1.x\n" - " #define w2 _c1.y\n" - " #define w3 _c1.z\n" - " #define w4 _c1.w\n" - " #define d1 _c2.x\n" - " #define d2 _c2.y\n" - " #define d3 _c2.z\n" - " #define d4 _c2.w\n" - " #define fscale _c3.x\n" - " #define fbias _c3.y\n" - " #define w_div _c3.z\n" - "" - " // note: if you just take one sample at exactly uv.xy, you get an avg of 4 pixels.\n" - " vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(1.0,1.0); // + moves blur UP, LEFT by 1-pixel increments\n" - "" - " vec3 blur = \n" - " ( texture2D( texture_sampler, uv2 + vec2( d1*srctexsize.z,0) ).xyz\n" - " + texture2D( texture_sampler, uv2 + vec2(-d1*srctexsize.z,0) ).xyz)*w1 +\n" - " ( texture2D( texture_sampler, uv2 + vec2( d2*srctexsize.z,0) ).xyz\n" - " + texture2D( texture_sampler, uv2 + vec2(-d2*srctexsize.z,0) ).xyz)*w2 +\n" - " ( texture2D( texture_sampler, uv2 + vec2( d3*srctexsize.z,0) ).xyz\n" - " + texture2D( texture_sampler, uv2 + vec2(-d3*srctexsize.z,0) ).xyz)*w3 +\n" - " ( texture2D( texture_sampler, uv2 + vec2( d4*srctexsize.z,0) ).xyz\n" - " + texture2D( texture_sampler, uv2 + vec2(-d4*srctexsize.z,0) ).xyz)*w4\n" - " ;\n" - " blur.xyz *= w_div;\n" - "" - " blur.xyz = blur.xyz*fscale + fbias;\n" - "" - " gl_FragColor.xyz = blur;\n" - " gl_FragColor.w = 1.0;\n" - "}\n"); - -std::string blur2_frag( - "#version " - GLSL_VERSION - "\n" - "" - "varying vec2 fragment_texture;\n" - "" - "uniform sampler2D texture_sampler;\n" - "uniform vec4 _c0; // source texsize (.xy), and inverse (.zw)\n" - "uniform vec4 _c5; // w1,w2,d1,d2\n" - "uniform vec4 _c6; // w_div, edge_darken_c1, edge_darken_c2, edge_darken_c3\n" - "" - "void main(){\n" - "" - " //SHORT VERTICAL PASS 2:\n" - " #define srctexsize _c0\n" - " #define w1 _c5.x\n" - " #define w2 _c5.y\n" - " #define d1 _c5.z\n" - " #define d2 _c5.w\n" - " #define edge_darken_c1 _c6.y\n" - " #define edge_darken_c2 _c6.z\n" - " #define edge_darken_c3 _c6.w\n" - " #define w_div _c6.x\n" - "" - " // note: if you just take one sample at exactly uv.xy, you get an avg of 4 pixels.\n" - " vec2 uv2 = fragment_texture.xy + srctexsize.zw*vec2(0,0); // + moves blur UP, LEFT by TWO-pixel increments! (since texture is 1/2 the size of blur1_ps)\n" - "" - " vec3 blur = \n" - " ( texture2D( texture_sampler, uv2 + vec2(0, d1*srctexsize.w) ).xyz\n" - " + texture2D( texture_sampler, uv2 + vec2(0,-d1*srctexsize.w) ).xyz)*w1 +\n" - " ( texture2D( texture_sampler, uv2 + vec2(0, d2*srctexsize.w) ).xyz\n" - " + texture2D( texture_sampler, uv2 + vec2(0,-d2*srctexsize.w) ).xyz)*w2\n" - " ;\n" - " blur.xyz *= w_div;\n" - "" - " // tone it down at the edges: (only happens on 1st X pass!)\n" - " float t = min( min(fragment_texture.x, fragment_texture.y), 1.0-max(fragment_texture.x, fragment_texture.y) );\n" - " t = sqrt(t);\n" - " t = edge_darken_c1 + edge_darken_c2*clamp(t*edge_darken_c3, 0.0, 1.0);\n" - " blur.xyz *= t;\n" - "" - " gl_FragColor.xyz = blur;\n" - " gl_FragColor.w = 1.0;\n" - "}\n"); - - - ShaderEngine::ShaderEngine() : presetCompShaderLoaded(false), presetWarpShaderLoaded(false) { - programID_v2f_c4f = CompileShaderProgram(v2f_c4f_vert, v2f_c4f_frag, "v2f_c4f"); - programID_v2f_c4f_t2f = CompileShaderProgram(v2f_c4f_t2f_vert, v2f_c4f_t2f_frag, "v2f_c4f_t2f"); + std::shared_ptr static_gl_shaders = StaticGlShaders::Get(); - programID_blur1 = CompileShaderProgram(blur_vert, blur1_frag, "blur1"); - programID_blur2 = CompileShaderProgram(blur_vert, blur2_frag, "blur2"); + programID_v2f_c4f = CompileShaderProgram( + static_gl_shaders->GetV2fC4fVertexShader(), + static_gl_shaders->GetV2fC4fFragmentShader(), "v2f_c4f"); + programID_v2f_c4f_t2f = CompileShaderProgram( + static_gl_shaders->GetV2fC4fT2fVertexShader(), + static_gl_shaders->GetV2fC4fT2fFragmentShader(), "v2f_c4f_t2f"); + + programID_blur1 = CompileShaderProgram( + static_gl_shaders->GetBlurVertexShader(), + static_gl_shaders->GetBlur1FragmentShader(), "blur1"); + programID_blur2 = CompileShaderProgram( + static_gl_shaders->GetBlurVertexShader(), + static_gl_shaders->GetBlur2FragmentShader(), "blur2"); uniform_v2f_c4f_vertex_tranformation = glGetUniformLocation(programID_v2f_c4f, "vertex_transformation"); uniform_v2f_c4f_vertex_point_size = glGetUniformLocation(programID_v2f_c4f, "vertex_point_size"); @@ -633,7 +276,7 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha std::string fullSource; // prepend our HLSL template to the actual program source - fullSource.append(PresetShaderIncludes); + fullSource.append(StaticGlShaders::Get()->GetPresetShaderHeader()); if (shaderType == PresentWarpShader) { fullSource.append( "#define rad _rad_ang.x\n" @@ -734,7 +377,9 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha } // generate GLSL - if (!generator.Generate(&tree, M4::GLSLGenerator::Target_FragmentShader, SHADER_VERSION, "PS")) { + if (!generator.Generate(&tree, M4::GLSLGenerator::Target_FragmentShader, + StaticGlShaders::Get()->GetGlslGeneratorVersion(), + "PS")) { std::cerr << "Failed to transpile HLSL(step3) " << shaderTypeString << " shader to GLSL" << std::endl; #if !DUMP_SHADERS_ON_ERROR std::cerr << "Source: " << std::endl << sourcePreprocessed << std::endl; @@ -746,13 +391,18 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha return GL_FALSE; } - // now we have GLSL source for the preset shader program (hopefully it's valid!) - // copmile the preset shader fragment shader with the standard vertex shader and cross our fingers + // now we have GLSL source for the preset shader program (hopefully it's + // valid!) copmile the preset shader fragment shader with the standard + // vertex shader and cross our fingers GLuint ret = 0; if (shaderType == PresentWarpShader) { - ret = CompileShaderProgram(presetWarpVertexShader, generator.GetResult(), shaderTypeString); // returns new program + ret = CompileShaderProgram( + StaticGlShaders::Get()->GetPresetWarpVertexShader(), + generator.GetResult(), shaderTypeString); } else { - ret = CompileShaderProgram(presetCompVertexShader, generator.GetResult(), shaderTypeString); // returns new program + ret = CompileShaderProgram( + StaticGlShaders::Get()->GetPresetCompVertexShader(), + generator.GetResult(), shaderTypeString); } if (ret != GL_FALSE) { diff --git a/src/libprojectM/Renderer/StaticGlShaders.cpp b/src/libprojectM/Renderer/StaticGlShaders.cpp new file mode 100644 index 000000000..52afd1fb2 --- /dev/null +++ b/src/libprojectM/Renderer/StaticGlShaders.cpp @@ -0,0 +1,822 @@ +#include "StaticGlShaders.h" + +#include + +namespace { +// Variants of shaders for GLSL1.2 +const std::string kPresetWarpVertexShaderGlsl120 = R"( +attribute vec2 vertex_position; +attribute vec4 vertex_color; +attribute vec2 vertex_texture; + +uniform mat4 vertex_transformation; + +varying vec4 frag_COLOR; +varying vec4 frag_TEXCOORD0; +varying vec2 frag_TEXCOORD1; + +void main(){ + vec4 position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); + gl_Position = position; + frag_COLOR = vertex_color; + frag_TEXCOORD0.xy = vertex_texture; + frag_TEXCOORD0.zw = position.xy; + frag_TEXCOORD1 = vec2(0.0, 0.0); +} +)"; + +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 kPresetWarpVertexShaderGlsl330 = 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 frag_COLOR; +out vec4 frag_TEXCOORD0; +out vec2 frag_TEXCOORD1; + +void main(){ + vec4 position = vertex_transformation * vec4(vertex_position, 0.0, 1.0); + gl_Position = position; + frag_COLOR = vertex_color; + frag_TEXCOORD0.xy = vertex_texture; + frag_TEXCOORD0.zw = position.xy; + frag_TEXCOORD1 = vec2(0.0, 0.0); +} +)"; + +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 * texture2D(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 = + (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; + + 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 = + (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; + + color.xyz = blur; + color.w = 1.0; +} +)"; + +} // namespace + +StaticGlShaders::StaticGlShaders(bool use_gles) : use_gles_(use_gles) { + version_ = QueryGlslVersion(); + + 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() { + std::string glsl_version_string = reinterpret_cast( + glGetString(GL_SHADING_LANGUAGE_VERSION)); + size_t dot_location = glsl_version_string.find('.'); + size_t end_location = glsl_version_string.find(' '); + auto major_string = glsl_version_string.substr(0, dot_location); + auto minor_string = glsl_version_string.substr(dot_location + 1, + end_location - dot_location); + int major = std::stoi(major_string); + int minor = std::stoi(minor_string); + + return GlslVersion{.major = major, .minor = 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(PresetWarpVertexShader); +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.h b/src/libprojectM/Renderer/StaticGlShaders.h new file mode 100644 index 000000000..8500dce8a --- /dev/null +++ b/src/libprojectM/Renderer/StaticGlShaders.h @@ -0,0 +1,72 @@ +#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; +#ifdef 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 GetPresetWarpVertexShader(); + 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; + }; + + // Constructs a StaticGlShaders, overriding the version to GLES3 if + // `use_gles` is true. + StaticGlShaders(bool use_gles); + + // Queries the system GLSL version using + // `glGetString(GL_SHADING_LANGUAGE_VERSION)` and returns the major and + // minor numbers. + GlslVersion QueryGlslVersion(); + + // 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/projectM-sdl/Makefile.am b/src/projectM-sdl/Makefile.am index 976b0aaac..b681c3039 100644 --- a/src/projectM-sdl/Makefile.am +++ b/src/projectM-sdl/Makefile.am @@ -3,6 +3,7 @@ ${my_CFLAGS} \ -include $(top_builddir)/config.h \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -I${top_srcdir}/src/libprojectM \ +-I$(top_srcdir)/src/libprojectM/Renderer/hlslparser/src \ -I${top_srcdir}/src/libprojectM/Renderer \ ${SDL_CFLAGS} diff --git a/src/projectM-sdl/pmSDL.cpp b/src/projectM-sdl/pmSDL.cpp index 39fff6a40..331a8711a 100644 --- a/src/projectM-sdl/pmSDL.cpp +++ b/src/projectM-sdl/pmSDL.cpp @@ -32,6 +32,7 @@ #include #include #include "Renderer/ShaderEngine.hpp" +#include "Renderer/StaticGlShaders.h" void projectMSDL::audioInputCallbackF32(void *userdata, unsigned char *stream, int len) { @@ -499,7 +500,9 @@ void projectMSDL::init(SDL_Window *window, SDL_GLContext *_glCtx, const bool _re // are we rendering to a texture? renderToTexture = _renderToTexture; if (renderToTexture) { - programID = ShaderEngine::CompileShaderProgram(ShaderEngine::v2f_c4f_t2f_vert, ShaderEngine::v2f_c4f_t2f_frag, "v2f_c4f_t2f"); + programID = ShaderEngine::CompileShaderProgram( + StaticGlShaders::Get()->GetV2fC4fT2fVertexShader(), + StaticGlShaders::Get()->GetV2fC4fT2fFragmentShader(), "v2f_c4f_t2f"); textureID = projectM::initRenderToTexture(); float points[16] = {