diff --git a/CMakeLists.txt b/CMakeLists.txt index 171bb5c..b3f32b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ +cmake_minimum_required(VERSION 3.5) project(visualization.shadertoy) -cmake_minimum_required(VERSION 2.6) - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) find_package(Kodi REQUIRED) @@ -9,54 +8,35 @@ find_package(p8-platform REQUIRED) add_subdirectory(lib/kissfft) -set(DEPLIBS kissfft) - -if (NOT WIN32) - if(APPLE) - set(DEPLIBS ${DEPLIBS} "-framework CoreVideo") - endif() - - add_options(CXX ALL_BUILDS -std=c++11) - +if(NOT WIN32) if(APP_RENDER_SYSTEM STREQUAL "gl" OR NOT APP_RENDER_SYSTEM) - find_package(OpenGL) - if(OPENGL_FOUND) - set(INCLUDES ${OpenGL_INCLUDE_DIR}) - add_definitions(-DHAS_OPENGL) - set(DEPLIBS ${DEPLIBS} ${OPENGL_LIBRARIES}) - set(APP_RENDER_SYSTEM gl) - endif() + find_package(OpenGl REQUIRED) + set(DEPLIBS ${OPENGL_LIBRARIES}) + set(includes ${OPENGL_INCLUDE_DIR}) + add_definitions(${OPENGL_DEFINITIONS}) + else() + find_package(OpenGLES REQUIRED) + set(DEPLIBS ${OPENGLES_LIBRARIES}) + set(includes ${OPENGLES_INCLUDE_DIR}) + add_definitions(${OPENGLES_DEFINITIONS}) endif() - if(APP_RENDER_SYSTEM STREQUAL "gles" OR NOT APP_RENDER_SYSTEM) - find_package(OpenGLES2) - if(OPENGLES2_FOUND) - set(INCLUDES ${OPENGLES2_INCLUDE_DIR}) - add_definitions(-DHAS_GLES2 -DHAS_GLES ${OpenGLES2_CFLAGS_OTHER}) - set(DEPLIBS ${DEPLIBS} ${OPENGLES2_LIBRARIES}) - set(APP_RENDER_SYSTEM gles) - endif() - endif() - if(NOT APP_RENDER_SYSTEM) - message(FATAL_ERROR "No rendering API found. Bailing") - endif() + include_directories(${GLM_INCLUDE_DIR} + ${KODI_INCLUDE_DIR}/.. # Hack way with "/..", need bigger Kodi cmake rework to match right include ways + ${PROJECT_SOURCE_DIR}/lib) - include_directories(${OpenGL_INCLUDE_DIR} - ${KODI_INCLUDE_DIR}/.. # Hack way with "/..", need bigger Kodi cmake rework to match right include ways (becomes done in future) - ${p8-platform_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR}/lib/kissfft - ${CMAKE_INCLUDE_PATH}) + if(${CORE_SYSTEM_NAME} STREQUAL "osx" OR + ${CORE_SYSTEM_NAME} STREQUAL "ios" OR + ${CORE_SYSTEM_NAME} STREQUAL "darwin_embedded") + list(APPEND DEPLIBS "-framework CoreVideo") + endif() set(SHADERTOY_SOURCES src/lodepng.cpp src/main.cpp) set(SHADERTOY_HEADERS src/lodepng.h - src/WICTextureLoader.h) - - set(DEPLIBS ${DEPLIBS} ${OPENGL_LIBRARIES}) - + src/main.h) elseif(WIN32) - set(APP_RENDER_SYSTEM dx11) include_directories(${KODI_INCLUDE_DIR}/.. # Hack way with "/..", need bigger Kodi cmake rework to match right include ways (becomes done in future) ${p8-platform_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/lib/kissfft @@ -69,7 +49,8 @@ elseif(WIN32) src/WICTextureLoader.h) endif() -message(STATUS "Configured render system: ${APP_RENDER_SYSTEM}") +list(APPEND DEPLIBS kissfft) +list(APPEND DEPENDS glm) build_addon(visualization.shadertoy SHADERTOY DEPLIBS) diff --git a/FindOpenGLES.cmake b/FindOpenGLES.cmake new file mode 100644 index 0000000..87a62cc --- /dev/null +++ b/FindOpenGLES.cmake @@ -0,0 +1,56 @@ +#.rst: +# FindOpenGLES +# ------------ +# Finds the OpenGLES2 and OpenGLES3 library +# +# This will define the following variables: +# +# OPENGLES_FOUND - system has OpenGLES +# OPENGLES_INCLUDE_DIRS - the OpenGLES include directory +# OPENGLES_LIBRARIES - the OpenGLES libraries +# OPENGLES_DEFINITIONS - the OpenGLES definitions +# + +if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) + set(_brcmprefix brcm) +endif() + +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_OPENGLES ${_brcmprefix}glesv2 QUIET) +endif() + +if(NOT CORE_SYSTEM_NAME STREQUAL ios AND + NOT CORE_SYSTEM_NAME STREQUAL darwin_embedded) + find_path(OPENGLES_INCLUDE_DIR GLES2/gl2.h + PATHS ${PC_OPENGLES_INCLUDEDIR}) + find_library(OPENGLES_gl_LIBRARY NAMES ${_brcmprefix}GLESv2 + PATHS ${PC_OPENGLES_LIBDIR}) +else() + find_library(OPENGLES_gl_LIBRARY NAMES OpenGLES + PATHS ${CMAKE_OSX_SYSROOT}/System/Library + PATH_SUFFIXES Frameworks + NO_DEFAULT_PATH) + set(OPENGLES_INCLUDE_DIR ${OPENGLES_gl_LIBRARY}/Headers) +endif() + +find_path(OPENGLES3_INCLUDE_DIR GLES3/gl3.h) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OpenGLES + REQUIRED_VARS OPENGLES_gl_LIBRARY OPENGLES_INCLUDE_DIR) + +find_path(OPENGLES3_INCLUDE_DIR GLES3/gl3.h + PATHS ${PC_OPENGLES_INCLUDEDIR}) + +if(OPENGLES_FOUND) + set(OPENGLES_LIBRARIES ${OPENGLES_gl_LIBRARY}) + if(OPENGLES3_INCLUDE_DIR) + set(OPENGLES_INCLUDE_DIRS ${OPENGLES_INCLUDE_DIR} ${OPENGLES3_INCLUDE_DIR}) + set(OPENGLES_DEFINITIONS -DHAS_GLES=3) + mark_as_advanced(OPENGLES_INCLUDE_DIR OPENGLES3_INCLUDE_DIR OPENGLES_gl_LIBRARY) + else() + set(OPENGLES_INCLUDE_DIRS ${OPENGLES_INCLUDE_DIR}) + set(OPENGLES_DEFINITIONS -DHAS_GLES=2) + mark_as_advanced(OPENGLES_INCLUDE_DIR OPENGLES_gl_LIBRARY) + endif() +endif() diff --git a/FindOpenGLES2.cmake b/FindOpenGLES2.cmake deleted file mode 100644 index e1b7d21..0000000 --- a/FindOpenGLES2.cmake +++ /dev/null @@ -1,36 +0,0 @@ -# - Try to find OpenGLES2 -# Once done this will define -# -# OPENGLES2_FOUND - system has OpenGLES2 -# OPENGLES2_INCLUDE_DIR - the GLES2 include directory -# OPENGLES2_LIBRARIES - Link these to use OpenGLES2 - -find_package(PkgConfig) -if(PKG_CONFIG_FOUND) - pkg_check_modules(OpenGLES2 glesv2) -endif(PKG_CONFIG_FOUND) - -if(NOT OPENGLES2_FOUND) - if("${CORE_SYSTEM_NAME}" STREQUAL "ios") - find_library(OPENGLES2_gl_LIBRARY NAMES OpenGLES PATHS ${CMAKE_OSX_SYSROOT}/System/Library PATH_SUFFIXES Frameworks NO_DEFAULT_PATH) - set(OPENGLES2_INCLUDE_DIR ${OPENGLES2_gl_LIBRARY}/Headers) - set(OPENGLES2_egl_LIBRARY ${OPENGLES2_gl_LIBRARY}) - else() - find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h) - find_library(OPENGLES2_gl_LIBRARY NAMES GLESv2) - find_library(OPENGLES2_egl_LIBRARY NAMES EGL) - endif() - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(OpenGLES2 DEFAULT_MSG - OPENGLES2_INCLUDE_DIR OPENGLES2_gl_LIBRARY OPENGLES2_egl_LIBRARY) - - set(OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_egl_LIBRARY}) -endif(NOT OPENGLES2_FOUND) - -mark_as_advanced( - OPENGLES2_INCLUDE_DIR - OPENGLES2_LIBRARIES - OPENGLES2_gl_LIBRARY - OPENGLES2_egl_LIBRARY -) diff --git a/FindOpenGl.cmake b/FindOpenGl.cmake new file mode 100644 index 0000000..ccde5e5 --- /dev/null +++ b/FindOpenGl.cmake @@ -0,0 +1,41 @@ +#.rst: +# FindOpenGl +# ---------- +# Finds the FindOpenGl library +# +# This will define the following variables:: +# +# OPENGL_FOUND - system has OpenGl +# OPENGL_INCLUDE_DIRS - the OpenGl include directory +# OPENGL_LIBRARIES - the OpenGl libraries +# OPENGL_DEFINITIONS - the OpenGl definitions + +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_OPENGL gl QUIET) +endif() + +if(NOT CORE_SYSTEM_NAME STREQUAL osx) + find_path(OPENGL_INCLUDE_DIR GL/gl.h + PATHS ${PC_OPENGL_gl_INCLUDEDIR}) + find_library(OPENGL_gl_LIBRARY NAMES GL + PATHS ${PC_OPENGL_gl_LIBDIR}) +else() + find_library(OPENGL_gl_LIBRARY NAMES OpenGL + PATHS ${CMAKE_OSX_SYSROOT}/System/Library + PATH_SUFFIXES Frameworks + NO_DEFAULT_PATH) + set(OPENGL_INCLUDE_DIR ${OPENGL_gl_LIBRARY}/Headers) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OpenGl + REQUIRED_VARS OPENGL_gl_LIBRARY OPENGL_INCLUDE_DIR) + +if(OPENGL_FOUND) + set(OPENGL_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR}) + set(OPENGL_LIBRARIES ${OPENGL_gl_LIBRARY}) + set(OPENGL_DEFINITIONS -DHAS_GL=1) +endif() + +mark_as_advanced(OPENGL_INCLUDE_DIR OPENGL_gl_LIBRARY) + diff --git a/depends/common/glm/flags.txt b/depends/common/glm/flags.txt new file mode 100644 index 0000000..fb3a5c7 --- /dev/null +++ b/depends/common/glm/flags.txt @@ -0,0 +1 @@ +-DGLM_TEST_ENABLE_CXX_11=1 -DGLM_TEST_ENABLE=0 -DGLM_TEST_ENABLE_SIMD_SSE2=0 -DCMAKE_INSTALL_LIBDIR=lib diff --git a/depends/common/glm/glm.sha256 b/depends/common/glm/glm.sha256 new file mode 100644 index 0000000..a2281e4 --- /dev/null +++ b/depends/common/glm/glm.sha256 @@ -0,0 +1 @@ +7f093f11c49877716bab96813c2e834db6839095281c8c0c65c60c8bdb9504a3 diff --git a/depends/common/glm/glm.txt b/depends/common/glm/glm.txt new file mode 100644 index 0000000..eeb544e --- /dev/null +++ b/depends/common/glm/glm.txt @@ -0,0 +1 @@ +glm https://github.com/g-truc/glm/archive/47031aa4b7b079716e4cac496819e7f464b6a713.tar.gz diff --git a/depends/osx/glm/flags.txt b/depends/osx/glm/flags.txt new file mode 100644 index 0000000..bd18bd7 --- /dev/null +++ b/depends/osx/glm/flags.txt @@ -0,0 +1 @@ +-DGLM_TEST_ENABLE_CXX_11=1 -DGLM_TEST_ENABLE=0 -DGLM_TEST_ENABLE_SIMD_SSE2=1 -DCMAKE_INSTALL_LIBDIR=lib diff --git a/depends/osx/glm/glm.sha256 b/depends/osx/glm/glm.sha256 new file mode 100644 index 0000000..a2281e4 --- /dev/null +++ b/depends/osx/glm/glm.sha256 @@ -0,0 +1 @@ +7f093f11c49877716bab96813c2e834db6839095281c8c0c65c60c8bdb9504a3 diff --git a/depends/osx/glm/glm.txt b/depends/osx/glm/glm.txt new file mode 100644 index 0000000..eeb544e --- /dev/null +++ b/depends/osx/glm/glm.txt @@ -0,0 +1 @@ +glm https://github.com/g-truc/glm/archive/47031aa4b7b079716e4cac496819e7f464b6a713.tar.gz diff --git a/lib/kissfft/CMakeLists.txt b/lib/kissfft/CMakeLists.txt index 79e95b4..a34639c 100644 --- a/lib/kissfft/CMakeLists.txt +++ b/lib/kissfft/CMakeLists.txt @@ -1,13 +1,7 @@ +cmake_minimum_required(VERSION 3.5) project(kissfft) -enable_language(C) - -cmake_minimum_required(VERSION 2.6) - set(SOURCES kiss_fft.c) -if(NOT WIN32) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") -endif() - add_library(kissfft STATIC ${SOURCES}) +set_property(TARGET kissfft PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/lib/kodi/gui/gl/GL.h b/lib/kodi/gui/gl/GL.h new file mode 100644 index 0000000..943c7d0 --- /dev/null +++ b/lib/kodi/gui/gl/GL.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2005-2019 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +//============================================================================== +/// +/// \defgroup cpp_kodi_gui_gl OpenGL helpers +/// \ingroup cpp_kodi_gui +/// \brief Auxiliary functions for Open GL +/// +/// This group includes help for definitions, functions, and classes for +/// OpenGL. +/// +/// To use OpenGL for your system, add the \ref GL.h "#include ". +/// +/// +///----------------------------------------------------------------------------- +/// +/// The \ref HAS_GL is declared if Open GL is required and \ref HAS_GLES if Open GL +/// Embedded Systems (ES) is required, with ES the version is additionally given +/// in the definition, this can be "2" or "3". +/// +/// +///----------------------------------------------------------------------------- +/// +/// Following \ref GL_TYPE_STRING define can be used, for example, to manage +/// different folders for GL and GLES and make the selection easier. +/// This are on OpenGL "GL" and on Open GL|ES "GLES". +/// +/// **Example:** +/// ~~~~~~~~~~~~~~~~~{.cpp} +/// kodi::GetAddonPath("resources/shaders/" GL_TYPE_STRING "/frag.glsl"); +/// ~~~~~~~~~~~~~~~~~ +/// +/// +///---------------------------------------------------------------------------- +/// +/// In addition, \ref BUFFER_OFFSET is declared in it which can be used to give an +/// offset on the array to GL. +/// +/// **Example:** +/// ~~~~~~~~~~~~~~~~~{.cpp} +/// const struct PackedVertex { +/// float position[3]; // Position x, y, z +/// float color[4]; // Color r, g, b, a +/// } vertices[3] = { +/// { { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, +/// { { 0.5f, -0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, +/// { { 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } +/// }; +/// +/// glVertexAttribPointer(m_aPosition, 3, GL_FLOAT, GL_FALSE, sizeof(PackedVertex), BUFFER_OFFSET(offsetof(PackedVertex, position))); +/// glEnableVertexAttribArray(m_aPosition); +/// +/// glVertexAttribPointer(m_aColor, 4, GL_FLOAT, GL_FALSE, sizeof(PackedVertex), BUFFER_OFFSET(offsetof(PackedVertex, color))); +/// glEnableVertexAttribArray(m_aColor); +/// ~~~~~~~~~~~~~~~~~ + +#if HAS_GL + #define GL_TYPE_STRING "GL" + // always define GL_GLEXT_PROTOTYPES before include gl headers + #if !defined(GL_GLEXT_PROTOTYPES) + #define GL_GLEXT_PROTOTYPES + #endif + #if defined(TARGET_LINUX) + #include + #include + #elif defined(TARGET_FREEBSD) + #include + #elif defined(TARGET_DARWIN) + #include + #include + #elif defined(WIN32) + #error Use of GL under Windows is not possible + #endif +#elif HAS_GLES >= 2 + #define GL_TYPE_STRING "GLES" + #if defined(WIN32) + #if defined(HAS_ANGLE) + #include + #else + #error Use of GLES only be available under Windows by the use of angle + #endif + #elif defined(TARGET_DARWIN) + #if HAS_GLES == 3 + #include + #include + #else + #include + #include + #endif + #else + #if HAS_GLES == 3 + #include + #include + #else + #include + #include + #endif + #endif +#endif + +#ifndef BUFFER_OFFSET +#define BUFFER_OFFSET(i) ((char *)nullptr + (i)) +#endif diff --git a/lib/kodi/gui/gl/Shader.h b/lib/kodi/gui/gl/Shader.h new file mode 100644 index 0000000..209f274 --- /dev/null +++ b/lib/kodi/gui/gl/Shader.h @@ -0,0 +1,594 @@ +/* + * Copyright (C) 2005-2019 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "GL.h" + +#include +#include +#include + +#include +#include + +#define LOG_SIZE 1024 +#define GLchar char + +namespace kodi +{ +namespace gui +{ +namespace gl +{ + +//======================================================================== +/// CShader - base class +class ATTRIBUTE_HIDDEN CShader +{ +public: + CShader() = default; + virtual ~CShader() = default; + virtual bool Compile(const std::string& extraBegin = "", + const std::string& extraEnd = "") = 0; + virtual void Free() = 0; + virtual GLuint Handle() = 0; + + bool LoadSource(const std::string& file) + { + char buffer[16384]; + + kodi::vfs::CFile source; + if (!source.OpenFile(file)) + { + kodi::Log(ADDON_LOG_ERROR, "CShader::%s: Failed to open file '%s'", __FUNCTION__, file.c_str()); + return false; + } + size_t len = source.Read(buffer, sizeof(buffer)); + m_source.assign(buffer); + m_source[len] = 0; + source.Close(); + return true; + } + + bool OK() const { return m_compiled; } + +protected: + std::string m_source; + std::string m_lastLog; + bool m_compiled = false; +}; +//------------------------------------------------------------------------ + +//======================================================================== +/// CVertexShader +class ATTRIBUTE_HIDDEN CVertexShader : public CShader +{ +public: + CVertexShader() = default; + ~CVertexShader() override { Free(); } + + void Free() override + { + if (m_vertexShader) + glDeleteShader(m_vertexShader); + m_vertexShader = 0; + } + + bool Compile(const std::string& extraBegin = "", + const std::string& extraEnd = "") override + { + GLint params[4]; + + Free(); + + m_vertexShader = glCreateShader(GL_VERTEX_SHADER); + + GLsizei count = 0; + const char *sources[3]; + if (!extraBegin.empty()) + sources[count++] = extraBegin.c_str(); + if (!m_source.empty()) + sources[count++] = m_source.c_str(); + if (!extraEnd.empty()) + sources[count++] = extraEnd.c_str(); + + glShaderSource(m_vertexShader, count, sources, nullptr); + glCompileShader(m_vertexShader); + glGetShaderiv(m_vertexShader, GL_COMPILE_STATUS, params); + if (params[0] != GL_TRUE) + { + GLchar log[LOG_SIZE]; + glGetShaderInfoLog(m_vertexShader, LOG_SIZE, nullptr, log); + kodi::Log(ADDON_LOG_ERROR, "CVertexShader::%s: %s", __FUNCTION__, log); + fprintf(stderr, "CVertexShader::%s: %s\n", __FUNCTION__, log); + m_lastLog = log; + m_compiled = false; + } + else + { + GLchar log[LOG_SIZE]; + glGetShaderInfoLog(m_vertexShader, LOG_SIZE, nullptr, log); + m_lastLog = log; + m_compiled = true; + } + return m_compiled; + } + + GLuint Handle() override { return m_vertexShader; } + +protected: + GLuint m_vertexShader = 0; +}; +//------------------------------------------------------------------------ + +//======================================================================== +/// CPixelShader +class ATTRIBUTE_HIDDEN CPixelShader : public CShader +{ +public: + CPixelShader() = default; + ~CPixelShader() { Free(); } + void Free() override + { + if (m_pixelShader) + glDeleteShader(m_pixelShader); + m_pixelShader = 0; + } + + bool Compile(const std::string& extraBegin = "", + const std::string& extraEnd = "") override + { + GLint params[4]; + + Free(); + + m_pixelShader = glCreateShader(GL_FRAGMENT_SHADER); + + GLsizei count = 0; + const char *sources[3]; + if (!extraBegin.empty()) + sources[count++] = extraBegin.c_str(); + if (!m_source.empty()) + sources[count++] = m_source.c_str(); + if (!extraEnd.empty()) + sources[count++] = extraEnd.c_str(); + + glShaderSource(m_pixelShader, count, sources, 0); + glCompileShader(m_pixelShader); + glGetShaderiv(m_pixelShader, GL_COMPILE_STATUS, params); + if (params[0] != GL_TRUE) + { + GLchar log[LOG_SIZE]; + glGetShaderInfoLog(m_pixelShader, LOG_SIZE, nullptr, log); + kodi::Log(ADDON_LOG_ERROR, "CPixelShader::%s: %s", __FUNCTION__, log); + fprintf(stderr, "CPixelShader::%s: %s\n", __FUNCTION__, log); + m_lastLog = log; + m_compiled = false; + } + else + { + GLchar log[LOG_SIZE]; + glGetShaderInfoLog(m_pixelShader, LOG_SIZE, nullptr, log); + m_lastLog = log; + m_compiled = true; + } + return m_compiled; + } + + GLuint Handle() override { return m_pixelShader; } + +protected: + GLuint m_pixelShader = 0; +}; +//------------------------------------------------------------------------ + +//============================================================================ +/// +/// \defgroup cpp_kodi_gui_gl_CShaderProgram GL Shader Program +/// \ingroup cpp_kodi_gui_gl +/// @brief \cpp_class{ kodi::gui::gl::CShaderProgram } +/// **Class to manage an OpenGL shader program** +/// +/// With this class the used GL shader code can be defined on the GPU and +/// its variables can be managed between CPU and GPU. +/// +/// It has the header \ref Shader.h "#include " +/// be included to enjoy it. +/// +/// ---------------------------------------------------------------------------- +/// +/// Example: +/// +/// ~~~~~~~~~~~~~{.cpp} +/// +/// #include +/// ... +/// +/// class ATTRIBUTE_HIDDEN CExample +/// : ..., +/// public kodi::gui::gl::CShaderProgram +/// { +/// public: +/// CExample() = default; +/// +/// bool Start(); +/// void Render(); +/// +/// // override functions for kodi::gui::gl::CShaderProgram +/// void OnCompiledAndLinked() override; +/// bool OnEnabled() override; +/// +/// private: +/// ... +/// GLint m_aPosition = -1; +/// GLint m_aColor = -1; +/// }; +/// +/// bool CExample::Start() +/// { +/// // Define shaders and load +/// std::string fraqShader = kodi::GetAddonPath("resources/shaders/" GL_TYPE_STRING "/glsl.frag"); +/// std::string vertShader = kodi::GetAddonPath("resources/shaders/" GL_TYPE_STRING "/glsl.vert"); +/// if (!LoadShaderFiles(vertShader, fraqShader) || !CompileAndLink()) +/// return false; +/// +/// ... +/// return true; +/// } +/// +/// ... +/// +/// void CExample::Render() +/// { +/// ... +/// +/// EnableShader(); +/// ... +/// DO WORK +/// ... +/// DisableShader(); +/// } +/// +/// void CExample::OnCompiledAndLinked() +/// { +/// ... +/// DO YOUR WORK HERE FOR WHAT IS ONE TIME REQUIRED DURING COMPILE OF SHADER, E.G.: +/// +/// m_aPosition = glGetAttribLocation(ProgramHandle(), "a_position"); +/// m_aColor = glGetAttribLocation(ProgramHandle(), "a_color"); +/// } +/// +/// bool OnEnabled() override +/// { +/// ... +/// DO YOUR WORK HERE FOR WHAT REQUIRED DURING ENABLE OF SHADER +/// ... +/// return true; +/// } +/// +/// ADDONCREATOR(CExample); +/// ~~~~~~~~~~~~~ +/// + +//======================================================================== +/// CShaderProgram +class ATTRIBUTE_HIDDEN CShaderProgram +{ +public: + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief Construct a new shader + /// + /// Load must be done later with \ref LoadShaderFiles. + /// + CShaderProgram() = default; + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief Construct a new shader and load defined shader files + /// + /// @param[in] vert Path to used GL vertext shader + /// @param[in] frag Path to used GL fragment shader + /// + CShaderProgram(const std::string& vert, const std::string& frag) + { + LoadShaderFiles(vert, frag); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief Destructor + /// + virtual ~CShaderProgram() + { + ShaderFree(); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief To load manually the needed shader files + /// + /// @param[in] vert Path to used GL vertext shader + /// @param[in] frag Path to used GL fragment shader + /// + /// + /// @note The use of the files is optional, but it must either be passed over + /// here or via \ref CompileAndLink, or both of the source code. + /// + bool LoadShaderFiles(const std::string& vert, const std::string& frag) + { + if (!kodi::vfs::FileExists(vert) || !m_pVP.LoadSource(vert)) + { + kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load '%s'", __func__, vert.c_str()); + return false; + } + + if (!kodi::vfs::FileExists(frag) || !m_pFP.LoadSource(frag)) + { + kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load '%s'", __func__, frag.c_str()); + return false; + } + + return true; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief To compile and link the shader to the GL interface + /// + /// Optionally, additional source code can be transferred here, or it can be + /// used independently without any files + /// + /// @param[in] vertexExtraBegin [opt] To additionally add vextex source + /// code to the beginning of the loaded file + /// source code + /// @param[in] vertexExtraEnd [opt] To additionally add vextex source + /// code to the end of the loaded file + /// source code + /// @param[in] fragmentExtraBegin [opt] To additionally add fragment source + /// code to the beginning of the loaded file + /// source code + /// @param[in] fragmentExtraEnd [opt] To additionally add fragment source + /// code to the end of the loaded file + /// source code + /// @return true if compile was successed + /// + /// + /// @note In the case of a compile error, it will be written once into the Kodi + /// log and in addition to the console output to quickly detect the errors when + /// writing the damage. + /// + /// + bool CompileAndLink(const std::string& vertexExtraBegin = "", + const std::string& vertexExtraEnd = "", + const std::string& fragmentExtraBegin = "", + const std::string& fragmentExtraEnd = "") + { + GLint params[4]; + + // free resources + ShaderFree(); + m_ok = false; + + // compiled vertex shader + if (!m_pVP.Compile(vertexExtraBegin, vertexExtraEnd)) + { + kodi::Log(ADDON_LOG_ERROR, "GL: Error compiling vertex shader"); + return false; + } + + // compile pixel shader + if (!m_pFP.Compile(fragmentExtraBegin, fragmentExtraEnd)) + { + m_pVP.Free(); + kodi::Log(ADDON_LOG_ERROR, "GL: Error compiling fragment shader"); + return false; + } + + // create program object + m_shaderProgram = glCreateProgram(); + if (!m_shaderProgram) + { + kodi::Log(ADDON_LOG_ERROR, "CShaderProgram::%s: Failed to create GL program", __FUNCTION__); + ShaderFree(); + return false; + } + + // attach the vertex shader + glAttachShader(m_shaderProgram, m_pVP.Handle()); + glAttachShader(m_shaderProgram, m_pFP.Handle()); + + // link the program + glLinkProgram(m_shaderProgram); + glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, params); + if (params[0] != GL_TRUE) + { + GLchar log[LOG_SIZE]; + glGetProgramInfoLog(m_shaderProgram, LOG_SIZE, nullptr, log); + kodi::Log(ADDON_LOG_ERROR, "CShaderProgram::%s: %s", __FUNCTION__, log); + fprintf(stderr, "CShaderProgram::%s: %s\n", __FUNCTION__, log); + ShaderFree(); + return false; + } + + m_validated = false; + m_ok = true; + OnCompiledAndLinked(); + return true; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief To activate the shader and use it on the GPU + /// + /// @return true if enable was successfull done + /// + /// + /// @note During this call, the \ref OnEnabled stored in the child is also + /// called + /// + bool EnableShader() + { + if (ShaderOK()) + { + glUseProgram(m_shaderProgram); + if (OnEnabled()) + { + if (!m_validated) + { + // validate the program + GLint params[4]; + glValidateProgram(m_shaderProgram); + glGetProgramiv(m_shaderProgram, GL_VALIDATE_STATUS, params); + if (params[0] != GL_TRUE) + { + GLchar log[LOG_SIZE]; + glGetProgramInfoLog(m_shaderProgram, LOG_SIZE, nullptr, log); + kodi::Log(ADDON_LOG_ERROR, "CShaderProgram::%s: %s", __FUNCTION__, log); + fprintf(stderr, "CShaderProgram::%s: %s\n", __FUNCTION__, log); + } + m_validated = true; + } + return true; + } + else + { + glUseProgram(0); + return false; + } + return true; + } + return false; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief To deactivate the shader use on the GPU + /// + void DisableShader() + { + if (ShaderOK()) + { + glUseProgram(0); + OnDisabled(); + } + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief Used to check if shader has been loaded before. + /// + /// @return true if enable was successfull done + /// + /// @note The CompileAndLink call sets these values + /// + ATTRIBUTE_FORCEINLINE bool ShaderOK() const { return m_ok; } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief To get the vertex shader class used by Kodi at the addon + /// + /// @return pointer to vertex shader class + /// + ATTRIBUTE_FORCEINLINE CVertexShader& VertexShader() { return m_pVP; } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief To get the fragment shader class used by Kodi at the addon + /// + /// @return pointer to fragment shader class + /// + ATTRIBUTE_FORCEINLINE CPixelShader& PixelShader() { return m_pFP; } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief Used to get the definition created in the OpenGL itself + /// + /// @return GLuint of GL shader program handler + /// + ATTRIBUTE_FORCEINLINE GLuint ProgramHandle() { return m_shaderProgram; } + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \defgroup cpp_kodi_gui_gl_CShaderProgram_child Child Functions + /// \ingroup cpp_kodi_gui_gl_CShaderProgram + /// @brief \cpp_class{ kodi::gui::gl::CShaderProgram child functions } + /// + /// Functions that are added by parent in the child + //@{ + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram_child + /// @brief Mandatory child function to set the necessary CPU to GPU data + /// + virtual void OnCompiledAndLinked() {}; + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram_child + /// @brief Optional function to exchange data between CPU and GPU while + /// activating the shader + /// + /// @return true if enable was successfull done + /// + virtual bool OnEnabled() { return true; }; + //-------------------------------------------------------------------------- + + //========================================================================== + /// + /// \ingroup cpp_kodi_gui_gl_CShaderProgram_child + /// @brief Optional child function that may have to be performed when + /// switching off the shader + virtual void OnDisabled() {}; + //-------------------------------------------------------------------------- + //@} + +private: + void ShaderFree() + { + if (m_shaderProgram) + glDeleteProgram(m_shaderProgram); + m_shaderProgram = 0; + m_ok = false; + } + + CVertexShader m_pVP; + CPixelShader m_pFP; + GLuint m_shaderProgram = 0; + bool m_ok = false; + bool m_validated = false; +}; +//------------------------------------------------------------------------ + +} /* namespace gl */ +} /* namespace gui */ +} /* namespace kodi */ diff --git a/src/main.cpp b/src/main.cpp index 2187652..9689904 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ /* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org + * Copyright (C) 2005-2019 Team Kodi + * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,114 +13,68 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see + * along with Kodi; see the file COPYING. If not, see * . * */ -#include -#if defined(HAS_GLES) -#include -#include -#include -#include -#define TO_STRING(...) #__VA_ARGS__ -#else -#define GL_GLEXT_PROTOTYPES -#ifdef __APPLE__ -#include -#include -#else -#include -#include -#endif -#endif -#include +#include "main.h" +#include "lodepng.h" + +#define _USE_MATH_DEFINES #include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include - -#include "kiss_fft.h" -#include "lodepng.h" -using namespace std; +#define SMOOTHING_TIME_CONSTANT (0.8) +#define MIN_DECIBELS (-100.0) +#define MAX_DECIBELS (-30.0) -string g_pathPresets; +#define AUDIO_BUFFER (1024) +#define NUM_BANDS (AUDIO_BUFFER / 2) -struct Preset { +struct Preset +{ std::string name; std::string file; int channel[4]; }; -#if defined(HAS_GLES) const std::vector g_presets = - { +{ {"2D LED Spectrum by un1versal", "2Dspectrum.frag.glsl", 99, -1, -1, -1}, - {"Input Sound by iq", "input.frag.glsl", 99, -1, -1, -1}, - {"LED spectrum by simesgreen", "ledspectrum.frag.glsl", 99, -1, -1, -1}, {"Audio Eclipse by airtight", "audioeclipse.frag.glsl", 99, -1, -1, -1}, {"Audio Reaktive by choard1895", "audioreaktive.frag.glsl", 99, -1, -1, -1}, {"AudioVisual by Passion", "audiovisual.frag.glsl", 99, -1, -1, -1}, {"Beating Circles by Phoenix72", "beatingcircles.frag.glsl", 99, -1, -1, -1}, {"BPM by iq", "bpm.frag.glsl", 99, -1, -1, -1}, - {"Dancing Metalights by Danguafare", "dancingmetalights.frag.glsl", 99, -1, -1, -1}, - {"The Disco Tunnel by poljere", "discotunnel.frag.glsl", 2, 13, 99, -1}, - {"Gameboy by iq", "gameboy.frag.glsl", 99, -1, -1, -1}, - {"Electric pulse by un1versal", "electricpulse.frag.glsl", 99, -1, -1, -1}, - {"Polar Beats by sauj123", "polarbeats.frag.glsl", 99, -1, -1, -1}, - {"Simplicity Galaxy by CBS", "simplicitygalaxy.frag.glsl", 99, -1, -1, -1}, - {"Sound Flower by iq", "soundflower.frag.glsl", 99, -1, -1, -1}, - {"Sound sinus wave by Eitraz", "soundsinuswave.frag.glsl", 99, -1, -1, -1}, - {"Spectrometer by jaba", "spectrometer.frag.glsl", 99, -1, -1, -1}, - {"symmetrical sound visualiser by thelinked","symmetricalsound.frag.glsl", 99, -1, -1, -1}, - {"Twisted Rings by poljere", "twistedrings.frag.glsl", 99, -1, -1, -1}, - {"Undulant Spectre by mafik", "undulantspectre.frag.glsl", 99, -1, -1, -1}, - {"Waves Remix by ADOB", "wavesremix.frag.glsl", 99, -1, -1, -1}, - {"Circle Wave by TekF", "circlewave.frag.glsl", 99, -1, -1, -1}}; -#else -const std::vector g_presets = - { - {"2D LED Spectrum by un1versal", "2Dspectrum.frag.glsl", 99, -1, -1, -1}, - {"Audio Reaktive by choard1895", "audioreaktive.frag.glsl", 99, -1, -1, -1}, - {"AudioVisual by Passion", "audiovisual.frag.glsl", 99, -1, -1, -1}, - {"Beating Circles by Phoenix72", "beatingcircles.frag.glsl", 99, -1, -1, -1}, - {"BPM by iq", "bpm.frag.glsl", 99, -1, -1, -1}, {"Circle Wave by TekF", "circlewave.frag.glsl", 99, -1, -1, -1}, {"Circuits by Kali", "circuits.frag.glsl", 99, 7, -1, -1}, {"Colored Bars by novalis", "coloredbars.frag.glsl", 99, -1, -1, -1}, {"Cubescape by iq", "cubescape.frag.glsl", 99, 5, -1, -1}, - {"The Disco Tunnel by poljere", "discotunnel.frag.glsl", 99, 2, 14, -1}, + {"Dancing Metalights by Danguafare", "dancingmetalights.frag.glsl", 99, -1, -1, -1}, + {"The Disco Tunnel by poljere", "discotunnel.frag.glsl", 2, 13, 99, -1}, + {"Electric pulse by un1versal", "electricpulse.frag.glsl", 99, -1, -1, -1}, {"Fractal Land by Kali", "fractalland.frag.glsl", 2, 13, 99, -1}, {"Gameboy by iq", "gameboy.frag.glsl", 99, -1, -1, -1}, - {"Electric pulse by un1versal", "electricpulse.frag.glsl", 99, -1, -1, -1}, + {"Input Sound by iq", "input.frag.glsl", 99, -1, -1, -1}, {"I/O by movAX13h", "io.frag.glsl", 99, -1, -1, -1}, {"Kaleidoscope Visualizer by Qqwy", "kaleidoscopevisualizer.frag.glsl", 99, 15, -1, -1}, - {"Nyancat by mu6k", "nyancat.frag.glsl", 99, 13, -1, -1}, + {"LED spectrum by simesgreen", "ledspectrum.frag.glsl", 99, -1, -1, -1}, {"Polar Beats by sauj123", "polarbeats.frag.glsl", 99, -1, -1, -1}, - {"Revision 2015 Livecoding Round 1 by mu6k", "revision2015.frag.glsl", 99, -1, -1, -1}, - {"Ribbons by XT95", "ribbons.frag.glsl", 99, -1, -1, -1}, {"Simplicity Galaxy by CBS", "simplicitygalaxy.frag.glsl", 99, -1, -1, -1}, {"Sound Flower by iq", "soundflower.frag.glsl", 99, -1, -1, -1}, {"Sound sinus wave by Eitraz", "soundsinuswave.frag.glsl", 99, -1, -1, -1}, + {"Spectrometer by jaba", "spectrometer.frag.glsl", 99, -1, -1, -1}, {"symmetrical sound visualiser by thelinked","symmetricalsound.frag.glsl", 99, -1, -1, -1}, {"Twisted Rings by poljere", "twistedrings.frag.glsl", 99, -1, -1, -1}, {"Undulant Spectre by mafik", "undulantspectre.frag.glsl", 99, -1, -1, -1}, {"Demo - Volumetric Lines by iq", "volumetriclines.frag.glsl", 99, -1, -1, -1}, - {"Waves Remix by ADOB", "wavesremix.frag.glsl", 99, -1, -1, -1}}; -#endif - -int g_currentPreset = 0; + {"Waves Remix by ADOB", "wavesremix.frag.glsl", 99, -1, -1, -1} +}; -const char *g_fileTextures[] = { +const std::vector g_fileTextures = +{ "tex00.png", "tex01.png", "tex02.png", @@ -139,518 +93,288 @@ const char *g_fileTextures[] = { "tex14.png", }; -#if defined(HAS_GLES) -struct -{ - GLuint vertex_buffer; - GLuint attr_vertex_e; - GLuint attr_vertex_r, uTexture; - GLuint effect_fb; - GLuint framebuffer_texture; - GLuint render_program; - GLuint uScale; - int fbwidth, fbheight; -} state_g, *state = &state_g; -#endif - -int g_numberTextures = 17; -GLint g_textures[17] = { }; - -void LogProps(AddonProps_Visualization *props) { - cout << "Props = {" << endl - << "\t x: " << props->x << endl - << "\t y: " << props->y << endl - << "\t width: " << props->width << endl - << "\t height: " << props->height << endl - << "\t pixelRatio: " << props->pixelRatio << endl - << "\t name: " << props->name << endl - << "\t presets: " << props->presets << endl - << "\t profile: " << props->profile << endl -// << "\t submodule: " << props->submodule << endl // Causes problems? Is it initialized? - << "}" << endl; -} +#if defined(HAS_GL) -void LogTrack(VisTrack *track) { - cout << "Track = {" << endl - << "\t title: " << track->title << endl - << "\t artist: " << track->artist << endl - << "\t album: " << track->album << endl - << "\t albumArtist: " << track->albumArtist << endl - << "\t genre: " << track->genre << endl - << "\t comment: " << track->comment << endl - << "\t lyrics: " << track->lyrics << endl - << "\t trackNumber: " << track->trackNumber << endl - << "\t discNumber: " << track->discNumber << endl - << "\t duration: " << track->duration << endl - << "\t year: " << track->year << endl - << "\t rating: " << track->rating << endl - << "}" << endl; -} +std::string fsHeader = +R"shader(#version 150 -void LogAction(const char *message) { - cout << "Action " << message << endl; -} +#extension GL_OES_standard_derivatives : enable -void LogActionString(const char *message, const char *param) { - cout << "Action " << message << " " << param << endl; -} +uniform vec3 iResolution; +uniform float iGlobalTime; +uniform float iChannelTime[4]; +uniform vec4 iMouse; +uniform vec4 iDate; +uniform float iSampleRate; +uniform vec3 iChannelResolution[4]; +uniform sampler2D iChannel0; +uniform sampler2D iChannel1; +uniform sampler2D iChannel2; +uniform sampler2D iChannel3; -float blackmanWindow(float in, size_t i, size_t length) { - double alpha = 0.16; - double a0 = 0.5 * (1.0 - alpha); - double a1 = 0.5; - double a2 = 0.5 * alpha; +out vec4 FragColor; - float x = (float)i / (float)length; - return in * (a0 - a1 * cos(2.0 * M_PI * x) + a2 * cos(4.0 * M_PI * x)); -} +#define iTime iGlobalTime -void smoothingOverTime(float *outputBuffer, float *lastOutputBuffer, kiss_fft_cpx *inputBuffer, size_t length, float smoothingTimeConstant, unsigned int fftSize) { - for (size_t i = 0; i < length; i++) { - kiss_fft_cpx c = inputBuffer[i]; - float magnitude = sqrt(c.r * c.r + c.i * c.i) / (float)fftSize; - outputBuffer[i] = smoothingTimeConstant * lastOutputBuffer[i] + (1.0 - smoothingTimeConstant) * magnitude; - } -} +#ifndef texture2D +#define texture2D texture +#endif +)shader"; -float linearToDecibels(float linear) { - if (!linear) - return -1000; - return 20 * log10f(linear); +std::string fsFooter = +R"shader( +void main(void) +{ + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); + mainImage(color, gl_FragCoord.xy); + color.w = 1.0; + FragColor = color; } +)shader"; -#define SMOOTHING_TIME_CONSTANT (0.8) -#define MIN_DECIBELS (-100.0) -#define MAX_DECIBELS (-30.0) - -#define AUDIO_BUFFER (1024) -#define NUM_BANDS (AUDIO_BUFFER / 2) - -GLuint createTexture(GLint format, unsigned int w, unsigned int h, const GLvoid * data) { - GLuint texture = 0; - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +std::string fsHeader = +R"shader(#version 100 + +#extension GL_OES_standard_derivatives : enable + +precision mediump float; +precision mediump int; + +uniform vec3 iResolution; +uniform float iGlobalTime; +uniform float iChannelTime[4]; +uniform vec4 iMouse; +uniform vec4 iDate; +uniform float iSampleRate; +uniform vec3 iChannelResolution[4]; +uniform sampler2D iChannel0; +uniform sampler2D iChannel1; +uniform sampler2D iChannel2; +uniform sampler2D iChannel3; + +#define iTime iGlobalTime +#ifndef texture +#define texture texture2D +#endif +)shader"; - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, data); - return texture; +std::string fsFooter = +R"shader( +void main(void) +{ + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); + mainImage(color, gl_FragCoord.xy); + color.w = 1.0; + gl_FragColor = color; } +)shader"; -GLuint createTexture(const GLvoid *data, GLint format, unsigned int w, unsigned int h, GLint internalFormat, GLint scaling, GLint repeat) { - GLuint texture = 0; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, scaling); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, scaling); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeat); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeat); - -#if defined(HAS_GLES) - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, data); -#else - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, data); #endif - glBindTexture(GL_TEXTURE_2D, 0); - return texture; +CVisualizationShadertoy::CVisualizationShadertoy() + : m_kissCfg(kiss_fft_alloc(AUDIO_BUFFER, 0, nullptr, nullptr)), + m_audioData(new GLubyte[AUDIO_BUFFER]()), + m_magnitudeBuffer(new float[NUM_BANDS]()), + m_pcm(new float[AUDIO_BUFFER]()) +{ + m_currentPreset = kodi::GetSettingInt("lastpresetidx"); } -GLuint createTexture(const char *file, GLint internalFormat, GLint scaling, GLint repeat) { - std::ostringstream ss; - ss << g_pathPresets << "/resources/" << file; - std::string fullPath = ss.str(); - - cout << "creating texture " << fullPath << endl; - - - unsigned error; - unsigned char* image; - unsigned width, height; - - error = lodepng_decode32_file(&image, &width, &height, fullPath.c_str()); - if (error) { - printf("error %u: %s\n", error, lodepng_error_text(error)); - return 0; - } - - GLuint texture = createTexture(image, GL_RGBA, width, height, internalFormat, scaling, repeat); - free(image); - return texture; +CVisualizationShadertoy::~CVisualizationShadertoy() +{ + delete [] m_audioData; + delete [] m_magnitudeBuffer; + delete [] m_pcm; + free(m_kissCfg); } -GLuint compileShader(GLenum shaderType, const char *shader) { - GLuint s = glCreateShader(shaderType); - if (s == 0) { - cerr << "Failed to create shader from\n====" << endl; - cerr << shader << endl; - cerr << "===" << endl; - - return 0; +//-- Render ------------------------------------------------------------------- +// Called once per frame. Do all rendering here. +//----------------------------------------------------------------------------- +void CVisualizationShadertoy::Render() +{ + if (m_initialized) + { + if (m_state.fbwidth && m_state.fbheight) + { + RenderTo(m_shadertoyShader.ProgramHandle(), m_state.effect_fb); + RenderTo(m_displayShader.ProgramHandle(), 0); + } + else + { + RenderTo(m_shadertoyShader.ProgramHandle(), 0); + } } +} - glShaderSource(s, 1, &shader, NULL); - glCompileShader(s); - - GLint param; - glGetShaderiv(s, GL_COMPILE_STATUS, ¶m); - if (param != GL_TRUE) { - cerr << "Failed to compile shader source\n====" << endl; - cerr << shader << endl; - cerr << "===" << endl; - - int infologLength = 0; - char *infoLog; - - glGetShaderiv(s, GL_INFO_LOG_LENGTH, &infologLength); +bool CVisualizationShadertoy::Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, std::string szSongName) +{ +#ifdef DEBUG_PRINT + printf("Start %i %i %i %s\n", iChannels, iSamplesPerSec, iBitsPerSample, szSongName.c_str()); +#endif - if (infologLength > 0) { - infoLog = new char[infologLength]; - glGetShaderInfoLog(s, infologLength, NULL, infoLog); - cout << "" << endl << infoLog << endl << "" << endl; - delete [] infoLog; - } + static const GLfloat vertex_data[] = + { + -1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0,-1.0, 1.0, 1.0, + -1.0,-1.0, 1.0, 1.0, + }; - glDeleteShader(s); + // Upload vertex data to a buffer + glGenBuffers(1, &m_state.vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, m_state.vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - return 0; - } + m_samplesPerSec = iSamplesPerSec; + Launch(m_currentPreset); + m_initialized = true; - return s; + return true; } -GLuint compileAndLinkProgram(const char *vertexShader, const char *fragmentShader) { - cout << "CompileAndLink " << endl; - GLuint program = glCreateProgram(); - if (program == 0) { - cerr << "Failed to create program" << endl; - return 0; - } - - GLuint vs = compileShader(GL_VERTEX_SHADER, vertexShader); - GLuint fs = compileShader(GL_FRAGMENT_SHADER, fragmentShader); - - if (vs && fs) { - glAttachShader(program, vs); - glAttachShader(program, fs); - glLinkProgram(program); - - GLint param; - glGetProgramiv(program, GL_LINK_STATUS, ¶m); - if (param != GL_TRUE) { - cerr << "Failed to link shader program " << endl; - glGetError(); - int infologLength = 0; - char *infoLog; - - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); - - if (infologLength > 0) { - infoLog = new char[infologLength]; - glGetProgramInfoLog(program, infologLength, NULL, infoLog); - cout << "" << endl << infoLog << endl << "" << endl; - delete [] infoLog; - } +void CVisualizationShadertoy::Stop() +{ + m_initialized = false; +#ifdef DEBUG_PRINT + printf("Stop\n"); +#endif - GLchar errorLog[1024] = {0}; - glGetProgramInfoLog(program, 1024, NULL, errorLog); + UnloadPreset(); + UnloadTextures(); - cout << "" << endl << vertexShader << endl << "" << endl; - cout << "" << endl << fragmentShader << endl << "" << endl; + glDeleteBuffers(1, &m_state.vertex_buffer); +} - glDetachShader(program, vs); - glDeleteShader(vs); - glDetachShader(program, fs); - glDeleteShader(fs); +void CVisualizationShadertoy::AudioData(const float* pAudioData, int iAudioDataLength, float* pFreqData, int iFreqDataLength) +{ + WriteToBuffer(pAudioData, iAudioDataLength, 2); - glDeleteProgram(program); - return 0; - } - } else { - glDeleteProgram(program); + kiss_fft_cpx in[AUDIO_BUFFER], out[AUDIO_BUFFER]; + for (unsigned int i = 0; i < AUDIO_BUFFER; i++) + { + in[i].r = BlackmanWindow(m_pcm[i], i, AUDIO_BUFFER); + in[i].i = 0; } - glUseProgram(0); - - if (vs) - glDeleteShader(vs); + kiss_fft(m_kissCfg, in, out); - if (fs) - glDeleteShader(fs); - - return program; -} + out[0].i = 0; + SmoothingOverTime(m_magnitudeBuffer, m_magnitudeBuffer, out, NUM_BANDS, SMOOTHING_TIME_CONSTANT, AUDIO_BUFFER); -#if defined(HAS_GLES) - -std::string vsSource = TO_STRING( - precision mediump float; - precision mediump int; - attribute vec4 vertex; - varying vec2 vTextureCoord; - uniform vec2 uScale; - void main(void) - { - gl_Position = vertex; - vTextureCoord = vertex.xy*0.5+0.5; - vTextureCoord.x = vTextureCoord.x * uScale.x; - vTextureCoord.y = vTextureCoord.y * uScale.y; - } - ); - -std::string render_vsSource = TO_STRING( - precision mediump float; - precision mediump int; - attribute vec4 vertex; - varying vec2 vTextureCoord; - void main(void) - { - gl_Position = vertex; - vTextureCoord = vertex.xy*0.5+0.5; - } - ); - -std::string render_fsSource = TO_STRING( - precision mediump float; - precision mediump int; - varying vec2 vTextureCoord; - uniform sampler2D uTexture; - void main(void) - { - gl_FragColor = texture2D(uTexture, vTextureCoord); - } - ); -#else -std::string vsSource = "void main() { gl_Position = ftransform(); }"; -#endif - -std::string fsHeader = -"#extension GL_OES_standard_derivatives : enable\n" -#ifdef HAS_GLES -"precision mediump float;\n" -"precision mediump int;\n" -#endif -"uniform vec3 iResolution;\n" -"uniform float iGlobalTime;\n" -"uniform float iChannelTime[4];\n" -"uniform vec4 iMouse;\n" -"uniform vec4 iDate;\n" -"uniform float iSampleRate;\n" -"uniform vec3 iChannelResolution[4];\n" -"uniform sampler2D iChannel0;\n" -"uniform sampler2D iChannel1;\n" -"uniform sampler2D iChannel2;\n" -"uniform sampler2D iChannel3;\n"; + const double rangeScaleFactor = MAX_DECIBELS == MIN_DECIBELS ? 1 : (1.0 / (MAX_DECIBELS - MIN_DECIBELS)); + for (unsigned int i = 0; i < NUM_BANDS; i++) + { + float linearValue = m_magnitudeBuffer[i]; + double dbMag = !linearValue ? MIN_DECIBELS : LinearToDecibels(linearValue); + double scaledValue = UCHAR_MAX * (dbMag - MIN_DECIBELS) * rangeScaleFactor; -std::string fsFooter = -"void main(void)\n" -"{\n" -" vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n" -" mainImage(color, gl_FragCoord.xy);\n" -" color.w = 1.0;\n" -" gl_FragColor = color;\n" -"}\n"; - -bool initialized = false; - -GLuint shadertoy_shader = 0; - -GLint iResolutionLoc = 0; -GLint iGlobalTimeLoc = 0; -GLint iChannelTimeLoc = 0; -GLint iMouseLoc = 0; -GLint iDateLoc = 0; -GLint iSampleRateLoc = 0; -GLint iChannelResolutionLoc = 0; -GLint iChannelLoc[4]; -GLuint iChannel[4]; - -int width = 0; -int height = 0; - -int64_t initial_time; -int bits_precision = 0; - -bool needsUpload = true; - -kiss_fft_cfg cfg; - -float *pcm = NULL; -float *magnitude_buffer = NULL; -GLubyte *audio_data = NULL; -int samplesPerSec = 0; - -void unloadTextures() { - for (int i=0; i<4; i++) { - if (iChannel[i]) { - cout << "Unloading iChannel" << i << " " << iChannel[i] << endl; - glDeleteTextures(1, &iChannel[i]); - iChannel[i] = 0; - } + m_audioData[i] = std::max(std::min((int)scaledValue, UCHAR_MAX), 0); } -} -void unloadPreset() { - if (shadertoy_shader) { - glDeleteProgram(shadertoy_shader); - shadertoy_shader = 0; - } -#if defined(HAS_GLES) - if (state->framebuffer_texture) - { - glDeleteTextures(1, &state->framebuffer_texture); - state->framebuffer_texture = 0; - } - if (state->effect_fb) + for (unsigned int i = 0; i < NUM_BANDS; i++) { - glDeleteFramebuffers(1, &state->effect_fb); - state->effect_fb = 0; - } - if (state->render_program) { - glDeleteProgram(state->render_program); - state->render_program = 0; + float v = (m_pcm[i] + 1.0f) * 128.0f; + m_audioData[i + NUM_BANDS] = std::max(std::min((int)v, UCHAR_MAX), 0); } -#endif + + m_needsUpload = true; } -std::string createShader(const std::string &file) +//-- OnAction ----------------------------------------------------------------- +// Handle Kodi actions such as next preset, lock preset, album art changed etc +//----------------------------------------------------------------------------- +bool CVisualizationShadertoy::NextPreset() { - std::ostringstream ss; - ss << g_pathPresets << "/resources/" << file; - std::string fullPath = ss.str(); - - cout << "Creating shader from " << fullPath << endl; - - std::ifstream t(fullPath); - std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); + m_currentPreset = (m_currentPreset + 1) % g_presets.size(); + Launch(m_currentPreset); + kodi::SetSettingInt("lastpresetidx", m_currentPreset); + return true; +} - //std::string str = "void mainImage( out vec4 fragColor, in vec2 fragCoord ) { fragColor = texture2D(iChannel1, fragCoord.xy / iResolution.xy); }"; +bool CVisualizationShadertoy::PrevPreset() +{ + m_currentPreset = (m_currentPreset - 1) % g_presets.size(); + Launch(m_currentPreset); + kodi::SetSettingInt("lastpresetidx", m_currentPreset); + return true; +} - std::string fsSource = fsHeader + "\n" + str + "\n" + fsFooter; - return fsSource; +bool CVisualizationShadertoy::LoadPreset(int select) +{ + m_currentPreset = select % g_presets.size(); + Launch(m_currentPreset); + kodi::SetSettingInt("lastpresetidx", m_currentPreset); + return true; } -GLint loadTexture(int number) +bool CVisualizationShadertoy::RandomPreset() { - if (number >= 0 && number < g_numberTextures) { - GLint format = GL_RGBA; - GLint scaling = GL_LINEAR; - GLint repeat = GL_REPEAT; - return createTexture(g_fileTextures[number], format, scaling, repeat); - } - else if (number == 99) { // framebuffer - return createTexture(GL_LUMINANCE, NUM_BANDS, 2, audio_data); - } - return 0; + m_currentPreset = (int)((std::rand() / (float)RAND_MAX) * g_presets.size()); + Launch(m_currentPreset); + kodi::SetSettingInt("lastpresetidx", m_currentPreset); + return true; } -void loadPreset(int preset, std::string vsSource, std::string fsSource) +//-- GetPresets --------------------------------------------------------------- +// Return a list of presets to Kodi for display +//----------------------------------------------------------------------------- +bool CVisualizationShadertoy::GetPresets(std::vector& presets) { - unloadPreset(); - shadertoy_shader = compileAndLinkProgram(vsSource.c_str(), fsSource.c_str()); - - iResolutionLoc = glGetUniformLocation(shadertoy_shader, "iResolution"); - iGlobalTimeLoc = glGetUniformLocation(shadertoy_shader, "iGlobalTime"); - iChannelTimeLoc = glGetUniformLocation(shadertoy_shader, "iChannelTime"); - iMouseLoc = glGetUniformLocation(shadertoy_shader, "iMouse"); - iDateLoc = glGetUniformLocation(shadertoy_shader, "iDate"); - iSampleRateLoc = glGetUniformLocation(shadertoy_shader, "iSampleRate"); - iChannelResolutionLoc = glGetUniformLocation(shadertoy_shader, "iChannelResolution"); - iChannelLoc[0] = glGetUniformLocation(shadertoy_shader, "iChannel0"); - iChannelLoc[1] = glGetUniformLocation(shadertoy_shader, "iChannel1"); - iChannelLoc[2] = glGetUniformLocation(shadertoy_shader, "iChannel2"); - iChannelLoc[3] = glGetUniformLocation(shadertoy_shader, "iChannel3"); - -#if defined(HAS_GLES) - state->uScale = glGetUniformLocation(shadertoy_shader, "uScale"); - state->attr_vertex_e = glGetAttribLocation(shadertoy_shader, "vertex"); - - state->render_program = compileAndLinkProgram(render_vsSource.c_str(), render_fsSource.c_str()); - state->uTexture = glGetUniformLocation(state->render_program, "uTexture"); - state->attr_vertex_r = glGetAttribLocation(state->render_program, "vertex"); - // Prepare a texture to render to - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &state->framebuffer_texture); - glBindTexture(GL_TEXTURE_2D, state->framebuffer_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, state->fbwidth, state->fbheight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // Prepare a framebuffer for rendering - glGenFramebuffers(1, &state->effect_fb); - glBindFramebuffer(GL_FRAMEBUFFER, state->effect_fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, state->framebuffer_texture, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - initial_time = P8PLATFORM::GetTimeMs(); -#endif + for (auto preset : g_presets) + presets.push_back(preset.name); + return true; } -static uint64_t GetTimeStamp() { - struct timeval tv; - gettimeofday(&tv,NULL); - return tv.tv_sec*(uint64_t)1000000+tv.tv_usec; +//-- GetPreset ---------------------------------------------------------------- +// Return the index of the current playing preset +//----------------------------------------------------------------------------- +int CVisualizationShadertoy::GetActivePreset() +{ + return m_currentPreset; } -static void RenderTo(GLuint shader, GLuint effect_fb) +void CVisualizationShadertoy::RenderTo(GLuint shader, GLuint effect_fb) { glUseProgram(shader); -#if !defined(HAS_GLES) - glDisable(GL_BLEND); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(-1, 1, -1, 1, -1, 1); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - glClear(GL_DEPTH_BUFFER_BIT); - glPushMatrix(); -#endif - - if (shader == shadertoy_shader) { - GLuint w = width, h = height; -#if defined(HAS_GLES) - if (state->fbwidth && state->fbheight) - w = state->fbwidth, h = state->fbheight; -#endif - int64_t intt = P8PLATFORM::GetTimeMs() - initial_time; - if (bits_precision) - intt &= (1<(std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count() * 1000.0) - m_initialTime; + if (m_bitsPrecision) + intt &= (1<uScale, (GLfloat)width/state->fbwidth, (GLfloat)height/state->fbheight); -#endif + glUniform3f(m_attrResolutionLoc, w, h, 0.0f); + glUniform1f(m_attrGlobalTimeLoc, t); + glUniform1f(m_attrSampleRateLoc, m_samplesPerSec); + glUniform1fv(m_attrChannelTimeLoc, 4, tv); + glUniform2f(m_state.uScale, static_cast(Width()) / m_state.fbwidth, static_cast(Height()) /m_state.fbheight); + time_t now = time(NULL); tm *ltm = localtime(&now); @@ -659,208 +383,97 @@ static void RenderTo(GLuint shader, GLuint effect_fb) float day = ltm->tm_mday; float sec = (ltm->tm_hour * 60 * 60) + (ltm->tm_min * 60) + ltm->tm_sec; - glUniform4f(iDateLoc, year, month, day, sec); + glUniform4f(m_attrDateLoc, year, month, day, sec); - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) + { glActiveTexture(GL_TEXTURE0 + i); -#if !defined(HAS_GLES) - glEnable(GL_TEXTURE_2D); -#endif - glUniform1i(iChannelLoc[i], i); - glBindTexture(GL_TEXTURE_2D, iChannel[i]); + glUniform1i(m_attrChannelLoc[i], i); + glBindTexture(GL_TEXTURE_2D, m_channelTextures[i]); } - } else { -#if defined(HAS_GLES) + } + else + { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, state->framebuffer_texture); - glUniform1i(state->uTexture, 0); // first currently bound texture "GL_TEXTURE0" -#endif + glBindTexture(GL_TEXTURE_2D, m_state.framebuffer_texture); + glUniform1i(m_state.uTexture, 0); // first currently bound texture "GL_TEXTURE0" } -#if defined(HAS_GLES) // Draw the effect to a texture or direct to framebuffer glBindFramebuffer(GL_FRAMEBUFFER, effect_fb); - GLuint attr_vertex = shader == shadertoy_shader ? state->attr_vertex_e : state->attr_vertex_r; - glBindBuffer(GL_ARRAY_BUFFER, state->vertex_buffer); + GLuint attr_vertex = shader == m_shadertoyShader.ProgramHandle() ? m_state.attr_vertex_e : m_state.attr_vertex_r; + glBindBuffer(GL_ARRAY_BUFFER, m_state.vertex_buffer); glVertexAttribPointer(attr_vertex, 4, GL_FLOAT, 0, 16, 0); glEnableVertexAttribArray(attr_vertex); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableVertexAttribArray(attr_vertex); glBindBuffer(GL_ARRAY_BUFFER, 0); -#else - glBegin(GL_QUADS); - glVertex3f(-1.0f, 1.0f, 0.0f); - glVertex3f( 1.0f, 1.0f, 0.0f); - glVertex3f( 1.0f,-1.0f, 0.0f); - glVertex3f(-1.0f,-1.0f, 0.0f); - glEnd(); -#endif - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) + { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, 0); } -#if !defined(HAS_GLES) - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); -#endif + glUseProgram(0); } - -class CVisualizationShadertoy - : public kodi::addon::CAddonBase - , public kodi::addon::CInstanceVisualization -{ -public: - virtual ~CVisualizationShadertoy(); - - virtual ADDON_STATUS Create() override; - - virtual bool Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName) override; - virtual void Stop() override; - virtual void AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength) override; - virtual void Render() override; - virtual bool GetPresets(std::vector& presets) override; - virtual int GetActivePreset() override; - virtual bool PrevPreset() override; - virtual bool NextPreset() override; - virtual bool LoadPreset(int select) override; - virtual bool RandomPreset() override; -}; - -//-- Render ------------------------------------------------------------------- -// Called once per frame. Do all rendering here. -//----------------------------------------------------------------------------- -void CVisualizationShadertoy::Render() +void CVisualizationShadertoy::Mix(float* destination, const float* source, size_t frames, size_t channels) { - glGetError(); - //cout << "Render" << std::endl; - if (initialized) { -#if defined(HAS_GLES) - if (state->fbwidth && state->fbheight) { - RenderTo(shadertoy_shader, state->effect_fb); - RenderTo(state->render_program, 0); - } else { - RenderTo(shadertoy_shader, 0); - } -#else - RenderTo(shadertoy_shader, 0); -#endif - static int frames = 0; - static uint64_t ts; - if (frames == 0) { - ts = GetTimeStamp(); - } - frames++; - uint64_t ts2 = GetTimeStamp(); - if (ts2 - ts > 1e6) + size_t length = frames * channels; + for (unsigned int i = 0; i < length; i += channels) + { + float v = 0.0f; + for (size_t j = 0; j < channels; j++) { - printf("%d fps\n", frames); - ts += 1e6; - frames = 0; + v += source[i + j]; } - } -} - -#ifdef HAS_GLES -static int determine_bits_precision() -{ - std::string vsPrecisionSource = TO_STRING( - void mainImage( out vec4 fragColor, in vec2 fragCoord ) - { - float y = ( fragCoord.y / iResolution.y ) * 26.0; - float x = 1.0 - ( fragCoord.x / iResolution.x ); - float b = fract( pow( 2.0, floor(y) ) + x ); - if (fract(y) >= 0.9) - b = 0.0; - fragColor = vec4(b, b, b, 1.0 ); - } - ); - std::string fsPrecisionSource = fsHeader + "\n" + vsPrecisionSource + "\n" + fsFooter; - - state->fbwidth = 32, state->fbheight = 26*10; - loadPreset(0, vsSource, fsPrecisionSource); - RenderTo(shadertoy_shader, state->effect_fb); - glFinish(); - unsigned char *buffer = new unsigned char[state->fbwidth * state->fbheight * 4]; - if (buffer) - glReadPixels(0, 0, state->fbwidth, state->fbheight, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - #if 0 - for (int j=0; jfbheight; j++) { - for (int i=0; ifbwidth; i++) { - printf("%02x ", buffer[4*(j*state->fbwidth+i)]); - } - printf("\n"); - } - #endif - int bits = 0; - unsigned char b = 0; - for (int j=0; jfbheight; j++) { - unsigned char c = buffer[4*(j*state->fbwidth+(state->fbwidth>>1))]; - if (c && !b) - bits++; - b = c; + destination[(i / 2)] = v / (float)channels; } - delete buffer; - unloadPreset(); - return bits; } -static double measure_performance(int preset, int size) +void CVisualizationShadertoy::WriteToBuffer(const float* input, size_t length, size_t channels) { - int iterations = -1; - std::string fsSource = createShader(g_presets[preset].file); + size_t frames = length / channels; + + if (frames >= AUDIO_BUFFER) + { + size_t offset = frames - AUDIO_BUFFER; - state->fbwidth = state->fbheight = size; - loadPreset(preset, vsSource, fsSource); + Mix(m_pcm, input + offset, AUDIO_BUFFER, channels); + } + else + { + size_t keep = AUDIO_BUFFER - frames; + memmove(m_pcm, m_pcm + frames, keep * sizeof(float)); - int64_t end, start; - do { -#if defined(HAS_GLES) - RenderTo(shadertoy_shader, state->effect_fb); - RenderTo(state->render_program, state->effect_fb); -#else - RenderTo(shadertoy_shader, 0); -#endif - glFinish(); - if (++iterations == 0) - start = P8PLATFORM::GetTimeMs(); - end = P8PLATFORM::GetTimeMs(); - } while (end - start < 50); - double t = (double)(end - start)/iterations; - //printf("%s %dx%d %.1fms = %.2f fps\n", __func__, size, size, t, 1000.0/t); - unloadPreset(); - return t; + Mix(m_pcm + keep, input, frames, channels); + } } -#endif -static void launch(int preset) +void CVisualizationShadertoy::Launch(int preset) { -#ifdef HAS_GLES - bits_precision = determine_bits_precision(); + m_bitsPrecision = DetermineBitsPrecision(); // mali-400 has only 10 bits which means milliseond timer wraps after ~1 second. // we'll fudge that up a bit as having a larger range is more important than ms accuracy - bits_precision = max(bits_precision, 13); - printf("bits=%d\n", bits_precision); + m_bitsPrecision = std::max(m_bitsPrecision, 13); +#ifdef DEBUG_PRINT + printf("bits=%d\n", m_bitsPrecision); #endif - - unloadTextures(); - for (int i=0; i<4; i++) { + + UnloadTextures(); + for (int i = 0; i < 4; i++) + { if (g_presets[preset].channel[i] >= 0) - iChannel[i] = loadTexture(g_presets[preset].channel[i]); + m_channelTextures[i] = LoadTexture(g_presets[preset].channel[i]); } -#ifdef HAS_GLES const int size1 = 256, size2=512; - double t1 = measure_performance(preset, size1); - double t2 = measure_performance(preset, size2); - + double t1 = MeasurePerformance(preset, size1); + double t2 = MeasurePerformance(preset, size2); + double expected_fps = 40.0; // time per pixel for rendering fragment shader double B = (t2-t1)/(size2*size2-size1*size1); @@ -868,227 +481,251 @@ static void launch(int preset) double A = t2 - size2*size2 * B; // how many pixels get the desired fps double pixels = (1000.0/expected_fps - A) / B; - state->fbwidth = sqrtf(pixels * width / height); - if (state->fbwidth * 4 >= width * 3) - state->fbwidth = 0; - else if (state->fbwidth < 320) - state->fbwidth = 320; - state->fbheight = state->fbwidth * height / width; - - printf("expected fps=%f, pixels=%f %dx%d (A:%f B:%f t1:%.1f t2:%.1f)\n", expected_fps, pixels, state->fbwidth, state->fbheight, A, B, t1, t2); + m_state.fbwidth = sqrtf(pixels * Width() / Height()); + if (m_state.fbwidth * 4 >= Width() * 3) + m_state.fbwidth = 0; + else if (m_state.fbwidth < 320) + m_state.fbwidth = 320; + m_state.fbheight = m_state.fbwidth * Height() / Width(); + +#ifdef DEBUG_PRINT + printf("expected fps=%f, pixels=%f %dx%d (A:%f B:%f t1:%.1f t2:%.1f)\n", expected_fps, pixels, m_state.fbwidth, m_state.fbheight, A, B, t1, t2); #endif - std::string fsSource = createShader(g_presets[preset].file); - loadPreset(preset, vsSource, fsSource); + LoadPreset(preset, kodi::GetAddonPath("resources/shaders/" + g_presets[preset].file)); } -bool CVisualizationShadertoy::Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, std::string szSongName) +GLint CVisualizationShadertoy::LoadTexture(int number) { - cout << "Start " << iChannels << " " << iSamplesPerSec << " " << iBitsPerSample << " " << szSongName << std::endl; - samplesPerSec = iSamplesPerSec; - return true; + if (number >= 0 && number < g_fileTextures.size()) + { + GLint format = GL_RGBA; + GLint scaling = GL_LINEAR; + GLint repeat = GL_REPEAT; + return CreateTexture(kodi::GetAddonPath("resources/" + g_fileTextures[number]), format, scaling, repeat); + } + else if (number == 99) // framebuffer + { + return CreateTexture(GL_RED, NUM_BANDS, 2, m_audioData); + } + return 0; } -void CVisualizationShadertoy::Stop() +void CVisualizationShadertoy::UnloadTextures() { - cout << "Stop" << std::endl; + for (int i = 0; i < 4; i++) + { + if (m_channelTextures[i]) + { + glDeleteTextures(1, &m_channelTextures[i]); + m_channelTextures[i] = 0; + } + } } -void Mix(float *destination, const float *source, size_t frames, size_t channels) +void CVisualizationShadertoy::LoadPreset(int preset, const std::string& shaderPath) { - size_t length = frames * channels; - for (unsigned int i = 0; i < length; i += channels) { - float v = 0.0f; - for (size_t j = 0; j < channels; j++) { - v += source[i + j]; - } + UnloadPreset(); + std::string vertShadertoyShader = kodi::GetAddonPath("resources/shaders/main_shadertoy_" GL_TYPE_STRING ".vert.glsl"); + if (!m_shadertoyShader.LoadShaderFiles(vertShadertoyShader, shaderPath) || + !m_shadertoyShader.CompileAndLink("", "", fsHeader, fsFooter)) + { + kodi::Log(ADDON_LOG_ERROR, "Failed to compile shadertoy shaders (current shadertoy file '%s')", shaderPath.c_str()); + return; + } - destination[(i / 2)] = v / (float)channels; + GLuint shadertoyShader = m_shadertoyShader.ProgramHandle(); + + m_attrResolutionLoc = glGetUniformLocation(shadertoyShader, "iResolution"); + m_attrGlobalTimeLoc = glGetUniformLocation(shadertoyShader, "iGlobalTime"); + m_attrChannelTimeLoc = glGetUniformLocation(shadertoyShader, "iChannelTime"); + m_attrMouseLoc = glGetUniformLocation(shadertoyShader, "iMouse"); + m_attrDateLoc = glGetUniformLocation(shadertoyShader, "iDate"); + m_attrSampleRateLoc = glGetUniformLocation(shadertoyShader, "iSampleRate"); + m_attrChannelResolutionLoc = glGetUniformLocation(shadertoyShader, "iChannelResolution"); + m_attrChannelLoc[0] = glGetUniformLocation(shadertoyShader, "iChannel0"); + m_attrChannelLoc[1] = glGetUniformLocation(shadertoyShader, "iChannel1"); + m_attrChannelLoc[2] = glGetUniformLocation(shadertoyShader, "iChannel2"); + m_attrChannelLoc[3] = glGetUniformLocation(shadertoyShader, "iChannel3"); + + m_state.uScale = glGetUniformLocation(shadertoyShader, "uScale"); + m_state.attr_vertex_e = glGetAttribLocation(shadertoyShader, "vertex"); + + std::string vertShader = kodi::GetAddonPath("resources/shaders/main_display_" GL_TYPE_STRING ".vert.glsl"); + std::string fraqShader = kodi::GetAddonPath("resources/shaders/main_display_" GL_TYPE_STRING ".frag.glsl"); + if (!m_displayShader.LoadShaderFiles(vertShader, fraqShader) || + !m_displayShader.CompileAndLink()) + { + kodi::Log(ADDON_LOG_ERROR, "Failed to compile main shaders"); + return; } -} -void WriteToBuffer(const float *input, size_t length, size_t channels) -{ - size_t frames = length / channels; + m_state.uTexture = glGetUniformLocation(m_displayShader.ProgramHandle(), "uTexture"); + m_state.attr_vertex_r = glGetAttribLocation(m_displayShader.ProgramHandle(), "vertex"); - if (frames >= AUDIO_BUFFER) { - size_t offset = frames - AUDIO_BUFFER; + // Prepare a texture to render to + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, &m_state.framebuffer_texture); + glBindTexture(GL_TEXTURE_2D, m_state.framebuffer_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_state.fbwidth, m_state.fbheight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - Mix(pcm, input + offset, AUDIO_BUFFER, channels); - } else { - size_t keep = AUDIO_BUFFER - frames; - memmove(pcm, pcm + frames, keep * sizeof(float)); + // Prepare a framebuffer for rendering + glGenFramebuffers(1, &m_state.effect_fb); + glBindFramebuffer(GL_FRAMEBUFFER, m_state.effect_fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_state.framebuffer_texture, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + m_initialTime = static_cast(std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count() * 1000.0); +} - Mix(pcm + keep, input, frames, channels); +void CVisualizationShadertoy::UnloadPreset() +{ + if (m_state.framebuffer_texture) + { + glDeleteTextures(1, &m_state.framebuffer_texture); + m_state.framebuffer_texture = 0; + } + if (m_state.effect_fb) + { + glDeleteFramebuffers(1, &m_state.effect_fb); + m_state.effect_fb = 0; } } -void CVisualizationShadertoy::AudioData(const float* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength) +GLuint CVisualizationShadertoy::CreateTexture(GLint format, unsigned int w, unsigned int h, const GLvoid* data) { - //cout << "AudioData" << std::endl; - WriteToBuffer(pAudioData, iAudioDataLength, 2); + GLuint texture = 0; + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); - kiss_fft_cpx in[AUDIO_BUFFER], out[AUDIO_BUFFER]; - for (unsigned int i = 0; i < AUDIO_BUFFER; i++) { - in[i].r = blackmanWindow(pcm[i], i, AUDIO_BUFFER); - in[i].i = 0; - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - kiss_fft(cfg, in, out); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - out[0].i = 0; + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, data); + return texture; +} - smoothingOverTime(magnitude_buffer, magnitude_buffer, out, NUM_BANDS, SMOOTHING_TIME_CONSTANT, AUDIO_BUFFER); +GLuint CVisualizationShadertoy::CreateTexture(const GLvoid* data, GLint format, unsigned int w, unsigned int h, GLint internalFormat, GLint scaling, GLint repeat) +{ + GLuint texture = 0; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); - const double rangeScaleFactor = MAX_DECIBELS == MIN_DECIBELS ? 1 : (1.0 / (MAX_DECIBELS - MIN_DECIBELS)); - for (unsigned int i = 0; i < NUM_BANDS; i++) { - float linearValue = magnitude_buffer[i]; - double dbMag = !linearValue ? MIN_DECIBELS : linearToDecibels(linearValue); - double scaledValue = UCHAR_MAX * (dbMag - MIN_DECIBELS) * rangeScaleFactor; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, scaling); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, scaling); - audio_data[i] = std::max(std::min((int)scaledValue, UCHAR_MAX), 0); - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeat); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeat); - for (unsigned int i = 0; i < NUM_BANDS; i++) { - float v = (pcm[i] + 1.0f) * 128.0f; - audio_data[i + NUM_BANDS] = std::max(std::min((int)v, UCHAR_MAX), 0); - } + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_2D, 0); - needsUpload = true; + return texture; } -//-- OnAction ----------------------------------------------------------------- -// Handle XBMC actions such as next preset, lock preset, album art changed etc -//----------------------------------------------------------------------------- -bool CVisualizationShadertoy::NextPreset() +GLuint CVisualizationShadertoy::CreateTexture(const std::string& file, GLint internalFormat, GLint scaling, GLint repeat) { - LogAction("VIS_ACTION_NEXT_PRESET"); - g_currentPreset = (g_currentPreset + 1) % g_presets.size(); - launch(g_currentPreset); - kodi::SetSettingInt("lastpresetidx", g_currentPreset); - return true; -} +#ifdef DEBUG_PRINT + printf("creating texture %s\n", file.c_str()); +#endif -bool CVisualizationShadertoy::PrevPreset() -{ - LogAction("VIS_ACTION_PREV_PRESET"); - g_currentPreset = (g_currentPreset - 1) % g_presets.size(); - launch(g_currentPreset); - kodi::SetSettingInt("lastpresetidx", g_currentPreset); - return true; -} + unsigned error; + unsigned char* image; + unsigned width, height; -bool CVisualizationShadertoy::LoadPreset(int select) -{ - LogAction("VIS_ACTION_LOAD_PRESET"); - g_currentPreset = select % g_presets.size(); - launch(g_currentPreset); - kodi::SetSettingInt("lastpresetidx", g_currentPreset); - return true; + error = lodepng_decode32_file(&image, &width, &height, file.c_str()); + if (error) + { + kodi::Log(ADDON_LOG_ERROR, "lodepng_decode32_file error %u: %s", error, lodepng_error_text(error)); + return 0; + } + + GLuint texture = CreateTexture(image, GL_RGBA, width, height, internalFormat, scaling, repeat); + free(image); + return texture; } -bool CVisualizationShadertoy::RandomPreset() +float CVisualizationShadertoy::BlackmanWindow(float in, size_t i, size_t length) { - LogAction("VIS_ACTION_RANDOM_PRESET"); - g_currentPreset = (int)((std::rand() / (float)RAND_MAX) * g_presets.size()); - launch(g_currentPreset); - kodi::SetSettingInt("lastpresetidx", g_currentPreset); - return true; + double alpha = 0.16; + double a0 = 0.5 * (1.0 - alpha); + double a1 = 0.5; + double a2 = 0.5 * alpha; + + float x = (float)i / (float)length; + return in * (a0 - a1 * cos(2.0 * M_PI * x) + a2 * cos(4.0 * M_PI * x)); } -//-- GetPresets --------------------------------------------------------------- -// Return a list of presets to XBMC for display -//----------------------------------------------------------------------------- -bool CVisualizationShadertoy::GetPresets(std::vector& presets) +void CVisualizationShadertoy::SmoothingOverTime(float* outputBuffer, float* lastOutputBuffer, kiss_fft_cpx* inputBuffer, size_t length, float smoothingTimeConstant, unsigned int fftSize) { - for (auto preset : g_presets) - presets.push_back(preset.name); - return true; + for (size_t i = 0; i < length; i++) + { + kiss_fft_cpx c = inputBuffer[i]; + float magnitude = sqrt(c.r * c.r + c.i * c.i) / (float)fftSize; + outputBuffer[i] = smoothingTimeConstant * lastOutputBuffer[i] + (1.0 - smoothingTimeConstant) * magnitude; + } } -//-- GetPreset ---------------------------------------------------------------- -// Return the index of the current playing preset -//----------------------------------------------------------------------------- -int CVisualizationShadertoy::GetActivePreset() +float CVisualizationShadertoy::LinearToDecibels(float linear) { - return g_currentPreset; + if (!linear) + return -1000; + return 20 * log10f(linear); } -//-- Create ------------------------------------------------------------------- -// Called on load. Addon should fully initalize or return error status -//----------------------------------------------------------------------------- -ADDON_STATUS CVisualizationShadertoy::Create() +int CVisualizationShadertoy::DetermineBitsPrecision() { - cout << "ADDON_Create" << std::endl; - - g_pathPresets = Presets(); - width = Width(); - height = Height(); - - audio_data = new GLubyte[AUDIO_BUFFER](); - magnitude_buffer = new float[NUM_BANDS](); - pcm = new float[AUDIO_BUFFER](); + m_state.fbwidth = 32, m_state.fbheight = 26*10; + LoadPreset(0, kodi::GetAddonPath("resources/shaders/main_test.frag.glsl")); + RenderTo(m_shadertoyShader.ProgramHandle(), m_state.effect_fb); + glFinish(); - cfg = kiss_fft_alloc(AUDIO_BUFFER, 0, NULL, NULL); + unsigned char* buffer = new unsigned char[m_state.fbwidth * m_state.fbheight * 4]; + if (buffer) + glReadPixels(0, 0, m_state.fbwidth, m_state.fbheight, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - if (!initialized) + int bits = 0; + unsigned char b = 0; + for (int j=0; jvertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, state->vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); -#endif - launch(g_currentPreset); - initialized = true; + unsigned char c = buffer[4*(j*m_state.fbwidth+(m_state.fbwidth>>1))]; + if (c && !b) + bits++; + b = c; } - - return ADDON_STATUS_OK; + delete buffer; + UnloadPreset(); + return bits; } -//-- Destroy ------------------------------------------------------------------ -// Do everything before unload of this add-on -// !!! Add-on master function !!! -//----------------------------------------------------------------------------- -CVisualizationShadertoy::~CVisualizationShadertoy() +double CVisualizationShadertoy::MeasurePerformance(int preset, int size) { - cout << "ADDON_Destroy" << std::endl; - - unloadPreset(); - unloadTextures(); - - if (audio_data) { - delete [] audio_data; - audio_data = NULL; - } - - if (magnitude_buffer) { - delete [] magnitude_buffer; - magnitude_buffer = NULL; - } - - if (pcm) { - delete [] pcm; - pcm = NULL; - } + int iterations = -1; + m_state.fbwidth = m_state.fbheight = size; + LoadPreset(preset, kodi::GetAddonPath("resources/shaders/" + g_presets[preset].file)); - if (cfg) { - free(cfg); - cfg = 0; - } -#if defined(HAS_GLES) - glDeleteBuffers(1, &state->vertex_buffer); + int64_t end, start; + do + { + RenderTo(m_shadertoyShader.ProgramHandle(), m_state.effect_fb); + RenderTo(m_displayShader.ProgramHandle(), m_state.effect_fb); + glFinish(); + if (++iterations == 0) + start = static_cast(std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count() * 1000.0); + end = static_cast(std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count() * 1000.0); + } while (end - start < 50); + double t = (double)(end - start)/iterations; +#ifdef DEBUG_PRINT + printf("%s %dx%d %.1fms = %.2f fps\n", __func__, size, size, t, 1000.0/t); #endif - - initialized = false; + UnloadPreset(); + return t; } ADDONCREATOR(CVisualizationShadertoy) // Don't touch this! diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..24c6288 --- /dev/null +++ b/src/main.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2005-2019 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kodi; see the file COPYING. If not, see + * . + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include "kissfft/kiss_fft.h" + +class ATTRIBUTE_HIDDEN CVisualizationShadertoy + : public kodi::addon::CAddonBase + , public kodi::addon::CInstanceVisualization +{ +public: + CVisualizationShadertoy(); + ~CVisualizationShadertoy() override; + + bool Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName) override; + void Stop() override; + void AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength) override; + void Render() override; + bool GetPresets(std::vector& presets) override; + int GetActivePreset() override; + bool PrevPreset() override; + bool NextPreset() override; + bool LoadPreset(int select) override; + bool RandomPreset() override; + +private: + void RenderTo(GLuint shader, GLuint effect_fb); + void Mix(float* destination, const float* source, size_t frames, size_t channels); + void WriteToBuffer(const float* input, size_t length, size_t channels); + void Launch(int preset); + void LoadPreset(int preset, const std::string& shaderPath); + void UnloadPreset(); + GLint LoadTexture(int number); + void UnloadTextures(); + GLuint CreateTexture(GLint format, unsigned int w, unsigned int h, const GLvoid* data); + GLuint CreateTexture(const GLvoid* data, GLint format, unsigned int w, unsigned int h, GLint internalFormat, GLint scaling, GLint repeat); + GLuint CreateTexture(const std::string& file, GLint internalFormat, GLint scaling, GLint repeat); + float BlackmanWindow(float in, size_t i, size_t length); + void SmoothingOverTime(float* outputBuffer, float* lastOutputBuffer, kiss_fft_cpx* inputBuffer, size_t length, float smoothingTimeConstant, unsigned int fftSize); + float LinearToDecibels(float linear); + int DetermineBitsPrecision(); + double MeasurePerformance(int preset, int size); + + kiss_fft_cfg m_kissCfg; + GLubyte* m_audioData; + float* m_magnitudeBuffer; + float* m_pcm; + + bool m_initialized = false; + int64_t m_initialTime = 0; // in ms + int m_bitsPrecision = 0; + int m_currentPreset = 0; + + int m_samplesPerSec = 0; // Given by Start(...) + bool m_needsUpload = true; // Set by AudioData(...) to mark presence of data + + GLint m_attrResolutionLoc = 0; + GLint m_attrGlobalTimeLoc = 0; + GLint m_attrChannelTimeLoc = 0; + GLint m_attrMouseLoc = 0; + GLint m_attrDateLoc = 0; + GLint m_attrSampleRateLoc = 0; + GLint m_attrChannelResolutionLoc = 0; + GLint m_attrChannelLoc[4] = {0}; + GLuint m_channelTextures[4] = {0}; + + kodi::gui::gl::CShaderProgram m_shadertoyShader; + kodi::gui::gl::CShaderProgram m_displayShader; + + struct + { + GLuint vertex_buffer; + GLuint attr_vertex_e; + GLuint attr_vertex_r, uTexture; + GLuint effect_fb; + GLuint framebuffer_texture; + GLuint uScale; + int fbwidth, fbheight; + } m_state; +}; diff --git a/visualization.shadertoy/addon.xml.in b/visualization.shadertoy/addon.xml.in index 1028889..3e4d405 100644 --- a/visualization.shadertoy/addon.xml.in +++ b/visualization.shadertoy/addon.xml.in @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ diff --git a/visualization.shadertoy/resources/circlewave.frag.glsl b/visualization.shadertoy/resources/circlewave.frag.glsl deleted file mode 100644 index ee6207e..0000000 --- a/visualization.shadertoy/resources/circlewave.frag.glsl +++ /dev/null @@ -1,52 +0,0 @@ -// Taken from https://www.shadertoy.com/view/Xsf3WB - -const float tau = 6.28318530717958647692; - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - vec2 uv = (fragCoord.xy - iResolution.xy*.5)/iResolution.x; - - uv = vec2(abs(atan(uv.x,uv.y)/(.5*tau)),length(uv)); - - // adjust frequency to look pretty - uv.x *= 1.0/2.0; - - float seperation = 0.06*(1.0-iMouse.x/iResolution.x); - - vec3 wave = vec3(0.0,0.0,0.0); - const int n = 9; - for ( int i=0; i < n; i++ ) - { -/* float u = uv.x*255.0; - float f = fract(u); - f = f*f*(3.0-2.0*f); - u = floor(u); - float sound = mix( texture2D( iChannel0, vec2((u+.5)/256.0,.75) ).x, texture2D( iChannel0, vec2((u+1.5)/256.0,.75) ).x, f );*/ - float sound = texture2D( iChannel0, vec2(uv.x,.75) ).x; - - // choose colour from spectrum - float a = .9*float(i)*tau/float(n)-.6; - vec3 phase = smoothstep(-1.0,.5,vec3(cos(a),cos(a-tau/3.0),cos(a-tau*2.0/3.0))); - - wave += phase*smoothstep(4.0/640.0, 0.0, abs(uv.y - sound*.3)); - uv.x += seperation/float(n); - } - wave *= 3.0/float(n); - - vec3 col = vec3(0,0,0); - col.z += texture2D( iChannel0, vec2(.000,.25) ).x; - col.zy += texture2D( iChannel0, vec2(.125,.25) ).xx*vec2(1.5,.5); - col.zy += texture2D( iChannel0, vec2(.250,.25) ).xx; - col.zy += texture2D( iChannel0, vec2(.375,.25) ).xx*vec2(.5,1.5); - col.y += texture2D( iChannel0, vec2(.500,.25) ).x; - col.yx += texture2D( iChannel0, vec2(.625,.25) ).xx*vec2(1.5,.5); - col.yx += texture2D( iChannel0, vec2(.750,.25) ).xx; - col.yx += texture2D( iChannel0, vec2(.875,.25) ).xx*vec2(.5,1.5); - col.x += texture2D( iChannel0, vec2(1.00,.25) ).x; - col /= vec3(4.0,7.0,4.0); - - // vignetting - col *= smoothstep( 1.2, 0.0, uv.y ); - - fragColor = vec4(wave+col,1); -} diff --git a/visualization.shadertoy/resources/circuits.frag.glsl b/visualization.shadertoy/resources/circuits.frag.glsl deleted file mode 100644 index 61d588c..0000000 --- a/visualization.shadertoy/resources/circuits.frag.glsl +++ /dev/null @@ -1,58 +0,0 @@ -// Taken from https://www.shadertoy.com/view/XlX3Rj# - -#define time iGlobalTime*.02 - - -#define width .005 -static float zoom = .18; - -static float shape=0.; -static vec3 color=vec3(0.,0.,0.),randcol; - -void formula(vec2 z, float c) { - float minit=0.; - float o,ot2,ot=ot2=1000.; - for (int i=0; i<9; i++) { - z=abs(z)/clamp(dot(z,z),.1,.5)-c; - float l=length(z); - o=min(max(abs(min(z.x,z.y)),-l+.25),abs(l-.25)); - ot=min(ot,o); - ot2=min(l*.1,ot2); - minit=max(minit,float(i)*(1.-abs(sign(ot-o)))); - } - minit+=1.; - float w=width*minit*2.; - float circ=pow(max(0.,w-ot2)/w,6.); - shape+=max(pow(max(0.,w-ot)/w,.25),circ); - vec3 col=normalize(.1+texture2D(iChannel1,vec2(minit*.1)).rgb); - color+=col*(.4+mod(minit/9.-time*10.+ot2*2.,1.)*1.6); - color+=vec3(1.,.7,.3)*circ*(10.-minit)*3.*smoothstep(0.,.5,.15+texture2D(iChannel0,vec2(.0,1.)).x-.5); -} - - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - vec2 pos = fragCoord.xy / iResolution.xy - .5; - pos.x*=iResolution.x/iResolution.y; - vec2 uv=pos; - float sph = length(uv); sph = sqrt(1. - sph*sph)*1.5; // curve for spheric distortion - uv=normalize(vec3(uv,sph)).xy; - float a=time+mod(time,1.)*.5; - vec2 luv=uv; - float b=a*5.48535; -// zoom*=1.+sin(time*3.758123)*.8; - uv*=mat2(cos(b),sin(b),-sin(b),cos(b)); - uv+=vec2(sin(a),cos(a*.5))*8.; - uv*=zoom; - float pix=.5/iResolution.x*zoom/sph; - float dof=max(1.,(10.-mod(time,1.)/.01)); - float c=1.5+mod(floor(time),6.)*.125; - for (int aa=0; aa<36; aa++) { - vec2 aauv=floor(vec2(float(aa)/6.,mod(float(aa),6.))); - formula(uv+aauv*pix*dof,c); - } - shape/=36.; color/=36.; - vec3 colo=mix(vec3(.15,.15,.15),color,shape)*(1.-length(pos))*min(1.,abs(.5-mod(time+.5,1.))*10.); - colo*=vec3(1.2,1.1,1.0); - fragColor = vec4(colo,1.0); -} diff --git a/visualization.shadertoy/resources/coloredbars.frag.glsl b/visualization.shadertoy/resources/coloredbars.frag.glsl deleted file mode 100644 index 12fe4f0..0000000 --- a/visualization.shadertoy/resources/coloredbars.frag.glsl +++ /dev/null @@ -1,115 +0,0 @@ -// Taken from https://www.shadertoy.com/view/XsBXW1# - -#define M_PI 3.1415926535897932384626433832795 -#define MAXDISTANCE 32. -#define MAXITERATIONS 32 -#define PRECISION 1e-3 - -float rand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -float plane(vec3 p, float z) { - return p.z - z; -} - -float udBox(vec3 p, vec3 b, out int object) { - float tme = iGlobalTime*2.0 + 1024.0; - - p.y += tme / 2.0; - float rowOffset = rand(vec2(0, floor(p.y/2.0))); - p.x += tme * (2. * rowOffset + texture2D(iChannel0, vec2(rowOffset,.25)).x/500.); - - object = int(6. * mod(p.x/(32.*6.), 1.)) + 2; - - vec2 c = vec2(32, 2); - p.xy = mod(p.xy, c)-.5*c; - return length(max(abs(p)-b,0.)); -} - -float getMap(vec3 p, out int object) { - float distance = MAXDISTANCE; - float tempDist; - int tempObject; - - distance = plane(p, 0.0); - object = 1; - - tempDist = udBox(p, vec3(12.0, 0.5, 0.5), tempObject); - if (tempDist <= distance) { - distance = tempDist; - object = tempObject; - } - return distance * 0.5; -} - -vec2 castRay(vec3 origin, vec3 direction, out int object) { - float distance = rand(vec2(direction.y * iGlobalTime, direction.x)) * 6.0; - float delta = 0.0; - object = 0; - - for (int i = 0; i < MAXITERATIONS; i++) { - vec3 p = origin + direction * distance; - - delta = getMap(p, object); - - distance += delta; - if (delta < PRECISION) { - return vec2(distance, float(i)); - } - if (distance > MAXDISTANCE) { - object = 0; - return vec2(distance, float(i)); - } - } - - object = 0; - return vec2(distance, MAXITERATIONS); -} - -vec3 drawScene(vec3 origin, vec3 direction) { - vec3 color = vec3(0.0, 0.0, 0.0); - int object = 0; - - vec2 ray = castRay(origin, direction, object); - - if (object != 0) { - if (object == 1) { - color = vec3(1.0, 1.0, 1.0); - } - else if (object == 2) { - color = vec3(1.0, 0.3, 0.3); - } - else if (object == 3) { - color = vec3(0.3, 1.0, 0.3); - } - else if (object == 4) { - color = vec3(0.3, 0.3, 1.0); - } - else if (object == 5) { - color = vec3(1.0, 1.0, 0.3); - } - else if (object == 6) { - color = vec3(0.3, 1.0, 1.0); - } - else if (object == 7) { - color = vec3(1.0, 0.3, 1.0); - } - } - return mix(color, vec3(0.0, 0.0, 0.0), ray.y/float(MAXITERATIONS)); -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - vec2 p = (fragCoord.xy / iResolution.xy) * 2.0 - 1.0; - float aspect = iResolution.x / iResolution.y; - p.x *= aspect; - - vec3 color = vec3(0.0, 0.0, 0.0); - vec3 origin = vec3(0.0, 0.0, 12.0); - vec3 direction = normalize(vec3(p.x, p.y, -1.0)); - direction.xy = mat2(cos(M_PI/4.0), sin(M_PI/4.0), -sin(M_PI/4.0), cos(M_PI/4.0)) * direction.xy; - - color = drawScene(origin, direction); - - fragColor = vec4(color, 1.0); -} diff --git a/visualization.shadertoy/resources/dancingmetalights.frag.glsl b/visualization.shadertoy/resources/dancingmetalights.frag.glsl deleted file mode 100644 index db10fcb..0000000 --- a/visualization.shadertoy/resources/dancingmetalights.frag.glsl +++ /dev/null @@ -1,43 +0,0 @@ -// from: https://www.shadertoy.com/view/XdfGRH - -/* - * I believe that the code is clear enough, so I will save comments :) - * But if you need help to understand anything, just tell me. - * This shader is free to use as long it is distributed with credits. - * And, yeah, you can change it. - * - * Author: Danguafer/Silexars - */ - -float beat = 0.; -float mb(vec2 p1, vec2 p0) { return (0.04+beat)/(pow(p1.x-p0.x,2.)+pow(p1.y-p0.y,2.)); } - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - float ct = iChannelTime[0]; - if ((ct > 8.0 && ct < 33.5) - || (ct > 38.0 && ct < 88.5) - || (ct > 93.0 && ct < 194.5)) - beat = pow(sin(ct*3.1416*3.78+1.9)*0.5+0.5,15.0)*0.05; - - vec2 mbr,mbg,mbb; - vec2 p = (2.0*fragCoord.xy-iResolution.xy)/iResolution.y; - vec2 o = vec2(pow(p.x,2.),pow(p.y,2.)); - vec3 col = vec3(pow(2.*abs(o.x+o.y)+abs(o.x-o.y),5.)); - col = max(col,1.); - float t=iGlobalTime+beat*2.; - - float t2=t*2.0,t3=t*3.0,s2=sin(t2),s3=sin(t3),s4=sin(t*4.0),c2=cos(t2),c3=cos(t3); // Let me extend this line a little more with an useless comment :-) - - mbr = mbg = mbb = vec2(0.); - mbr += vec2(0.10*s4+0.40*c3,0.40*s2 +0.20*c3); - mbg += vec2(0.15*s3+0.30*c2,0.10*-s4+0.30*c3); - mbb += vec2(0.10*s3+0.50*c3,0.10*-s4+0.50*c2); - - col.r *= length(mbr.xy-p.xy); - col.g *= length(mbg.xy-p.xy); - col.b *= length(mbb.xy-p.xy); - col *= pow(mb(mbr,p)+mb(mbg,p)+mb(mbb,p),1.75); - - fragColor = vec4(col,1.); -} diff --git a/visualization.shadertoy/resources/fractalland.frag.glsl b/visualization.shadertoy/resources/fractalland.frag.glsl deleted file mode 100644 index 14de8fc..0000000 --- a/visualization.shadertoy/resources/fractalland.frag.glsl +++ /dev/null @@ -1,223 +0,0 @@ -// Taken from https://www.shadertoy.com/view/XsBXWt# - -// "Fractal Cartoon" - former "DE edge detection" by Kali - -// Cartoon-like effect using eiffies's edge detection found here: -// https://www.shadertoy.com/view/4ss3WB -// I used my own method previously but was too complicated and not compiling everywhere. -// Thanks to the suggestion by WouterVanNifterick. - -// There are no lights and no AO, only color by normals and dark edges. - -// update: Nyan Cat cameo, thanks to code from mu6k: https://www.shadertoy.com/view/4dXGWH - - -//#define SHOWONLYEDGES -#define NYAN -#define WAVES -#define BORDER - -#define RAY_STEPS 150 - -#define BRIGHTNESS 1.2 -#define GAMMA 1.4 -#define SATURATION .65 - - -#define detail .001 -#define t iGlobalTime*.5 - - -const vec3 origin=vec3(-1.,.7,0.); -float det=0.0; - - -// 2D rotation function -mat2 rot(float a) { - return mat2(cos(a),sin(a),-sin(a),cos(a)); -} - -// "Amazing Surface" fractal -vec4 formula(vec4 p) { - p.xz = abs(p.xz+1.)-abs(p.xz-1.)-p.xz; - p.y-=.25; - p.xy*=rot(radians(35.)); - p=p*2./clamp(dot(p.xyz,p.xyz),.2,1.); - return p; -} - -// Distance function -float de(vec3 pos) { -#ifdef WAVES - pos.y+=sin(pos.z-t*6.)*.15; //waves! -#endif - float hid=0.; - vec3 tpos=pos; - tpos.z=abs(3.-mod(tpos.z,6.)); - vec4 p=vec4(tpos,1.); - for (int i=0; i<4; i++) {p=formula(p);} - float fr=(length(max(vec2(0.),p.yz-1.5))-1.)/p.w; - float ro=max(abs(pos.x+1.)-.3,pos.y-.35); - ro=max(ro,-max(abs(pos.x+1.)-.1,pos.y-.5)); - pos.z=abs(.25-mod(pos.z,.5)); - ro=max(ro,-max(abs(pos.z)-.2,pos.y-.3)); - ro=max(ro,-max(abs(pos.z)-.01,-pos.y+.32)); - float d=min(fr,ro); - return d; -} - - -// Camera path -vec3 path(float ti) { - ti*=1.5; - vec3 p=vec3(sin(ti),(1.-sin(ti*2.))*.5,-ti*5.)*.5; - return p; -} - -// Calc normals, and here is edge detection, set to variable "edge" - -float edge=0.; -vec3 normal(vec3 p) { - vec3 e = vec3(0.0,det*5.,0.0); - - float d1=de(p-e.yxx),d2=de(p+e.yxx); - float d3=de(p-e.xyx),d4=de(p+e.xyx); - float d5=de(p-e.xxy),d6=de(p+e.xxy); - float d=de(p); - edge=abs(d-0.5*(d2+d1))+abs(d-0.5*(d4+d3))+abs(d-0.5*(d6+d5));//edge finder - edge=min(1.,pow(edge,.55)*15.); - return normalize(vec3(d1-d2,d3-d4,d5-d6)); -} - - -// Used Nyan Cat code by mu6k, with some mods - -vec4 rainbow(vec2 p) -{ - float q = max(p.x,-0.1); - float s = sin(p.x*7.0+t*70.0)*0.08; - p.y+=s; - p.y*=1.1; - - vec4 c; - if (p.x>0.0) c=vec4(0,0,0,0); else - if (0.0/6.00.2) color.a=0.0; - return color; -} - - -// Raymarching and 2D graphics - -vec3 raymarch(in vec3 from, in vec3 dir) - -{ - edge=0.; - vec3 p, norm; - float d=100.; - float totdist=0.; - for (int i=0; idet && totdist<25.0) { - p=from+totdist*dir; - d=de(p); - det=detail*exp(.13*totdist); - totdist+=d; - } - else { break; } - } - vec3 col=vec3(0.); - p-=(det-d)*dir; - norm=normal(p); -#ifdef SHOWONLYEDGES - col=1.-vec3(edge); // show wireframe version -#else - col=(1.-abs(norm))*max(0.,1.-edge*.8); // set normal as color with dark edges -#endif - totdist=clamp(totdist,0.,26.); - dir.y-=.02; - float sunsize=7.-max(0.,texture2D(iChannel0,vec2(.6,.2)).x)*5.; // responsive sun size - float an=atan(dir.x,dir.y)+iGlobalTime*1.5; // angle for drawing and rotating sun - float s=pow(clamp(1.0-length(dir.xy)*sunsize-abs(.2-mod(an,.4)),0.,1.),.1); // sun - float sb=pow(clamp(1.0-length(dir.xy)*(sunsize-.2)-abs(.2-mod(an,.4)),0.,1.),.1); // sun border - float sg=pow(clamp(1.0-length(dir.xy)*(sunsize-4.5)-.5*abs(.2-mod(an,.4)),0.,1.),3.); // sun rays - float y=mix(.45,1.2,pow(smoothstep(0.,1.,.75-dir.y),2.))*(1.-sb*.5); // gradient sky - - // set up background with sky and sun - vec3 backg=vec3(0.5,0.,1.)*((1.-s)*(1.-sg)*y+(1.-sb)*sg*vec3(1.,.8,0.15)*3.); - backg+=vec3(1.,.9,.1)*s; - backg=max(backg,sg*vec3(1.,.9,.5)); - - col=mix(vec3(1.,.9,.3),col,exp(-.004*totdist*totdist));// distant fading to sun color - if (totdist>25.) col=backg; // hit background - col=pow(col,vec3(GAMMA))*BRIGHTNESS; - col=mix(vec3(length(col)),col,SATURATION); -#ifdef SHOWONLYEDGES - col=1.-vec3(length(col)); -#else - col*=vec3(1.,.9,.85); -#ifdef NYAN - dir.yx*=rot(dir.x); - vec2 ncatpos=(dir.xy+vec2(-3.+mod(-t,6.),-.27)); - vec4 ncat=nyan(ncatpos*5.); - vec4 rain=rainbow(ncatpos*10.+vec2(.8,.5)); - if (totdist>8.) col=mix(col,max(vec3(.2),rain.xyz),rain.a*.9); - if (totdist>8.) col=mix(col,max(vec3(.2),ncat.xyz),ncat.a*.9); -#endif -#endif - return col; -} - -// get camera position -vec3 move(inout vec3 dir) { - vec3 go=path(t); - vec3 adv=path(t+.7); - float hd=de(adv); - vec3 advec=normalize(adv-go); - float an=adv.x-go.x; an*=min(1.,abs(adv.z-go.z))*sign(adv.z-go.z)*.7; - dir.xy*=mat2(cos(an),sin(an),-sin(an),cos(an)); - an=advec.y*1.7; - dir.yz*=mat2(cos(an),sin(an),-sin(an),cos(an)); - an=atan(advec.x,advec.z); - dir.xz*=mat2(cos(an),sin(an),-sin(an),cos(an)); - return go; -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - vec2 uv = fragCoord.xy / iResolution.xy*2.-1.; - vec2 oriuv=uv; - uv.y*=iResolution.y/iResolution.x; - vec2 mouse=(iMouse.xy/iResolution.xy-.5)*3.; - if (iMouse.z<1.) mouse=vec2(0.,-0.05); - float fov=.9-max(0.,.7-iGlobalTime*.3); - vec3 dir=normalize(vec3(uv*fov,1.)); - dir.yz*=rot(mouse.y); - dir.xz*=rot(mouse.x); - vec3 from=origin+move(dir); - vec3 color=raymarch(from,dir); - #ifdef BORDER - color=mix(vec3(0.),color,pow(max(0.,.95-length(oriuv*oriuv*oriuv*vec2(1.05,1.1))),.3)); - #endif - fragColor = vec4(color,1.); -} diff --git a/visualization.shadertoy/resources/gameboy.frag.glsl b/visualization.shadertoy/resources/gameboy.frag.glsl deleted file mode 100644 index 8937987..0000000 --- a/visualization.shadertoy/resources/gameboy.frag.glsl +++ /dev/null @@ -1,90 +0,0 @@ -// Taken from https://www.shadertoy.com/view/XdlGzr - -// Created by inigo quilez - iq/2013 -// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. - -float text( vec2 p ) -{ - // trick for encoding fonts from CPU - p.x += 0.2*floor(10.0*(0.5+0.5*sin(iGlobalTime)))/10.0; - - float x = floor( p.x*100.0 ) - 23.0; - float y = floor( p.y*100.0 ) - 82.0; - - if( y<0.0 || y> 5.0) return 0.0; - if( x<0.0 || x>70.0) return 0.0; - - float v = 0.0; - - if( x>63.5 ) { v=12288.0; - if(y>2.5) v=30720.0; - if(y>3.5) v=52224.0; } - else if( x>47.5 ) { v=12408.0; - if(y>0.5) v=12492.0; - if(y>4.5) v=64632.0; } - else if( x>31.5 ) { v=64716.0; - if(y>0.5) v=49360.0; - if(y>1.5) v=49400.0; - if(y>2.5) v=63692.0; - if(y>3.5) v=49356.0; - if(y>4.5) v=64760.0; } - else if( x>15.5 ) { v=40184.0; - if(y>0.5) v=40092.0; - if(y>2.5) v=64668.0; - if(y>3.5) v=40092.0; - if(y>4.5) v=28920.0; } - else { v=30860.0; - if(y>0.5) v=40076.0; - if(y>1.5) v= 7308.0; - if(y>2.5) v=30972.0; - if(y>3.5) v=49292.0; - if(y>4.5) v=30860.0; } - - return floor( mod(v/pow(2.0,15.0-mod( x, 16.0 )), 2.0) ); -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - vec2 uv = fragCoord.xy / iResolution.xy; - vec2 uvo = uv; - - vec2 res = floor( 60.0*vec2(1.0,iResolution.y/iResolution.x) ); - - vec3 col = vec3(131.0, 145.0, 0.0); - if( uv.x>0.03 && uv.x<0.97 ) - { - uv.x = clamp( (uv.x-0.03)/0.94, 0.0, 1.0 ); - - vec2 iuv = floor( uv * res )/res; - - float f = 1.0-abs(-1.0+2.0*fract( uv.x * res.x )); - float g = 1.0-abs(-1.0+2.0*fract( uv.y * res.y )); - - float fft = texture2D( iChannel0, vec2(iuv.x,0.25) ).x; - fft = 0.8*fft*fft; - if( iuv.y0.1 && g>0.1 ) col = vec3(40.0,44.0,4.0); - if( f>0.5 && g>0.5 ) col = vec3(74.0,82.0,4.0); - } - - - float wave = texture2D( iChannel0, vec2(iuv.x*0.5,0.75) ).x; - if( abs(iuv.y-wave)<=(1.0/res.y) ) - { - col = vec3(185.0, 200.0, 90.0); - } - - float t = text( uvo ); - col = mix( col, vec3(40.0,44.0,4.0), t ); - } - else - { - float g = 1.0-abs(-1.0+2.0*fract( uv.y * res.y*1.5 )); - float f = 1.0-abs(-1.0+2.0*fract( uv.x * res.x + 0.5*floor(uv.y*res.y*1.5))); - - if( g<0.15 || f<0.15 ) col = vec3(40.0,44.0,4.0); - } - - fragColor = vec4( col/255.0,1.0 ); -} diff --git a/visualization.shadertoy/resources/io.frag.glsl b/visualization.shadertoy/resources/io.frag.glsl deleted file mode 100644 index da5f559..0000000 --- a/visualization.shadertoy/resources/io.frag.glsl +++ /dev/null @@ -1,69 +0,0 @@ -// Taken from https://www.shadertoy.com/view/XsfGDS -// I/O fragment shader by movAX13h, August 2013 - -#define SHOW_BLOCKS - -float rand(float x) -{ - return fract(sin(x) * 4358.5453123); -} - -float rand(vec2 co) -{ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5357); -} - -float box(vec2 p, vec2 b, float r) -{ - return length(max(abs(p)-b,0.0))-r; -} - -float sampleMusic() -{ - return 0.5 * ( - //texture2D( iChannel0, vec2( 0.01, 0.25 ) ).x + - //texture2D( iChannel0, vec2( 0.07, 0.25 ) ).x + - texture2D( iChannel0, vec2( 0.15, 0.25 ) ).x + - texture2D( iChannel0, vec2( 0.30, 0.25 ) ).x); -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - const float speed = 0.7; - const float ySpread = 1.6; - const int numBlocks = 70; - - float pulse = sampleMusic(); - - vec2 uv = fragCoord.xy / iResolution.xy - 0.5; - float aspect = iResolution.x / iResolution.y; - vec3 baseColor = uv.x > 0.0 ? vec3(0.0,0.3, 0.6) : vec3(0.6, 0.0, 0.3); - - vec3 color = pulse*baseColor*0.5*(0.9-cos(uv.x*8.0)); - uv.x *= aspect; - - for (int i = 0; i < numBlocks; i++) - { - float z = 1.0-0.7*rand(float(i)*1.4333); // 0=far, 1=near - float tickTime = iGlobalTime*z*speed + float(i)*1.23753; - float tick = floor(tickTime); - - vec2 pos = vec2(0.6*aspect*(rand(tick)-0.5), sign(uv.x)*ySpread*(0.5-fract(tickTime))); - pos.x += 0.24*sign(pos.x); // move aside - if (abs(pos.x) < 0.1) pos.x++; // stupid fix; sign sometimes returns 0 - - vec2 size = 1.8*z*vec2(0.04, 0.04 + 0.1*rand(tick+0.2)); - float b = box(uv-pos, size, 0.01); - float dust = z*smoothstep(0.22, 0.0, b)*pulse*0.5; - #ifdef SHOW_BLOCKS - float block = 0.2*z*smoothstep(0.002, 0.0, b); - float shine = 0.6*z*pulse*smoothstep(-0.002, b, 0.007); - color += dust*baseColor + block*z + shine; - #else - color += dust*baseColor; - #endif - } - - color -= rand(uv)*0.04; - fragColor = vec4(color, 1.0); -} diff --git a/visualization.shadertoy/resources/kaleidoscopevisualizer.frag.glsl b/visualization.shadertoy/resources/kaleidoscopevisualizer.frag.glsl deleted file mode 100644 index 288856f..0000000 --- a/visualization.shadertoy/resources/kaleidoscopevisualizer.frag.glsl +++ /dev/null @@ -1,104 +0,0 @@ -// Taken from https://www.shadertoy.com/view/ldsXWn# -// ---- change here kaleidoscope size and toggle on/off---- -const float USE_KALEIDOSCOPE = 1.0; -const float NUM_SIDES = 8.0; - -// ---- Change the amount at which the visualizer reacts to music (per song different settings work best) ---- -const float MIN_SIZE = 0.01; -const float REACT_INTENSITY = 0.3; -const float BASS_INTENSITY = 1.1; -const float BASS_BASE_HEIGHT = .0; -const float ZOOM_FACTOR = 0.5; - -// math const -const float PI = 3.14159265359; -const float DEG_TO_RAD = PI / 180.0; - -// -4/9(r/R)^6 + (17/9)(r/R)^4 - (22/9)(r/R)^2 + 1.0 -float field( vec2 p, vec2 center, float r ) { - float d = length( p - center ) / r; - - float t = d * d; - float tt = t * d; - float ttt = tt * d; - - float v = - ( - 10.0 / 9.0 ) * ttt + - ( 17.0 / 9.0 ) * tt + - ( -22.0 / 9.0 ) * t + - 1.0; - - return clamp( v, 0.0, 1.0 ); -} - -vec2 Kaleidoscope( vec2 uv, float n, float bias ) { - float angle = PI / n; - - float r = length( uv*.5 ); - float a = atan( uv.y, uv.x ) / angle; - - a = mix( fract( a ), 1.0 - fract( a ), mod( floor( a ), 2.0 ) ) * angle; - - return vec2( cos( a ), sin( a ) ) * r; -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - vec2 ratio = iResolution.xy / min( iResolution.x, iResolution.y ); - vec2 uv = ( fragCoord.xy * 2.0 - iResolution.xy ) / min( iResolution.x, iResolution.y ); - - // --- Kaleidoscope --- - uv = mix( uv, Kaleidoscope( uv, NUM_SIDES, iChannelTime[1]*10. ), USE_KALEIDOSCOPE ); - - uv *= ZOOM_FACTOR+(BASS_INTENSITY)* (texture2D(iChannel0, vec2(.01,0)).r); - - vec3 final_color = vec3( 0.0 ); - float final_density = 0.0; - for ( int i = 0; i < 128; i++ ) { - vec4 noise = texture2D( iChannel1, vec2( float( i ) + 0.5, 0.5 ) / 256.0 ); - vec4 noise2 = texture2D( iChannel1, vec2( float( i ) + 0.5, 9.5 ) / 256.0 ); - - - //sound loudness to intensity - float velintensity = texture2D(iChannel0, vec2(1.0+uv.x,0)).r; - - // velocity - vec2 vel = -abs(noise.xy) * 3.0 +vec2( .003*-velintensity )-vec2(2.0); - vel*=-.5; - - // center - vec2 pos = noise.xy; - pos += iChannelTime[1] * vel * 0.2; - pos = mix( fract( pos ),fract( pos ), mod( floor( pos ), 2.0 ) ); - - //sound loudness to intensity - float intensity = texture2D(iChannel0, vec2(pos.y,0)).r; - - // remap to screen - pos = ( pos * 2.0 - 1.0 ) * ratio; - - - - // radius - float radius = clamp( noise.w, 0.3, 0.8 ); - radius *= 3.*intensity; - //radius += 0.5; - radius *= radius * 0.4; - radius = clamp(radius, MIN_SIZE*abs(-pos.x), REACT_INTENSITY); - - // color - vec3 color = noise2.xyz; - - // density - float density = field( uv, pos, radius ); - - // accumulate - final_density += density; - final_color += density * color; - } - - final_density = clamp( final_density - 0.1, 0.0, 1.0 ); - final_density = pow( final_density, 3.0 ); - - fragColor = vec4( final_color * final_density, final_density ); -} diff --git a/visualization.shadertoy/resources/ledspectrum.frag.glsl b/visualization.shadertoy/resources/ledspectrum.frag.glsl deleted file mode 100644 index a9fe25d..0000000 --- a/visualization.shadertoy/resources/ledspectrum.frag.glsl +++ /dev/null @@ -1,57 +0,0 @@ -// Taken from https://www.shadertoy.com/view/Msl3zr - -const float PI = 3.14159; - -// http://github.prideout.net/barrel-distortion/ -vec2 distort(vec2 p, float power) -{ - float a = atan(p.y, p.x); - float r = length(p); - r = pow(r, power); - return vec2(r * cos(a), r*sin(a)); - //return vec2((a / PI), r*2.0-1.0); // polar -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - // create pixel coordinates - vec2 uv = fragCoord.xy / iResolution.xy; - - // distort - float bass = texture2D( iChannel0, vec2(0, 0) ).x; - uv = distort(uv*2.0-1.0, 0.5+bass)*0.5+0.5; - - // quantize coordinates - const float bands = 20.0; - const float segs = 20.0; - vec2 p; - p.x = floor(uv.x*bands)/bands; - p.y = floor(uv.y*segs)/segs; - - // read frequency data from first row of texture - float fft = texture2D( iChannel0, vec2(p.x,0.0) ).x; - - // led color - vec3 color = mix(vec3(0.0, 2.0, 0.0), vec3(2.0, 0.0, 0.0), sqrt(uv.y)); - - // mask for bar graph - float mask = (p.y < fft) ? 1.0 : 0.0; - - // led shape - vec2 d = fract((uv - p)*vec2(bands, segs)) - 0.5; - float led = smoothstep(0.5, 0.3, abs(d.x)) * - smoothstep(0.5, 0.3, abs(d.y)); - vec3 ledColor = led*color*mask; - - // second texture row is the sound wave - float wave = texture2D( iChannel0, vec2(uv.x, 0.75) ).x; - vec3 waveColor = vec3(0.001, 0.01, 0.04) / abs(wave - uv.y); - - // output final color - //fragColor = vec4(vec3(fft),1.0); - //fragColor = vec4(d, 0.0, 1.0); - //fragColor = vec4(ledColor, 1.0); - //fragColor = vec4(waveColor, 1.0); - fragColor = vec4(ledColor + waveColor, 1.0); -} - diff --git a/visualization.shadertoy/resources/shaders/2Dspectrum.frag.glsl b/visualization.shadertoy/resources/shaders/2Dspectrum.frag.glsl new file mode 100644 index 0000000..2e90882 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/2Dspectrum.frag.glsl @@ -0,0 +1,37 @@ +/* +2D LED Spectrum - Visualiser - https://www.shadertoy.com/view/Mlj3WV# +Based on Led Spectrum Analiser by: simesgreen - 27th February, 2013 - https://www.shadertoy.com/view/Msl3zr +2D LED Spectrum by: uNiversal - 27th May, 2015 +Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. +*/ + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + // create pixel coordinates + vec2 uv = fragCoord.xy / iResolution.xy; + + // quantize coordinates + const float bands = 30.0; + const float segs = 40.0; + vec2 p; + p.x = floor(uv.x*bands)/bands; + p.y = floor(uv.y*segs)/segs; + + // read frequency data from first row of texture + float fft = texture2D( iChannel0, vec2(p.x,0.0) ).x; + + // led color + vec3 color = mix(vec3(0.0, 2.0, 0.0), vec3(2.0, 0.0, 0.0), sqrt(uv.y)); + + // mask for bar graph + float mask = (p.y < fft) ? 1.0 : 0.1; + + // led shape + vec2 d = fract((uv - p)*vec2(bands, segs)) - 0.5; + float led = smoothstep(0.5, 0.35, abs(d.x)) * + smoothstep(0.5, 0.35, abs(d.y)); + vec3 ledColor = led*color*mask; + + // output final color + fragColor = vec4(ledColor, 1.0); +} diff --git a/visualization.shadertoy/resources/audioeclipse.frag.glsl b/visualization.shadertoy/resources/shaders/audioeclipse.frag.glsl similarity index 62% rename from visualization.shadertoy/resources/audioeclipse.frag.glsl rename to visualization.shadertoy/resources/shaders/audioeclipse.frag.glsl index 0a2fc26..5d3ac02 100644 --- a/visualization.shadertoy/resources/audioeclipse.frag.glsl +++ b/visualization.shadertoy/resources/shaders/audioeclipse.frag.glsl @@ -1,6 +1,6 @@ // see: https://www.shadertoy.com/view/MdsXWM -const float dots = 20.; //number of lights +const float dots = 40.; //number of lights const float radius = .25; //radius of light ring const float brightness = 0.02; @@ -10,36 +10,35 @@ vec3 hsv2rgb(vec3 c){ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } - + void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 p=(fragCoord.xy-.5*iResolution.xy)/min(iResolution.x,iResolution.y); vec3 c=vec3(0,0,0.1); //background color - + for(float i=0.;i 1.0) uv.x = 2.0 - uv.x; + #endif + + + //four distortion patterns + float coord1 = sin(uv.x + hwf) - cos(uv.y); + float coord2 = sin(1.0 - uv.x + hwf) - sin(uv.y * 3.0); + //float coord3 = cos(uv.x+sin(0.2*iTime)) - sin(2.5*uv.y - wf); + float coord4 = mix(coord1, coord2,hwf); + float coord5 = mix(coord1, coord2, beat); + + float coorda = mix(coord1, coord2, 0.5 + 0.5 *sin(iTime*0.7)); + float coordb = mix(coord5, coord4, 0.5 + 0.5 *sin(iTime*0.5)); + + //mix distortions based on time + float coord = mix(coorda, coordb, 0.5 + 0.5 *sin(iTime*0.3)); + + //distort the spectrum image using the above coords + float j = (texture(iChannel0, vec2(abs(coord),0.0)).x - 0.5) * 2.0; + + //greyscale -> color with a lot of dot products + float fac1 = dot(vec3(uv.x,uv.y,j),sun); + float fac2 = dot(vec3(uv.y,j,uv.x),sun); + float fac3 = dot(vec3(j,uv.x,uv.y),sun); + bg_color = vec3(fac1,fac2,fac3); + + + //extract some info about wave shape + float w1 = texture(iChannel0, vec2(0.1,0.0)).x; + float w2 = texture(iChannel0, vec2(0.2,0.0)).x; + float w3 = texture(iChannel0, vec2(0.4,0.0)).x; + float w4 = texture(iChannel0, vec2(0.8,0.0)).x; + + //save screenspace for later + vec2 ouv = uv; + + + float wave_width = 0.0; + float wave_amp = 0.0; + + //rescale to aspect-aware [-1, 1] + uv = -1.0 + 2.0 * uv; + uv.y *= iResolution.y/iResolution.x; + + #ifdef ALT_MODE + //bend-spin-stretch the coord system based on wave shape + float theta = (w1 - w2 + w3 - w4) * 3.14; + uv = uv*mat2(cos(theta * 0.2),-sin(theta * 0.3),sin(theta * 0.5),cos(theta * 0.7)); + #endif + + //for polar calculations + float rad = length(uv) - 0.3; + + float h; + + //slightly based on Waves by bonniem + for(float i = 0.0; i < 10.0; i++) { + //build a simple trig series based on wave shape + //note that waves are in rectangular coords + h = sin(uv.x*8.0+iTime)*0.2*w1+ + sin(uv.x*16.0-2.0*iTime)*0.2*w2 + + sin(uv.x*32.0+3.0*iTime)*0.2*w3 + + sin(uv.x*64.0-4.0*iTime)*0.2*w4; + rad += h * 0.4; + //find the wave section's width in polar coords + wave_width = abs(1.0 / (100.0 * rad)); + wave_amp += wave_width; + } + + //color waves based on sonar shape and screen position + wave_color = vec3(0.2 + w2*1.5, 0.1 + w4*2.0 + uv.y*0.1, 0.1 + w3*2.0+uv.x*0.1); + + #ifdef ALT_MODE + //fade with beat + wave_amp *= beat * 3.0; + #endif + + //modulate with waveform. doesn't do much. + wave_amp *= hwf*2.0; + + + //fade bg in from 0 to 5 sec + final_color = bg_color*smoothstep(0.0,5.0,iChannelTime[0]); + final_color += 0.12*wave_color*wave_amp; + + //postproc code from iq :) + #ifdef POST_PROC + //gamma. remove this for a solarized look + final_color = pow( clamp( final_color, 0.0, 1.0 ), vec3(1.7) ); + + //contrast + final_color = final_color*0.3 + 0.7*final_color*final_color*(3.0-2.0*final_color); + #endif + + //vignette + final_color *= 0.5 + 0.5*pow( 16.0*ouv.x*ouv.y*(1.0-ouv.x)*(1.0-ouv.y), 0.2); + + #ifdef ALT_MODE +// final_color = mix(final_color, vec3(noise), distort * 10.0); + final_color += vec3(noise) * distort * 10.0; + #endif + + fragColor = vec4(final_color, 1.0); +} +/* +split into vwf and hwf +use vwf to self-modulate a texture for distort phase +distort uv of beginning with vwf +text! +simple float arrays for each line, stored at half or less res +use +1 for words, -1 for outline, inbet for glow effect +eg 0.0, 0.1, 0.3, 0.5, 0.9, -1.0, -1.0, 1.0, 1.0... +use timecodes of channel to get a time offset for text anim, +a text centre, and a lyric file. +*/ + +/* +Lean out in the window, take a look and see +Metal moons are dreaming both of you and me +Staring in the sky they are for days and weeks +Painting cubes and ribbons like in demoscene + +Circuit-bent, eight-bit made, but how is your heart? +pixel pelt, low-fi brain, that makes you so smart +beeps and voice, glitch and noise, you're not a machine any more + +Coding every minute, coding every bit +parties you can visit, people you can meet +turn on your computer, make a brand new beat +dance it like a human with your robot feet + +What is high definition for +when you still play on Commodore? + +Any more +*/ diff --git a/visualization.shadertoy/resources/shaders/audiovisual.frag.glsl b/visualization.shadertoy/resources/shaders/audiovisual.frag.glsl new file mode 100644 index 0000000..4758513 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/audiovisual.frag.glsl @@ -0,0 +1,25 @@ +// Taken from https://www.shadertoy.com/view/MsBSzw# + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 p = (fragCoord.xy-.5*iResolution.xy)/min(iResolution.x,iResolution.y); + vec3 c = vec3(0.0); + vec2 uv = fragCoord.xy / iResolution.xy; + float wave = texture( iChannel0, vec2(uv.x,0.75) ).x; + + for(int i = 1; i<20; i++) + { + float time = 2.*3.14*float(i)/20.* (iTime*.9); + float x = sin(time)*1.8*smoothstep( 0.0, 0.15, abs(wave - uv.y)); + float y = sin(.5*time) *smoothstep( 0.0, 0.15, abs(wave - uv.y)); + y*=.5; + vec2 o = .4*vec2(x*cos(iTime*.5),y*sin(iTime*.3)); + float red = fract(time); + float green = 1.-red; + c+=0.016/(length(p-o))*vec3(red,green,sin(iTime)); + } + fragColor = vec4(c,1.0); +} +//2014 - Passion +//References - https://www.shadertoy.com/view/Xds3Rr +// - tokyodemofest.jp/2014/7lines/index.html diff --git a/visualization.shadertoy/resources/shaders/beatingcircles.frag.glsl b/visualization.shadertoy/resources/shaders/beatingcircles.frag.glsl new file mode 100644 index 0000000..130f7c3 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/beatingcircles.frag.glsl @@ -0,0 +1,35 @@ +// Taken from https://www.shadertoy.com/view/4d23Ww + +const float Pi = 3.14159; +float beat = 0.; + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + float ct = iChannelTime[0]; + if ((ct > 8.0 && ct < 33.5) + || (ct > 38.0 && ct < 88.5) + || (ct > 93.0 && ct < 194.5)) + beat = pow(sin(ct*3.1416*3.78+1.9)*0.5+0.5,15.0)*0.1; + + float scale = iResolution.y / 50.0; + float ring = 20.0; + float radius = iResolution.x*1.0; + float gap = scale*.5; + vec2 pos = fragCoord.xy - iResolution.xy*.5; + + float d = length(pos); + + // Create the wiggle + d += beat*2.0*(sin(pos.y*0.25/scale+iTime*cos(ct))*sin(pos.x*0.25/scale+iTime*.5*cos(ct)))*scale*5.0; + + // Compute the distance to the closest ring + float v = mod(d + radius/(ring*2.0), radius/ring); + v = abs(v - radius/(ring*2.0)); + + v = clamp(v-gap, 0.0, 1.0); + + d /= radius; + vec3 m = fract((d-1.0)*vec3(ring*-.5, -ring, ring*.25)*0.5); + + fragColor = vec4(m*v, 1.0); +} diff --git a/visualization.shadertoy/resources/shaders/bpm.frag.glsl b/visualization.shadertoy/resources/shaders/bpm.frag.glsl new file mode 100644 index 0000000..bf7d837 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/bpm.frag.glsl @@ -0,0 +1,30 @@ +// Taken from https://www.shadertoy.com/view/ldB3D1 + +// Created by inigo quilez - iq/2013 +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + +// An example showing the use of iChannelData[] in order to synchronize an aimation + +#define BPM 128.0 + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = -1.0+2.0*fragCoord.xy / iResolution.xy; + uv.x *= iResolution.x/iResolution.y; + + vec3 col = vec3(0.0); + + float h = fract( 0.25 + 0.5*iChannelTime[0]*BPM/60.0 ); + float f = 1.0-smoothstep( 0.0, 1.0, h ); + f *= smoothstep( 4.5, 4.51, iChannelTime[0] ); + float r = length(uv-0.0) + 0.2*cos(25.0*h)*exp(-4.0*h); + f = pow(f,0.5)*(1.0-smoothstep( 0.5, 0.55, r) ); + float rn = r/0.55; + col = mix( col, vec3(0.4+1.5*rn,0.1+rn*rn,0.50)*rn, f ); + + + col = mix( col, vec3(1.0), smoothstep( 0.0, 3.0, iChannelTime[0] )*exp( -1.00*max(0.0,iChannelTime[0]- 2.5)) ); + col = mix( col, vec3(1.0), smoothstep( 16.0, 18.0, iChannelTime[0] )*exp( -0.75*max(0.0,iChannelTime[0]-19.0)) ); + + fragColor = vec4(col,1.0); +} diff --git a/visualization.shadertoy/resources/shaders/circlewave.frag.glsl b/visualization.shadertoy/resources/shaders/circlewave.frag.glsl new file mode 100644 index 0000000..3bc71f7 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/circlewave.frag.glsl @@ -0,0 +1,52 @@ +// Taken from https://www.shadertoy.com/view/Xsf3WB + +const float tau = 6.28318530717958647692; + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = (fragCoord.xy - iResolution.xy*.5)/iResolution.x; + + uv = vec2(abs(atan(uv.x,uv.y)/(.5*tau)),length(uv)); + + // adjust frequency to look pretty + uv.x *= 1.0/2.0; + + float seperation = 0.06*(1.0-iMouse.x/iResolution.x); + + vec3 wave = vec3(0.0); + const int n = 60; + for ( int i=0; i < n; i++ ) + { +/* float u = uv.x*255.0; + float f = fract(u); + f = f*f*(3.0-2.0*f); + u = floor(u); + float sound = mix( texture( iChannel0, vec2((u+.5)/256.0,.75) ).x, texture( iChannel0, vec2((u+1.5)/256.0,.75) ).x, f );*/ + float sound = texture( iChannel0, vec2(uv.x,.75) ).x; + + // choose colour from spectrum + float a = .9*float(i)*tau/float(n)-.6; + vec3 phase = smoothstep(-1.0,.5,vec3(cos(a),cos(a-tau/3.0),cos(a-tau*2.0/3.0))); + + wave += phase*smoothstep(4.0/640.0, 0.0, abs(uv.y - sound*.3)); + uv.x += seperation/float(n); + } + wave *= 3.0/float(n); + + vec3 col = vec3(0); + col.z += texture( iChannel0, vec2(.000,.25) ).x; + col.zy += texture( iChannel0, vec2(.125,.25) ).xx*vec2(1.5,.5); + col.zy += texture( iChannel0, vec2(.250,.25) ).xx; + col.zy += texture( iChannel0, vec2(.375,.25) ).xx*vec2(.5,1.5); + col.y += texture( iChannel0, vec2(.500,.25) ).x; + col.yx += texture( iChannel0, vec2(.625,.25) ).xx*vec2(1.5,.5); + col.yx += texture( iChannel0, vec2(.750,.25) ).xx; + col.yx += texture( iChannel0, vec2(.875,.25) ).xx*vec2(.5,1.5); + col.x += texture( iChannel0, vec2(1.00,.25) ).x; + col /= vec3(4.0,7.0,4.0); + + // vignetting + col *= smoothstep( 1.2, 0.0, uv.y ); + + fragColor = vec4(wave+col,1); +} diff --git a/visualization.shadertoy/resources/shaders/circuits.frag.glsl b/visualization.shadertoy/resources/shaders/circuits.frag.glsl new file mode 100644 index 0000000..72877b9 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/circuits.frag.glsl @@ -0,0 +1,59 @@ +// Taken from https://www.shadertoy.com/view/XlX3Rj# + +// This content is under the MIT License. + +#define time iTime*.02 + + +#define width .005 +float zoom = .18; + +float shape=0.; +vec3 color=vec3(0.),randcol; + +void formula(vec2 z, float c) { + float minit=0.; + float o,ot2,ot=ot2=1000.; + for (int i=0; i<9; i++) { + z=abs(z)/clamp(dot(z,z),.1,.5)-c; + float l=length(z); + o=min(max(abs(min(z.x,z.y)),-l+.25),abs(l-.25)); + ot=min(ot,o); + ot2=min(l*.1,ot2); + minit=max(minit,float(i)*(1.-abs(sign(ot-o)))); + } + minit+=1.; + float w=width*minit*2.; + float circ=pow(max(0.,w-ot2)/w,6.); + shape+=max(pow(max(0.,w-ot)/w,.25),circ); + vec3 col=normalize(.1+texture(iChannel1,vec2(minit*.1)).rgb); + color+=col*(.4+mod(minit/9.-time*10.+ot2*2.,1.)*1.6); + color+=vec3(1.,.7,.3)*circ*(10.-minit)*3.*smoothstep(0.,.5,.15+texture(iChannel0,vec2(.0,1.)).x-.5); +} + + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 pos = fragCoord.xy / iResolution.xy - .5; + pos.x*=iResolution.x/iResolution.y; + vec2 uv=pos; + float sph = length(uv); sph = sqrt(1. - sph*sph)*1.5; + uv=normalize(vec3(uv,sph)).xy; + float a=time+mod(time,1.)*.5; + vec2 luv=uv; + float b=a*5.48535; + uv*=mat2(cos(b),sin(b),-sin(b),cos(b)); + uv+=vec2(sin(a),cos(a*.5))*8.; + uv*=zoom; + float pix=.5/iResolution.x*zoom/sph; + float dof=max(1.,(10.-mod(time,1.)/.01)); + float c=1.5+mod(floor(time),6.)*.125; + for (int aa=0; aa<36; aa++) { + vec2 aauv=floor(vec2(float(aa)/6.,mod(float(aa),6.))); + formula(uv+aauv*pix*dof,c); + } + shape/=36.; color/=36.; + vec3 colo=mix(vec3(.15),color,shape)*(1.-length(pos))*min(1.,abs(.5-mod(time+.5,1.))*10.); + colo*=vec3(1.2,1.1,1.0); + fragColor = vec4(colo,1.0); +} diff --git a/visualization.shadertoy/resources/shaders/coloredbars.frag.glsl b/visualization.shadertoy/resources/shaders/coloredbars.frag.glsl new file mode 100644 index 0000000..bd30f10 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/coloredbars.frag.glsl @@ -0,0 +1,115 @@ +// Taken from https://www.shadertoy.com/view/XsBXW1# + +#define M_PI 3.1415926535897932384626433832795 +#define MAXDISTANCE 32. +#define MAXITERATIONS 32 +#define PRECISION 1e-3 + +float rand(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +float plane(vec3 p, float z) { + return p.z - z; +} + +float udBox(vec3 p, vec3 b, out int object) { + float tme = iTime*2.0 + 1024.0; + + p.y += tme / 2.0; + float rowOffset = rand(vec2(0, floor(p.y/2.0))); + p.x += tme * (2. * rowOffset + texture(iChannel0, vec2(rowOffset,.25)).x/500.); + + object = int(6. * mod(p.x/(32.*6.), 1.)) + 2; + + vec2 c = vec2(32, 2); + p.xy = mod(p.xy, c)-.5*c; + return length(max(abs(p)-b,0.)); +} + +float getMap(vec3 p, out int object) { + float distance = MAXDISTANCE; + float tempDist; + int tempObject; + + distance = plane(p, 0.0); + object = 1; + + tempDist = udBox(p, vec3(12.0, 0.5, 0.5), tempObject); + if (tempDist <= distance) { + distance = tempDist; + object = tempObject; + } + return distance * 0.5; +} + +vec2 castRay(vec3 origin, vec3 direction, out int object) { + float distance = rand(vec2(direction.y * iTime, direction.x)) * 6.0; + float delta = 0.0; + object = 0; + + for (int i = 0; i < MAXITERATIONS; i++) { + vec3 p = origin + direction * distance; + + delta = getMap(p, object); + + distance += delta; + if (delta < PRECISION) { + return vec2(distance, float(i)); + } + if (distance > MAXDISTANCE) { + object = 0; + return vec2(distance, float(i)); + } + } + + object = 0; + return vec2(distance, MAXITERATIONS); +} + +vec3 drawScene(vec3 origin, vec3 direction) { + vec3 color = vec3(0.0, 0.0, 0.0); + int object = 0; + + vec2 ray = castRay(origin, direction, object); + + if (object != 0) { + if (object == 1) { + color = vec3(1.0, 1.0, 1.0); + } + else if (object == 2) { + color = vec3(1.0, 0.3, 0.3); + } + else if (object == 3) { + color = vec3(0.3, 1.0, 0.3); + } + else if (object == 4) { + color = vec3(0.3, 0.3, 1.0); + } + else if (object == 5) { + color = vec3(1.0, 1.0, 0.3); + } + else if (object == 6) { + color = vec3(0.3, 1.0, 1.0); + } + else if (object == 7) { + color = vec3(1.0, 0.3, 1.0); + } + } + return mix(color, vec3(0.0, 0.0, 0.0), ray.y/float(MAXITERATIONS)); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) { + vec2 p = (fragCoord.xy / iResolution.xy) * 2.0 - 1.0; + float aspect = iResolution.x / iResolution.y; + p.x *= aspect; + + vec3 color = vec3(0.0, 0.0, 0.0); + vec3 origin = vec3(0.0, 0.0, 12.0); + vec3 direction = normalize(vec3(p.x, p.y, -1.0)); + direction.xy = mat2(cos(M_PI/4.0), sin(M_PI/4.0), -sin(M_PI/4.0), cos(M_PI/4.0)) * direction.xy; + + color = drawScene(origin, direction); + + fragColor = vec4(color, 1.0); +} diff --git a/visualization.shadertoy/resources/cubescape.frag.glsl b/visualization.shadertoy/resources/shaders/cubescape.frag.glsl similarity index 62% rename from visualization.shadertoy/resources/cubescape.frag.glsl rename to visualization.shadertoy/resources/shaders/cubescape.frag.glsl index 7a098d4..8d47030 100644 --- a/visualization.shadertoy/resources/cubescape.frag.glsl +++ b/visualization.shadertoy/resources/shaders/cubescape.frag.glsl @@ -5,7 +5,7 @@ //--------------------------------- -//#define ANTIALIAS +#define ANTIALIAS 2 float hash( float n ) { return fract(sin(n)*13.5453123); } @@ -18,11 +18,11 @@ float dbox( vec3 p, vec3 b, float r ) vec4 texcube( sampler2D sam, in vec3 p, in vec3 n ) { - vec4 x = texture2D( sam, p.yz ); - vec4 y = texture2D( sam, p.zx ); - vec4 z = texture2D( sam, p.yx ); + vec4 x = texture( sam, p.yz ); + vec4 y = texture( sam, p.zx ); + vec4 z = texture( sam, p.yx ); vec3 a = abs(n); - return (x*a.x + y*a.y + z*a.z) / (a.x + a.y + a.z); + return (x*a.x + y*a.y + z*a.z) / (a.x + a.y + a.z); } //--------------------------------- @@ -31,15 +31,15 @@ float freqs[4]; vec3 mapH( in vec2 pos ) { - vec2 fpos = fract( pos ); - vec2 ipos = floor( pos ); - + vec2 fpos = fract( pos ); + vec2 ipos = floor( pos ); + float f = 0.0; - float id = hash( ipos.x + ipos.y*57.0 ); - f += freqs[0] * clamp(1.0 - abs(id-0.20)/0.30, 0.0, 1.0 ); - f += freqs[1] * clamp(1.0 - abs(id-0.40)/0.30, 0.0, 1.0 ); - f += freqs[2] * clamp(1.0 - abs(id-0.60)/0.30, 0.0, 1.0 ); - f += freqs[3] * clamp(1.0 - abs(id-0.80)/0.30, 0.0, 1.0 ); + float id = hash( ipos.x + ipos.y*57.0 ); + f += freqs[0] * clamp(1.0 - abs(id-0.20)/0.30, 0.0, 1.0 ); + f += freqs[1] * clamp(1.0 - abs(id-0.40)/0.30, 0.0, 1.0 ); + f += freqs[2] * clamp(1.0 - abs(id-0.60)/0.30, 0.0, 1.0 ); + f += freqs[3] * clamp(1.0 - abs(id-0.80)/0.30, 0.0, 1.0 ); f = pow( clamp( f, 0.0, 1.0 ), 2.0 ); float h = 2.5*f; @@ -49,68 +49,45 @@ vec3 mapH( in vec2 pos ) vec3 map( in vec3 pos ) { - vec2 p = fract( pos.xz ); + vec2 p = fract( pos.xz ); vec3 m = mapH( pos.xz ); - float d = dbox( vec3(p.x-0.5,pos.y-0.5*m.x,p.y-0.5), vec3(0.3,m.x*0.5,0.3), 0.1 ); + float d = dbox( vec3(p.x-0.5,pos.y-0.5*m.x,p.y-0.5), vec3(0.3,m.x*0.5,0.3), 0.1 ); return vec3( d, m.yz ); } const float surface = 0.001; -#if 0 -vec3 trace( in vec3 ro, in vec3 rd, in float startf, in float maxd ) -{ - float s = surface*2.0; - float t = startf; - - float sid = -1.0; - float alt = 0.0; - for( int i=0; i<128; i++ ) - { - if( smaxd ) break; - t += 0.15*s; - vec3 res = map( ro + rd*t ); - s = res.x; - sid = res.y; - alt = res.z; - } - if( t>maxd ) sid = -1.0; - return vec3( t, sid, alt ); -} - -#else - vec3 trace( vec3 ro, in vec3 rd, in float tmin, in float tmax ) { ro += tmin*rd; - vec2 pos = floor(ro.xz); + vec2 pos = floor(ro.xz); vec3 rdi = 1.0/rd; vec3 rda = abs(rdi); - vec2 rds = sign(rd.xz); - vec2 dis = (pos-ro.xz+ 0.5 + rds*0.5) * rdi.xz; - - vec3 res = vec3( -1.0 ); + vec2 rds = sign(rd.xz); + vec2 dis = (pos-ro.xz+ 0.5 + rds*0.5) * rdi.xz; + + vec3 res = vec3( -1.0 ); // traverse regular grid (in 2D) - vec2 mm = vec2(0.0); - for( int i=0; i<28; i++ ) - { + vec2 mm = vec2(0.0); + for( int i=0; i<28; i++ ) + { vec3 cub = mapH( pos ); #if 1 vec2 pr = pos+0.5-ro.xz; - vec2 mini = (pr-0.5*rds)*rdi.xz; - float s = max( mini.x, mini.y ); + vec2 mini = (pr-0.5*rds)*rdi.xz; + float s = max( mini.x, mini.y ); if( (tmin+s)>tmax ) break; #endif // intersect box - vec3 ce = vec3( pos.x+0.5, 0.5*cub.x, pos.y+0.5 ); + vec3 ce = vec3( pos.x+0.5, 0.5*cub.x, pos.y+0.5 ); vec3 rb = vec3(0.3,cub.x*0.5,0.3); vec3 ra = rb + 0.12; - vec3 rc = ro - ce; + vec3 rc = ro - ce; float tN = maxcomp( -rdi*rc - rda*ra ); float tF = maxcomp( -rdi*rc + rda*ra ); if( tN < tF )//&& tF > 0.0 ) @@ -131,20 +108,18 @@ vec3 trace( vec3 ro, in vec3 rd, in float tmin, in float tmax ) break; } - } + } - // step to next cell - mm = step( dis.xy, dis.yx ); - dis += mm*rda.xz; + mm = step( dis.xy, dis.yx ); + dis += mm*rda.xz; pos += mm*rds; - } + } res.x += tmin; - return res; + return res; } -#endif float softshadow( in vec3 ro, in vec3 rd, in float mint, in float maxt, in float k ) @@ -165,9 +140,9 @@ vec3 calcNormal( in vec3 pos, in float t ) { vec2 e = vec2(1.0,-1.0)*surface*t; return normalize( e.xyy*map( pos + e.xyy ).x + - e.yyx*map( pos + e.yyx ).x + - e.yxy*map( pos + e.yxy ).x + - e.xxx*map( pos + e.xxx ).x ); + e.yyx*map( pos + e.yyx ).x + + e.yxy*map( pos + e.yxy ).x + + e.xxx*map( pos + e.xxx ).x ); } const vec3 light1 = vec3( 0.70, 0.52, -0.45 ); @@ -192,35 +167,34 @@ vec2 boundingVlume( vec2 tminmax, in vec3 ro, in vec3 rd ) return tminmax; } - vec3 doLighting( in vec3 col, in float ks, in vec3 pos, in vec3 nor, in vec3 rd ) { - vec3 ldif = pos - lpos; + vec3 ldif = lpos - pos; float llen = length( ldif ); ldif /= llen; - float con = dot(-light1,ldif); - float occ = mix( clamp( pos.y/4.0, 0.0, 1.0 ), 1.0, max(0.0,nor.y) ); + float con = dot( light1,ldif); + float occ = mix( clamp( pos.y/4.0, 0.0, 1.0 ), 1.0, max(0.0,nor.y) ); vec2 sminmax = vec2(0.01, 5.0); - //sminmax = boundingVlume( sminmax, pos, -ldif ); - float sha = softshadow( pos, -ldif, sminmax.x, sminmax.y, 32.0 );; - + + float sha = softshadow( pos, ldif, sminmax.x, sminmax.y, 32.0 );; + float bb = smoothstep( 0.5, 0.8, con ); - float lkey = clamp( dot(nor,-ldif), 0.0, 1.0 ); - vec3 lkat = vec3(1.0); + float lkey = clamp( dot(nor,ldif), 0.0, 1.0 ); + vec3 lkat = vec3(1.0); lkat *= vec3(bb*bb*0.6+0.4*bb,bb*0.5+0.5*bb*bb,bb).zyx; lkat /= 1.0+0.25*llen*llen; - lkat *= 25.0; + lkat *= 30.0; lkat *= sha; float lbac = clamp( 0.1 + 0.9*dot( light2, nor ), 0.0, 1.0 ); lbac *= smoothstep( 0.0, 0.8, con ); - lbac /= 1.0+0.2*llen*llen; - lbac *= 4.0; - float lamb = 1.0 - 0.5*nor.y; + lbac /= 1.0+0.2*llen*llen; + lbac *= 4.0; + float lamb = 1.0 - 0.5*nor.y; lamb *= 1.0-smoothstep( 10.0, 25.0, length(pos.xz) ); - lamb *= 0.25 + 0.75*smoothstep( 0.0, 0.8, con ); - lamb *= 0.25; - + lamb *= 0.25 + 0.75*smoothstep( 0.0, 0.8, con ); + lamb *= 0.25; + vec3 lin = 1.0*vec3(0.20,0.05,0.02)*lamb*occ; lin += 1.0*vec3(1.60,0.70,0.30)*lkey*lkat*(0.5+0.5*occ); lin += 1.0*vec3(0.70,0.20,0.08)*lbac*occ; @@ -228,18 +202,21 @@ vec3 doLighting( in vec3 col, in float ks, col = col*lin; - vec3 spe = vec3(1.0)*occ*lkat*pow( clamp(dot( reflect(rd,nor), -ldif ),0.0,1.0), 4.0 ); - col += (0.5+0.5*ks)*0.5*spe*vec3(1.0,0.9,0.7); + vec3 spe = ks*lkey*lkat*(0.5+0.5*occ)*5.0* + pow( clamp(dot(normalize(ldif-rd), nor),0.0,1.0), 4.0 ) * + (0.04+0.96*pow(clamp(dot(nor,-rd),0.0,1.0),5.0)); + + col += (0.5+0.5*ks)*0.5*spe*vec3(1.0,0.9,0.7); return col; } mat3 setLookAt( in vec3 ro, in vec3 ta, float cr ) { - vec3 cw = normalize(ta-ro); - vec3 cp = vec3(sin(cr), cos(cr),0.0); - vec3 cu = normalize( cross(cw,cp) ); - vec3 cv = normalize( cross(cu,cw) ); + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = normalize( cross(cu,cw) ); return mat3( cu, cv, cw ); } @@ -272,25 +249,26 @@ vec3 render( in vec3 ro, in vec3 rd ) } + void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - freqs[0] = texture2D( iChannel0, vec2( 0.01, 0.25 ) ).x; - freqs[1] = texture2D( iChannel0, vec2( 0.07, 0.25 ) ).x; - freqs[2] = texture2D( iChannel0, vec2( 0.15, 0.25 ) ).x; - freqs[3] = texture2D( iChannel0, vec2( 0.30, 0.25 ) ).x; - + freqs[0] = texture( iChannel0, vec2( 0.01, 0.25 ) ).x; + freqs[1] = texture( iChannel0, vec2( 0.07, 0.25 ) ).x; + freqs[2] = texture( iChannel0, vec2( 0.15, 0.25 ) ).x; + freqs[3] = texture( iChannel0, vec2( 0.30, 0.25 ) ).x; //----------- - float time = 5.0 + 0.2*iGlobalTime + 20.0*iMouse.x/iResolution.x; - + float time = 5.0 + 0.2*iTime + 20.0*iMouse.x/iResolution.x; + vec3 tot = vec3(0.0); #ifdef ANTIALIAS - for( int i=0; i<4; i++ ) + for( int j=0; j 8.0 && ct < 33.5) + || (ct > 38.0 && ct < 88.5) + || (ct > 93.0 && ct < 194.5)) + beat = pow(sin(ct*3.1416*3.78+1.9)*0.5+0.5,15.0)*0.05; + + vec2 mbr,mbg,mbb; + vec2 p = (2.0*fragCoord.xy-iResolution.xy)/iResolution.y; + vec2 o = vec2(pow(p.x,2.),pow(p.y,2.)); + vec3 col = vec3(pow(2.*abs(o.x+o.y)+abs(o.x-o.y),5.)); + col = max(col,1.); + float t=iTime+beat*2.; + + float t2=t*2.0,t3=t*3.0,s2=sin(t2),s3=sin(t3),s4=sin(t*4.0),c2=cos(t2),c3=cos(t3); // Let me extend this line a little more with an useless comment :-) + + mbr = mbg = mbb = vec2(0.); + mbr += vec2(0.10*s4+0.40*c3,0.40*s2 +0.20*c3); + mbg += vec2(0.15*s3+0.30*c2,0.10*-s4+0.30*c3); + mbb += vec2(0.10*s3+0.50*c3,0.10*-s4+0.50*c2); + + col.r *= length(mbr.xy-p.xy); + col.g *= length(mbg.xy-p.xy); + col.b *= length(mbb.xy-p.xy); + col *= pow(mb(mbr,p)+mb(mbg,p)+mb(mbb,p),1.75); + + fragColor = vec4(col,1.); +} diff --git a/visualization.shadertoy/resources/shaders/discotunnel.frag.glsl b/visualization.shadertoy/resources/shaders/discotunnel.frag.glsl new file mode 100644 index 0000000..9c813d6 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/discotunnel.frag.glsl @@ -0,0 +1,47 @@ +// Taken from https://www.shadertoy.com/view/lsBSRR + +float tex(vec2 uv, float s) +{ + float col; + float ntiles = 10.0; + + // Calculate the shape of the LEDs + vec2 r = mod(uv * ntiles, 1.0) - vec2(0.5); + col = 1.0 - dot(r, r); + + // Add some light to the tunnel + vec4 n = texture(iChannel1, floor(uv * ntiles) / ntiles); + col *= mod(n.r * n.g * n.b * s + iTime * 0.1 + clamp(s, 0.0, 0.6), 1.0); + return clamp(col, 0.0, 1.0); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy / iResolution.xy; + vec2 uv1 = uv * 2.0 - 1.0; + + uv1.x *= iResolution.x / iResolution.y; + + // Calculate new UV coordinates + vec2 center = vec2(0.0, 0.0) + + vec2(0.075*(0.5 + 0.5 * sin(iTime*4.0)), + 0.05*(0.5 + 0.5 * sin(iTime*0.01 + 1.7))); + vec2 p = uv1 - center; + float r = length(p); + float a = atan(p.y, p.x) * 3.0 / 3.14; + vec2 uv2= vec2(1.0 / r + iTime*0.25, a); + + // Read the sound texture + float sound = texture(iChannel2, vec2(0.01, 1.0 - r)).r; + sound = pow(sound, 1.5); + + // Calculate the colors + vec3 c1 = vec3(0.02, 0.1, 0.02); + vec3 c2 = mix( vec3(1.0, 0.6, 0.6), vec3(0.6, 0.6, 1.0), vec3(0.5 + 0.5 * sin(iTime*0.1))); + vec3 c = mix(c1, c2, r); + vec3 coltunnel = sound * c * tex(uv2, sound) + ( 0.15 * texture(iChannel0, uv2).rgb); + vec3 colback = vec3(0.05,0.05,0.05); + + // Mix the colors + fragColor = vec4(r * coltunnel + (1.0 - r) * colback, 1.0); +} diff --git a/visualization.shadertoy/resources/electricpulse.frag.glsl b/visualization.shadertoy/resources/shaders/electricpulse.frag.glsl similarity index 69% rename from visualization.shadertoy/resources/electricpulse.frag.glsl rename to visualization.shadertoy/resources/shaders/electricpulse.frag.glsl index 959404d..af873a3 100644 --- a/visualization.shadertoy/resources/electricpulse.frag.glsl +++ b/visualization.shadertoy/resources/shaders/electricpulse.frag.glsl @@ -16,7 +16,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) for (float i = .0; i<0.5; i+=.008) { - acc+=texture2D(iChannel0,vec2(i,1.0)).x-.5; + acc+=texture(iChannel0,vec2(i,1.0)).x-.5; if (acc>best_acc) { best_acc = acc; @@ -28,18 +28,18 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) for (float i = .0; i< 1.0; i+=.05) { - colorize[int(i*3.0)]+=texture2D(iChannel0,vec2(i,9.1)).x*pow(i+.5,.9); + colorize[int(i*3.0)]+=texture(iChannel0,vec2(i,9.1)).x*pow(i+.5,.9); } colorize = normalize(colorize); float offset = best; - float osc = texture2D(iChannel0,vec2(offset+tuv.x*.4 +.1,1.0)).x-.5; - osc += texture2D(iChannel0,vec2(offset+tuv.x*.4 -.01,2.0)).x-.5; - osc += texture2D(iChannel0,vec2(offset+tuv.x*.4 +.01,5.0)).x-.5; + float osc = texture(iChannel0,vec2(offset+tuv.x*.4 +.1,1.0)).x-.5; + osc += texture(iChannel0,vec2(offset+tuv.x*.4 -.01,2.0)).x-.5; + osc += texture(iChannel0,vec2(offset+tuv.x*.4 +.01,5.0)).x-.5; osc*=.333; - float boost = texture2D(iChannel0,vec2(1.0)).x; + float boost = texture(iChannel0,vec2(1.0)).x; float power = pow(boost,9.0); vec3 color = vec3(.01); @@ -48,12 +48,12 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) color += colorize*.2*((.9-power)*.5+.1); vec2 buv = uv*(1.0+power*power*power*.2); - buv += vec2(pow(power,12.0)*5.1,iGlobalTime*.5); + buv += vec2(pow(power,12.0)*5.1,iTime*.5); color += color -= length(uv)*1.1; - color += texture2D(iChannel0,fragCoord.xy/256.0).xyz*.01; + color += texture(iChannel0,fragCoord.xy/256.0).xyz*.01; color = pow(max(vec3(.05),color),vec3(1.5)); fragColor = vec4(color,0.5); diff --git a/visualization.shadertoy/resources/shaders/fractalland.frag.glsl b/visualization.shadertoy/resources/shaders/fractalland.frag.glsl new file mode 100644 index 0000000..85db0d1 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/fractalland.frag.glsl @@ -0,0 +1,217 @@ +// Taken from https://www.shadertoy.com/view/XsBXWt# + +// "Fractal Cartoon" - former "DE edge detection" by Kali + +// There are no lights and no AO, only color by normals and dark edges. + +// update: Nyan Cat cameo, thanks to code from mu6k: https://www.shadertoy.com/view/4dXGWH + + +//#define SHOWONLYEDGES +#define NYAN +#define WAVES +#define BORDER + +#define RAY_STEPS 150 + +#define BRIGHTNESS 1.2 +#define GAMMA 1.4 +#define SATURATION .65 + + +#define detail .001 +#define t iTime*.5 + + +const vec3 origin=vec3(-1.,.7,0.); +float det=0.0; + + +// 2D rotation function +mat2 rot(float a) { + return mat2(cos(a),sin(a),-sin(a),cos(a)); +} + +// "Amazing Surface" fractal +vec4 formula(vec4 p) { + p.xz = abs(p.xz+1.)-abs(p.xz-1.)-p.xz; + p.y-=.25; + p.xy*=rot(radians(35.)); + p=p*2./clamp(dot(p.xyz,p.xyz),.2,1.); + return p; +} + +// Distance function +float de(vec3 pos) { +#ifdef WAVES + pos.y+=sin(pos.z-t*6.)*.15; //waves! +#endif + float hid=0.; + vec3 tpos=pos; + tpos.z=abs(3.-mod(tpos.z,6.)); + vec4 p=vec4(tpos,1.); + for (int i=0; i<4; i++) {p=formula(p);} + float fr=(length(max(vec2(0.),p.yz-1.5))-1.)/p.w; + float ro=max(abs(pos.x+1.)-.3,pos.y-.35); + ro=max(ro,-max(abs(pos.x+1.)-.1,pos.y-.5)); + pos.z=abs(.25-mod(pos.z,.5)); + ro=max(ro,-max(abs(pos.z)-.2,pos.y-.3)); + ro=max(ro,-max(abs(pos.z)-.01,-pos.y+.32)); + float d=min(fr,ro); + return d; +} + + +// Camera path +vec3 path(float ti) { + ti*=1.5; + vec3 p=vec3(sin(ti),(1.-sin(ti*2.))*.5,-ti*5.)*.5; + return p; +} + +// Calc normals, and here is edge detection, set to variable "edge" + +float edge=0.; +vec3 normal(vec3 p) { + vec3 e = vec3(0.0,det*5.,0.0); + + float d1=de(p-e.yxx),d2=de(p+e.yxx); + float d3=de(p-e.xyx),d4=de(p+e.xyx); + float d5=de(p-e.xxy),d6=de(p+e.xxy); + float d=de(p); + edge=abs(d-0.5*(d2+d1))+abs(d-0.5*(d4+d3))+abs(d-0.5*(d6+d5));//edge finder + edge=min(1.,pow(edge,.55)*15.); + return normalize(vec3(d1-d2,d3-d4,d5-d6)); +} + + +// Used Nyan Cat code by mu6k, with some mods + +vec4 rainbow(vec2 p) +{ + float q = max(p.x,-0.1); + float s = sin(p.x*7.0+t*70.0)*0.08; + p.y+=s; + p.y*=1.1; + + vec4 c; + if (p.x>0.0) c=vec4(0,0,0,0); else + if (0.0/6.00.2) color.a=0.0; + return color; +} + + +// Raymarching and 2D graphics + +vec3 raymarch(in vec3 from, in vec3 dir) + +{ + edge=0.; + vec3 p, norm; + float d=100.; + float totdist=0.; + for (int i=0; idet && totdist<25.0) { + p=from+totdist*dir; + d=de(p); + det=detail*exp(.13*totdist); + totdist+=d; + } + } + vec3 col=vec3(0.); + p-=(det-d)*dir; + norm=normal(p); +#ifdef SHOWONLYEDGES + col=1.-vec3(edge); // show wireframe version +#else + col=(1.-abs(norm))*max(0.,1.-edge*.8); // set normal as color with dark edges +#endif + totdist=clamp(totdist,0.,26.); + dir.y-=.02; + float sunsize=7.-max(0.,texture(iChannel0,vec2(.6,.2)).x)*5.; // responsive sun size + float an=atan(dir.x,dir.y)+iTime*1.5; // angle for drawing and rotating sun + float s=pow(clamp(1.0-length(dir.xy)*sunsize-abs(.2-mod(an,.4)),0.,1.),.1); // sun + float sb=pow(clamp(1.0-length(dir.xy)*(sunsize-.2)-abs(.2-mod(an,.4)),0.,1.),.1); // sun border + float sg=pow(clamp(1.0-length(dir.xy)*(sunsize-4.5)-.5*abs(.2-mod(an,.4)),0.,1.),3.); // sun rays + float y=mix(.45,1.2,pow(smoothstep(0.,1.,.75-dir.y),2.))*(1.-sb*.5); // gradient sky + + // set up background with sky and sun + vec3 backg=vec3(0.5,0.,1.)*((1.-s)*(1.-sg)*y+(1.-sb)*sg*vec3(1.,.8,0.15)*3.); + backg+=vec3(1.,.9,.1)*s; + backg=max(backg,sg*vec3(1.,.9,.5)); + + col=mix(vec3(1.,.9,.3),col,exp(-.004*totdist*totdist));// distant fading to sun color + if (totdist>25.) col=backg; // hit background + col=pow(col,vec3(GAMMA))*BRIGHTNESS; + col=mix(vec3(length(col)),col,SATURATION); +#ifdef SHOWONLYEDGES + col=1.-vec3(length(col)); +#else + col*=vec3(1.,.9,.85); +#ifdef NYAN + dir.yx*=rot(dir.x); + vec2 ncatpos=(dir.xy+vec2(-3.+mod(-t,6.),-.27)); + vec4 ncat=nyan(ncatpos*5.); + vec4 rain=rainbow(ncatpos*10.+vec2(.8,.5)); + if (totdist>8.) col=mix(col,max(vec3(.2),rain.xyz),rain.a*.9); + if (totdist>8.) col=mix(col,max(vec3(.2),ncat.xyz),ncat.a*.9); +#endif +#endif + return col; +} + +// get camera position +vec3 move(inout vec3 dir) { + vec3 go=path(t); + vec3 adv=path(t+.7); + float hd=de(adv); + vec3 advec=normalize(adv-go); + float an=adv.x-go.x; an*=min(1.,abs(adv.z-go.z))*sign(adv.z-go.z)*.7; + dir.xy*=mat2(cos(an),sin(an),-sin(an),cos(an)); + an=advec.y*1.7; + dir.yz*=mat2(cos(an),sin(an),-sin(an),cos(an)); + an=atan(advec.x,advec.z); + dir.xz*=mat2(cos(an),sin(an),-sin(an),cos(an)); + return go; +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy / iResolution.xy*2.-1.; + vec2 oriuv=uv; + uv.y*=iResolution.y/iResolution.x; + vec2 mouse=(iMouse.xy/iResolution.xy-.5)*3.; + if (iMouse.z<1.) mouse=vec2(0.,-0.05); + float fov=.9-max(0.,.7-iTime*.3); + vec3 dir=normalize(vec3(uv*fov,1.)); + dir.yz*=rot(mouse.y); + dir.xz*=rot(mouse.x); + vec3 from=origin+move(dir); + vec3 color=raymarch(from,dir); + #ifdef BORDER + color=mix(vec3(0.),color,pow(max(0.,.95-length(oriuv*oriuv*oriuv*vec2(1.05,1.1))),.3)); + #endif + fragColor = vec4(color,1.); +} diff --git a/visualization.shadertoy/resources/shaders/gameboy.frag.glsl b/visualization.shadertoy/resources/shaders/gameboy.frag.glsl new file mode 100644 index 0000000..0592d50 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/gameboy.frag.glsl @@ -0,0 +1,93 @@ +// Taken from https://www.shadertoy.com/view/XdlGzr + +// Created by inigo quilez - iq/2013 +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + +// Created by inigo quilez - iq/2013 +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + +float text( vec2 p ) +{ + // trick for encoding fonts from CPU + p.x += 0.2*floor(10.0*(0.5+0.5*sin(iTime)))/10.0; + + float x = floor( p.x*100.0 ) - 23.0; + float y = floor( p.y*100.0 ) - 82.0; + + if( y<0.0 || y> 5.0) return 0.0; + if( x<0.0 || x>70.0) return 0.0; + + float v = 0.0; + + if( x>63.5 ) { v=12288.0; + if(y>2.5) v=30720.0; + if(y>3.5) v=52224.0; } + else if( x>47.5 ) { v=12408.0; + if(y>0.5) v=12492.0; + if(y>4.5) v=64632.0; } + else if( x>31.5 ) { v=64716.0; + if(y>0.5) v=49360.0; + if(y>1.5) v=49400.0; + if(y>2.5) v=63692.0; + if(y>3.5) v=49356.0; + if(y>4.5) v=64760.0; } + else if( x>15.5 ) { v=40184.0; + if(y>0.5) v=40092.0; + if(y>2.5) v=64668.0; + if(y>3.5) v=40092.0; + if(y>4.5) v=28920.0; } + else { v=30860.0; + if(y>0.5) v=40076.0; + if(y>1.5) v= 7308.0; + if(y>2.5) v=30972.0; + if(y>3.5) v=49292.0; + if(y>4.5) v=30860.0; } + + return floor( mod(v/pow(2.0,15.0-mod( x, 16.0 )), 2.0) ); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy / iResolution.xy; + vec2 uvo = uv; + + vec2 res = floor( 60.0*vec2(1.0,iResolution.y/iResolution.x) ); + + vec3 col = vec3(131.0, 145.0, 0.0); + if( uv.x>0.03 && uv.x<0.97 ) + { + uv.x = clamp( (uv.x-0.03)/0.94, 0.0, 1.0 ); + + vec2 iuv = floor( uv * res )/res; + + float f = 1.0-abs(-1.0+2.0*fract( uv.x * res.x )); + float g = 1.0-abs(-1.0+2.0*fract( uv.y * res.y )); + + float fft = texture( iChannel0, vec2(iuv.x,0.25) ).x; + fft = 0.8*fft*fft; + if( iuv.y0.1 && g>0.1 ) col = vec3(40.0,44.0,4.0); + if( f>0.5 && g>0.5 ) col = vec3(74.0,82.0,4.0); + } + + + float wave = texture( iChannel0, vec2(iuv.x*0.5,0.75) ).x; + if( abs(iuv.y-wave)<=(1.0/res.y) ) + { + col = vec3(185.0, 200.0, 90.0); + } + + float t = text( uvo ); + col = mix( col, vec3(40.0,44.0,4.0), t ); + } + else + { + float g = 1.0-abs(-1.0+2.0*fract( uv.y * res.y*1.5 )); + float f = 1.0-abs(-1.0+2.0*fract( uv.x * res.x + 0.5*floor(uv.y*res.y*1.5))); + + if( g<0.15 || f<0.15 ) col = vec3(40.0,44.0,4.0); + } + + fragColor = vec4( col/255.0,1.0 ); +} diff --git a/visualization.shadertoy/resources/input.frag.glsl b/visualization.shadertoy/resources/shaders/input.frag.glsl similarity index 100% rename from visualization.shadertoy/resources/input.frag.glsl rename to visualization.shadertoy/resources/shaders/input.frag.glsl diff --git a/visualization.shadertoy/resources/shaders/io.frag.glsl b/visualization.shadertoy/resources/shaders/io.frag.glsl new file mode 100644 index 0000000..613f852 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/io.frag.glsl @@ -0,0 +1,71 @@ +// Taken from https://www.shadertoy.com/view/XsfGDS +// I/O fragment shader by movAX13h, August 2013 + +// I/O fragment shader by movAX13h, August 2013 + +#define SHOW_BLOCKS + +float rand(float x) +{ + return fract(sin(x) * 4358.5453123); +} + +float rand(vec2 co) +{ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5357); +} + +float box(vec2 p, vec2 b, float r) +{ + return length(max(abs(p)-b,0.0))-r; +} + +float sampleMusic() +{ + return 0.5 * ( + //texture( iChannel0, vec2( 0.01, 0.25 ) ).x + + //texture( iChannel0, vec2( 0.07, 0.25 ) ).x + + texture( iChannel0, vec2( 0.15, 0.25 ) ).x + + texture( iChannel0, vec2( 0.30, 0.25 ) ).x); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + const float speed = 0.7; + const float ySpread = 1.6; + const int numBlocks = 70; + + float pulse = sampleMusic(); + + vec2 uv = fragCoord.xy / iResolution.xy - 0.5; + float aspect = iResolution.x / iResolution.y; + vec3 baseColor = uv.x > 0.0 ? vec3(0.0,0.3, 0.6) : vec3(0.6, 0.0, 0.3); + + vec3 color = pulse*baseColor*0.5*(0.9-cos(uv.x*8.0)); + uv.x *= aspect; + + for (int i = 0; i < numBlocks; i++) + { + float z = 1.0-0.7*rand(float(i)*1.4333); // 0=far, 1=near + float tickTime = iTime*z*speed + float(i)*1.23753; + float tick = floor(tickTime); + + vec2 pos = vec2(0.6*aspect*(rand(tick)-0.5), sign(uv.x)*ySpread*(0.5-fract(tickTime))); + pos.x += 0.24*sign(pos.x); // move aside + if (abs(pos.x) < 0.1) pos.x++; // stupid fix; sign sometimes returns 0 + + vec2 size = 1.8*z*vec2(0.04, 0.04 + 0.1*rand(tick+0.2)); + float b = box(uv-pos, size, 0.01); + float dust = z*smoothstep(0.22, 0.0, b)*pulse*0.5; + #ifdef SHOW_BLOCKS + float block = 0.2*z*smoothstep(0.002, 0.0, b); + float shine = 0.6*z*pulse*smoothstep(-0.002, b, 0.007); + color += dust*baseColor + block*z + shine; + #else + color += dust*baseColor; + #endif + } + + color -= rand(uv)*0.04; + fragColor = vec4(color, 1.0); +} diff --git a/visualization.shadertoy/resources/shaders/kaleidoscopevisualizer.frag.glsl b/visualization.shadertoy/resources/shaders/kaleidoscopevisualizer.frag.glsl new file mode 100644 index 0000000..c322404 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/kaleidoscopevisualizer.frag.glsl @@ -0,0 +1,105 @@ +// Taken from https://www.shadertoy.com/view/ldsXWn# + +// ---- change here kaleidoscope size and toggle on/off---- +const float USE_KALEIDOSCOPE = 1.0; +const float NUM_SIDES = 8.0; + +// ---- Change the amount at which the visualizer reacts to music (per song different settings work best) ---- +const float MIN_SIZE = 0.01; +const float REACT_INTENSITY = 0.3; +const float BASS_INTENSITY = 1.1; +const float BASS_BASE_HEIGHT = .0; +const float ZOOM_FACTOR = 0.5; + +// math const +const float PI = 3.14159265359; +const float DEG_TO_RAD = PI / 180.0; + +// -4/9(r/R)^6 + (17/9)(r/R)^4 - (22/9)(r/R)^2 + 1.0 +float field( vec2 p, vec2 center, float r ) { + float d = length( p - center ) / r; + + float t = d * d; + float tt = t * d; + float ttt = tt * d; + + float v = + ( - 10.0 / 9.0 ) * ttt + + ( 17.0 / 9.0 ) * tt + + ( -22.0 / 9.0 ) * t + + 1.0; + + return clamp( v, 0.0, 1.0 ); +} + +vec2 Kaleidoscope( vec2 uv, float n, float bias ) { + float angle = PI / n; + + float r = length( uv*.5 ); + float a = atan( uv.y, uv.x ) / angle; + + a = mix( fract( a ), 1.0 - fract( a ), mod( floor( a ), 2.0 ) ) * angle; + + return vec2( cos( a ), sin( a ) ) * r; +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 ratio = iResolution.xy / min( iResolution.x, iResolution.y ); + vec2 uv = ( fragCoord.xy * 2.0 - iResolution.xy ) / min( iResolution.x, iResolution.y ); + + // --- Kaleidoscope --- + uv = mix( uv, Kaleidoscope( uv, NUM_SIDES, iChannelTime[1]*10. ), USE_KALEIDOSCOPE ); + + uv *= ZOOM_FACTOR+(BASS_INTENSITY)* (texture(iChannel1, vec2(.01,0)).r); + + vec3 final_color = vec3( 0.0 ); + float final_density = 0.0; + for ( int i = 0; i < 128; i++ ) { + vec4 noise = texture( iChannel0, vec2( float( i ) + 0.5, 0.5 ) / 256.0 ); + vec4 noise2 = texture( iChannel0, vec2( float( i ) + 0.5, 9.5 ) / 256.0 ); + + + //sound loudness to intensity + float velintensity = texture(iChannel1, vec2(1.0+uv.x,0)).r; + + // velocity + vec2 vel = -abs(noise.xy) * 3.0 +vec2( .003*-velintensity )-vec2(2.0); + vel*=-.5; + + // center + vec2 pos = noise.xy; + pos += iChannelTime[1] * vel * 0.2; + pos = mix( fract( pos ),fract( pos ), mod( floor( pos ), 2.0 ) ); + + //sound loudness to intensity + float intensity = texture(iChannel1, vec2(pos.y,0)).r; + + // remap to screen + pos = ( pos * 2.0 - 1.0 ) * ratio; + + + + // radius + float radius = clamp( noise.w, 0.3, 0.8 ); + radius *= 3.*intensity; + //radius += 0.5; + radius *= radius * 0.4; + radius = clamp(radius, MIN_SIZE*abs(-pos.x), REACT_INTENSITY); + + // color + vec3 color = noise2.xyz; + + // density + float density = field( uv, pos, radius ); + + // accumulate + final_density += density; + final_color += density * color; + } + + final_density = clamp( final_density - 0.1, 0.0, 1.0 ); + final_density = pow( final_density, 3.0 ); + + fragColor = vec4( final_color * final_density, final_density ); +} diff --git a/visualization.shadertoy/resources/shaders/ledspectrum.frag.glsl b/visualization.shadertoy/resources/shaders/ledspectrum.frag.glsl new file mode 100644 index 0000000..b52865e --- /dev/null +++ b/visualization.shadertoy/resources/shaders/ledspectrum.frag.glsl @@ -0,0 +1,56 @@ +// Taken from https://www.shadertoy.com/view/Msl3zr + +const float PI = 3.14159; + +// http://github.prideout.net/barrel-distortion/ +vec2 distort(vec2 p, float power) +{ + float a = atan(p.y, p.x); + float r = length(p); + r = pow(r, power); + return vec2(r * cos(a), r*sin(a)); + //return vec2((a / PI), r*2.0-1.0); // polar +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + // create pixel coordinates + vec2 uv = fragCoord.xy / iResolution.xy; + + // distort + float bass = texture( iChannel0, vec2(0, 0) ).x; + uv = distort(uv*2.0-1.0, 0.5+bass)*0.5+0.5; + + // quantize coordinates + const float bands = 20.0; + const float segs = 20.0; + vec2 p; + p.x = floor(uv.x*bands)/bands; + p.y = floor(uv.y*segs)/segs; + + // read frequency data from first row of texture + float fft = texture( iChannel0, vec2(p.x,0.0) ).x; + + // led color + vec3 color = mix(vec3(0.0, 2.0, 0.0), vec3(2.0, 0.0, 0.0), sqrt(uv.y)); + + // mask for bar graph + float mask = (p.y < fft) ? 1.0 : 0.0; + + // led shape + vec2 d = fract((uv - p)*vec2(bands, segs)) - 0.5; + float led = smoothstep(0.5, 0.3, abs(d.x)) * + smoothstep(0.5, 0.3, abs(d.y)); + vec3 ledColor = led*color*mask; + + // second texture row is the sound wave + float wave = texture( iChannel0, vec2(uv.x, 0.75) ).x; + vec3 waveColor = vec3(0.001, 0.01, 0.04) / abs(wave - uv.y); + + // output final color + //fragColor = vec4(vec3(fft),1.0); + //fragColor = vec4(d, 0.0, 1.0); + //fragColor = vec4(ledColor, 1.0); + //fragColor = vec4(waveColor, 1.0); + fragColor = vec4(ledColor + waveColor, 1.0); +} diff --git a/visualization.shadertoy/resources/shaders/main_display_GL.frag.glsl b/visualization.shadertoy/resources/shaders/main_display_GL.frag.glsl new file mode 100644 index 0000000..725c7c2 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_display_GL.frag.glsl @@ -0,0 +1,12 @@ +#version 150 + +uniform sampler2D uTexture; + +in vec2 vTextureCoord; + +out vec4 FragColor; + +void main(void) +{ + FragColor = texture(uTexture, vTextureCoord); +} diff --git a/visualization.shadertoy/resources/shaders/main_display_GL.vert.glsl b/visualization.shadertoy/resources/shaders/main_display_GL.vert.glsl new file mode 100644 index 0000000..f5a00ce --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_display_GL.vert.glsl @@ -0,0 +1,10 @@ +#version 150 + +in vec4 vertex; +out vec2 vTextureCoord; + +void main(void) +{ + gl_Position = vertex; + vTextureCoord = vertex.xy*0.5+0.5; +} diff --git a/visualization.shadertoy/resources/shaders/main_display_GLES.frag.glsl b/visualization.shadertoy/resources/shaders/main_display_GLES.frag.glsl new file mode 100644 index 0000000..2339be0 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_display_GLES.frag.glsl @@ -0,0 +1,13 @@ +#version 100 + +precision mediump float; +precision mediump int; + +varying vec2 vTextureCoord; + +uniform sampler2D uTexture; + +void main(void) +{ + gl_FragColor = texture2D(uTexture, vTextureCoord); +} diff --git a/visualization.shadertoy/resources/shaders/main_display_GLES.vert.glsl b/visualization.shadertoy/resources/shaders/main_display_GLES.vert.glsl new file mode 100644 index 0000000..a74e9ae --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_display_GLES.vert.glsl @@ -0,0 +1,14 @@ +#version 100 + +precision mediump float; +precision mediump int; + +attribute vec4 vertex; + +varying vec2 vTextureCoord; + +void main(void) +{ + gl_Position = vertex; + vTextureCoord = vertex.xy*0.5+0.5; +} diff --git a/visualization.shadertoy/resources/shaders/main_shadertoy_GL.vert.glsl b/visualization.shadertoy/resources/shaders/main_shadertoy_GL.vert.glsl new file mode 100644 index 0000000..edc8bc2 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_shadertoy_GL.vert.glsl @@ -0,0 +1,14 @@ +#version 150 + +uniform vec2 uScale; + +in vec4 vertex; +out vec2 vTextureCoord; + +void main(void) +{ + gl_Position = vertex; + vTextureCoord = vertex.xy*0.5+0.5; + vTextureCoord.x = vTextureCoord.x * uScale.x; + vTextureCoord.y = vTextureCoord.y * uScale.y; +} diff --git a/visualization.shadertoy/resources/shaders/main_shadertoy_GLES.vert.glsl b/visualization.shadertoy/resources/shaders/main_shadertoy_GLES.vert.glsl new file mode 100644 index 0000000..1a24673 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_shadertoy_GLES.vert.glsl @@ -0,0 +1,15 @@ +#version 100 + +attribute vec4 vertex; + +varying vec2 vTextureCoord; + +uniform vec2 uScale; + +void main(void) +{ + gl_Position = vertex; + vTextureCoord = vertex.xy*0.5+0.5; + vTextureCoord.x = vTextureCoord.x * uScale.x; + vTextureCoord.y = vTextureCoord.y * uScale.y; +} diff --git a/visualization.shadertoy/resources/shaders/main_test.frag.glsl b/visualization.shadertoy/resources/shaders/main_test.frag.glsl new file mode 100644 index 0000000..338d063 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/main_test.frag.glsl @@ -0,0 +1,9 @@ +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + float y = ( fragCoord.y / iResolution.y ) * 26.0; + float x = 1.0 - ( fragCoord.x / iResolution.x ); + float b = fract( pow( 2.0, floor(y) ) + x ); + if (fract(y) >= 0.9) + b = 0.0; + fragColor = vec4(b, b, b, 1.0 ); +} diff --git a/visualization.shadertoy/resources/nyancat.frag.glsl b/visualization.shadertoy/resources/shaders/nyancat.frag.glsl similarity index 100% rename from visualization.shadertoy/resources/nyancat.frag.glsl rename to visualization.shadertoy/resources/shaders/nyancat.frag.glsl diff --git a/visualization.shadertoy/resources/shaders/polarbeats.frag.glsl b/visualization.shadertoy/resources/shaders/polarbeats.frag.glsl new file mode 100644 index 0000000..05f8c71 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/polarbeats.frag.glsl @@ -0,0 +1,89 @@ +// Taken from https://www.shadertoy.com/view/4dBXRz# + +#define FILTER +#define LIGHT_SOURCE +#define GLOW + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + // aspect ratio + float a = iResolution.x/iResolution.y; + + // position of screen + // dom x = [0.0, 1.0] + // dom y = [0.0, 1.0] + // origin is at bottom left corner + vec2 uv = fragCoord.xy / iResolution.xy; + + // multiply aspect ratio to remove distortions + uv.x *= a; + + // align polar graph to center of screen + vec2 q = uv - vec2(0.5*a, 0.5); + + // fft values, look at the bars at the bottom of the screen + float fft = texture2D(iChannel0, vec2(0.0, 0.)).x; + float fft2 = texture2D(iChannel0, vec2(1., 0.)).x; + float fft3 = texture2D(iChannel0, vec2(0.5, 0.)).x; + + // theta value + float t = atan(q.y, q.x); + + // time from start of song + float ts = iChannelTime[0]; + + // the main polar graph, r = ... + float r = pow(fft*2.-0.5, 2.)*cos(6.*t + (fft2*1.5 + ts)*5.) + 2.0 + pow(fft, 2.); + r *= fft/12. + 0.04; + + vec2 p = q; + #ifdef FILTER + p.x += sin(q.y*5000.)/100.; + p.y += cos(q.x*5000.)/100.; + #endif + + + // bg + float bg = smoothstep(r, r + fft*0.02 + 0.01, length(p)); + vec3 col = vec3(bg,bg,bg); + #ifdef GLOW + col *= 1.*smoothstep(0., r + fft*0.2, length(q)); + #endif + + col.r = clamp(col.r, 0.0, 1.0); + col.g = clamp(col.g, 0.0, 1.0); + col.b = clamp(col.b, 0.0, 1.0); + + // fg + vec3 col2 = 1.0 - col; + + // bg + // radial gradient + col -= 0.5*smoothstep(0.0, 2., length(q/(fft + 0.5))); + + #ifdef LIGHT_SOURCE + // give a more red warm light colour + col.g *= 0.97; + col.b *= 0.97; + + // cool lighting effect + col += uv.y/16.; + #endif + + #ifdef FILTER + col += sin(50.*q.y - ts*3.)*(fft*0.5+0.5)*0.05 - 0.1*(fft*0.3+0.5)*abs(-2.*q.x*sin(q.y*1000. - ts*5.)); + #endif // FILTER + + // fg + // colour of polar graph + col2 *= vec3(0.0, 0.9, 0.9); + // radial gradient for polar graph. + // removing this will change the polar graph to a solid colour + col2 *= length(q)*0.5 + 0.85; + + // add fg to bg + col += col2; + + // volia! + fragColor = vec4(col,1.0); +} diff --git a/visualization.shadertoy/resources/revision2015.frag.glsl b/visualization.shadertoy/resources/shaders/revision2015.frag.glsl similarity index 100% rename from visualization.shadertoy/resources/revision2015.frag.glsl rename to visualization.shadertoy/resources/shaders/revision2015.frag.glsl diff --git a/visualization.shadertoy/resources/ribbons.frag.glsl b/visualization.shadertoy/resources/shaders/ribbons.frag.glsl similarity index 100% rename from visualization.shadertoy/resources/ribbons.frag.glsl rename to visualization.shadertoy/resources/shaders/ribbons.frag.glsl diff --git a/visualization.shadertoy/resources/shaders/simplicitygalaxy.frag.glsl b/visualization.shadertoy/resources/shaders/simplicitygalaxy.frag.glsl new file mode 100644 index 0000000..4952aa6 --- /dev/null +++ b/visualization.shadertoy/resources/shaders/simplicitygalaxy.frag.glsl @@ -0,0 +1,87 @@ +// Taken from https://www.shadertoy.com/view/MslGWN + +//CBS +//Parallax scrolling fractal galaxy. +//Inspired by JoshP's Simplicity shader: https://www.shadertoy.com/view/lslGWr + +// http://www.fractalforums.com/new-theories-and-research/very-simple-formula-for-fractal-patterns/ +float field(in vec3 p,float s) { + float strength = 7. + .03 * log(1.e-6 + fract(sin(iTime) * 4373.11)); + float accum = s/4.; + float prev = 0.; + float tw = 0.; + for (int i = 0; i < 26; ++i) { + float mag = dot(p, p); + p = abs(p) / mag + vec3(-.5, -.4, -1.5); + float w = exp(-float(i) / 7.); + accum += w * exp(-strength * pow(abs(mag - prev), 2.2)); + tw += w; + prev = mag; + } + return max(0., 5. * accum / tw - .7); +} + +// Less iterations for second layer +float field2(in vec3 p, float s) { + float strength = 7. + .03 * log(1.e-6 + fract(sin(iTime) * 4373.11)); + float accum = s/4.; + float prev = 0.; + float tw = 0.; + for (int i = 0; i < 18; ++i) { + float mag = dot(p, p); + p = abs(p) / mag + vec3(-.5, -.4, -1.5); + float w = exp(-float(i) / 7.); + accum += w * exp(-strength * pow(abs(mag - prev), 2.2)); + tw += w; + prev = mag; + } + return max(0., 5. * accum / tw - .7); +} + +vec3 nrand3( vec2 co ) +{ + vec3 a = fract( cos( co.x*8.3e-3 + co.y )*vec3(1.3e5, 4.7e5, 2.9e5) ); + vec3 b = fract( sin( co.x*0.3e-3 + co.y )*vec3(8.1e5, 1.0e5, 0.1e5) ); + vec3 c = mix(a, b, 0.5); + return c; +} + + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) { + vec2 uv = 2. * fragCoord.xy / iResolution.xy - 1.; + vec2 uvs = uv * iResolution.xy / max(iResolution.x, iResolution.y); + vec3 p = vec3(uvs / 4., 0) + vec3(1., -1.3, 0.); + p += .2 * vec3(sin(iTime / 16.), sin(iTime / 12.), sin(iTime / 128.)); + + float freqs[4]; + //Sound + freqs[0] = texture( iChannel0, vec2( 0.01, 0.25 ) ).x; + freqs[1] = texture( iChannel0, vec2( 0.07, 0.25 ) ).x; + freqs[2] = texture( iChannel0, vec2( 0.15, 0.25 ) ).x; + freqs[3] = texture( iChannel0, vec2( 0.30, 0.25 ) ).x; + + float t = field(p,freqs[2]); + float v = (1. - exp((abs(uv.x) - 1.) * 6.)) * (1. - exp((abs(uv.y) - 1.) * 6.)); + + //Second Layer + vec3 p2 = vec3(uvs / (4.+sin(iTime*0.11)*0.2+0.2+sin(iTime*0.15)*0.3+0.4), 1.5) + vec3(2., -1.3, -1.); + p2 += 0.25 * vec3(sin(iTime / 16.), sin(iTime / 12.), sin(iTime / 128.)); + float t2 = field2(p2,freqs[3]); + vec4 c2 = mix(.4, 1., v) * vec4(1.3 * t2 * t2 * t2 ,1.8 * t2 * t2 , t2* freqs[0], t2); + + + //Let's add some stars + //Thanks to http://glsl.heroku.com/e#6904.0 + vec2 seed = p.xy * 2.0; + seed = floor(seed * iResolution.x); + vec3 rnd = nrand3( seed ); + vec4 starcolor = vec4(pow(rnd.y,40.0)); + + //Second Layer + vec2 seed2 = p2.xy * 2.0; + seed2 = floor(seed2 * iResolution.x); + vec3 rnd2 = nrand3( seed2 ); + starcolor += vec4(pow(rnd2.y,40.0)); + + fragColor = mix(freqs[3]-.3, 1., v) * vec4(1.5*freqs[2] * t * t* t , 1.2*freqs[1] * t * t, freqs[3]*t, 1.0)+c2+starcolor; +} diff --git a/visualization.shadertoy/resources/shaders/soundflower.frag.glsl b/visualization.shadertoy/resources/shaders/soundflower.frag.glsl new file mode 100644 index 0000000..f4b886b --- /dev/null +++ b/visualization.shadertoy/resources/shaders/soundflower.frag.glsl @@ -0,0 +1,23 @@ +// Taken from https://www.shadertoy.com/view/Msf3Dn# + +// Created by inigo quilez - iq/2013 +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = -1.0+2.0*fragCoord.xy/iResolution.xy; + uv.x *= iResolution.x/iResolution.y; + + float r = length( uv ); + float a = atan( uv.x, uv.y ); + + float w = texture2D( iChannel0, vec2( abs(a)/6.28,1.0) ).x; + + float t = 3.0*sqrt(abs(w-0.5)); + + float f = 0.0; + if( r 0.5) + { + uv -= 0.5; + uv *= 2.; + } + else + { + uv *= 2.; + uv = 1. - uv; + } + + float fft = texture( iChannel0, vec2(uv.x,0.25) ).x; + float dr = length(uv); + float radius = 1.8; + + vec3 col = vec3(0.); + if( abs(uv.y)61.8 && iChannelTime[0]<65.0 ) + col *= vec3(1.0)*clamp( (iChannelTime[0]-61.8)/(65.0-61.8), 0.0, 1.0 ); + + + col *= 0.15+0.85*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.15 ); + + fragColor=vec4( col, 1.0 ); +} diff --git a/visualization.shadertoy/resources/shaders/wavesremix.frag.glsl b/visualization.shadertoy/resources/shaders/wavesremix.frag.glsl new file mode 100644 index 0000000..d89f78e --- /dev/null +++ b/visualization.shadertoy/resources/shaders/wavesremix.frag.glsl @@ -0,0 +1,32 @@ +// Taken from https://www.shadertoy.com/view/4ljGD1 + +float squared(float value) { return value * value; } + +float getAmp(float frequency) { return texture(iChannel0, vec2(frequency / 512.0, 0)).x; } + +float getWeight(float f) { + return (+ getAmp(f-2.0) + getAmp(f-1.0) + getAmp(f+2.0) + getAmp(f+1.0) + getAmp(f)) / 5.0; } + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uvTrue = fragCoord.xy / iResolution.xy; + vec2 uv = -1.0 + 2.0 * uvTrue; + + float lineIntensity; + float glowWidth; + vec3 color = vec3(0.0); + + for(float i = 0.0; i < 5.0; i++) { + + uv.y += (0.2 * sin(uv.x + i/7.0 - iTime * 0.6)); + float Y = uv.y + getWeight(squared(i) * 20.0) * + (texture(iChannel0, vec2(uvTrue.x, 1)).x - 0.5); + lineIntensity = 0.4 + squared(1.6 * abs(mod(uvTrue.x + i / 1.3 + iTime,2.0) - 1.0)); + glowWidth = abs(lineIntensity / (150.0 * Y)); + color += vec3(glowWidth * (2.0 + sin(iTime * 0.13)), + glowWidth * (2.0 - sin(iTime * 0.23)), + glowWidth * (2.0 - cos(iTime * 0.19))); + } + + fragColor = vec4(color, 1.0); +} diff --git a/visualization.shadertoy/resources/simplicitygalaxy.frag.glsl b/visualization.shadertoy/resources/simplicitygalaxy.frag.glsl deleted file mode 100644 index 0d1adab..0000000 --- a/visualization.shadertoy/resources/simplicitygalaxy.frag.glsl +++ /dev/null @@ -1,89 +0,0 @@ -// Taken from https://www.shadertoy.com/view/MslGWN - -//CBS -//Parallax scrolling fractal galaxy. -//Inspired by JoshP's Simplicity shader: https://www.shadertoy.com/view/lslGWr - -// http://www.fractalforums.com/new-theories-and-research/very-simple-formula-for-fractal-patterns/ -float field(in vec3 p, float s) { - float strength = 7. + .03 * log(1.e-6 + fract(sin(iGlobalTime) * 4373.11)); - float accum = s / 4.; - float prev = 0.; - float tw = 0.; - for (int i = 0; i < 14; ++i) { - float mag = dot(p, p); - p = abs(p) / mag + vec3(-.5, -.4, -1.5); - float w = exp(-float(i) / 7.); - accum += w * exp(-strength * pow(abs(mag - prev), 2.2)); - tw += w; - prev = mag; - } - return max(0., 5. * accum / tw - .7); -} - -// Less iterations for second layer -float field2(in vec3 p, float s) { - float strength = 7. + .03 * log(1.e-6 + fract(sin(iGlobalTime) * 4373.11)); - float accum = s / 4.; - float prev = 0.; - float tw = 0.; - for (int i = 0; i < 12; ++i) { - float mag = dot(p, p); - p = abs(p) / mag + vec3(-.5, -.4, -1.5); - float w = exp(-float(i) / 7.); - accum += w * exp(-strength * pow(abs(mag - prev), 2.2)); - tw += w; - prev = mag; - } - return max(0., 5. * accum / tw - .7); -} - -vec3 nrand3(vec2 co) -{ - vec3 a = fract(cos(co.x*8.3e-3 + co.y)*vec3(1.3e5, 4.7e5, 2.9e5)); - vec3 b = fract(sin(co.x*0.3e-3 + co.y)*vec3(8.1e5, 1.0e5, 0.1e5)); - vec3 c = mix(a, b, 0.5); - return c; -} - - -void mainImage(out vec4 fragColor, in vec2 fragCoord) { - vec2 uv = 2. * fragCoord.xy / iResolution.xy - 1.; - vec2 uvs = uv * iResolution.xy / max(iResolution.x, iResolution.y); - vec3 p = vec3(uvs / 4., 0) + vec3(1., -1.3, 0.); - p += .2 * vec3(sin(iGlobalTime / 16.), sin(iGlobalTime / 12.), sin(iGlobalTime / 128.)); - - float freqs[4]; - //Sound - freqs[0] = texture2D(iChannel0, vec2(0.01, 0.25)).x; - freqs[1] = texture2D(iChannel0, vec2(0.07, 0.25)).x; - freqs[2] = texture2D(iChannel0, vec2(0.15, 0.25)).x; - freqs[3] = texture2D(iChannel0, vec2(0.30, 0.25)).x; - - float t = field(p, freqs[2]); - float v = (1. - exp((abs(uv.x) - 1.) * 6.)) * (1. - exp((abs(uv.y) - 1.) * 6.)); - - //Second Layer - vec3 p2 = vec3(uvs / (4. + sin(iGlobalTime*0.11)*0.2 + 0.2 + sin(iGlobalTime*0.15)*0.3 + 0.4), 1.5) + vec3(2., -1.3, -1.); - p2 += 0.25 * vec3(sin(iGlobalTime / 16.), sin(iGlobalTime / 12.), sin(iGlobalTime / 128.)); - float t2 = field2(p2, freqs[3]); - vec4 c2 = mix(.4, 1., v) * vec4(1.3 * t2 * t2 * t2, 1.8 * t2 * t2, t2* freqs[0], t2); - - - //Let's add some stars - //Thanks to http://glsl.heroku.com/e#6904.0 - vec2 seed = p.xy * 2.0; - seed = floor(seed * iResolution.x); - vec3 rnd = nrand3(seed); - float tmp = pow(rnd.y, 40.0); - vec4 starcolor = vec4(tmp,tmp,tmp,tmp); - - //Second Layer - vec2 seed2 = p2.xy * 2.0; - seed2 = floor(seed2 * iResolution.x); - vec3 rnd2 = nrand3(seed2); - tmp = pow(rnd2.y, 40.0); - starcolor += vec4(tmp,tmp,tmp,tmp); - - fragColor = mix(freqs[3] - .3, 1., v) * vec4(1.5*freqs[2] * t * t* t, 1.2*freqs[1] * t * t, freqs[3] * t, 1.0) + c2 + starcolor; -} diff --git a/visualization.shadertoy/resources/volumetriclines.frag.glsl b/visualization.shadertoy/resources/volumetriclines.frag.glsl deleted file mode 100644 index 75e679b..0000000 --- a/visualization.shadertoy/resources/volumetriclines.frag.glsl +++ /dev/null @@ -1,153 +0,0 @@ -//Taken from https://www.shadertoy.com/view/4slGz4 - -// Created by inigo quilez - iq/2013 -// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. - - -vec3 hash3( float n ) -{ - return fract(sin(vec3(n,n+1.0,n+2.0))*vec3(43758.5453123,22578.1459123,19642.3490423)); -} - -vec3 snoise3( in float x ) -{ - float p = floor(x); - float f = fract(x); - - f = f*f*(3.0-2.0*f); - - return -1.0 + 2.0*mix( hash3(p+0.0), hash3(p+1.0), f ); -} - -float freqs[16]; - -vec3 distanceLines( vec3 a, vec3 b, vec3 o, vec3 d ) -{ - vec3 ba = b - a; - vec3 oa = o - a; - - float oad = dot( oa, d ); - float dba = dot( d, ba ); - float baba = dot( ba, ba ); - float oaba = dot( oa, ba ); - - vec2 th = vec2( -oad*baba + dba*oaba, oaba - oad*dba ) / (baba - dba*dba); - - th.x = max( th.x, 0.0 ); - th.y = clamp( th.y, 0.0, 1.0 ); - - vec3 p = a + ba*th.y; - vec3 q = o + d*th.x; - - return vec3( length( p-q ), th ); -} - - -vec3 castRay( vec3 ro, vec3 rd, float linesSpeed ) -{ - vec3 col = vec3(0.0,0.0,0.0); - - - float mindist = 10000.0; - vec3 p = vec3(0.2,0.2,0.2); - float h = 0.0; - float rad = 0.04 + 0.15*freqs[0]; - float mint = 0.0; - for( int i=0; i<128; i++ ) - { - vec3 op = p; - - op = p; - p = 1.25*1.0*normalize(snoise3( 64.0*h + linesSpeed*0.015*iGlobalTime )); - - vec3 dis = distanceLines( op, p, ro, rd ); - - vec3 lcol = 0.6 + 0.4*sin( 10.0*6.2831*h + vec3(0.0,0.6,0.9) ); - - float m = pow( texture2D( iChannel0, vec2(h*0.5,0.25) ).x, 2.0 )*(1.0+2.0*h); - - float f = 1.0 - 4.0*dis.z*(1.0-dis.z); - float width = 1240.0 - 1000.0*f; - width *= 0.25; - float ff = 1.0*exp(-0.06*dis.y*dis.y*dis.y); - ff *= m; - col += 0.3*lcol*exp( -0.3*width*dis.x*dis.x )*ff; - col += 0.5*lcol*exp( -8.0*width*dis.x*dis.x )*ff; - h += 1.0/128.0; - } - - - return col; -} - - - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - vec2 q = fragCoord.xy/iResolution.xy; - vec2 p = -1.0+2.0*q; - p.x *= iResolution.x/iResolution.y; - vec2 mo = iMouse.xy/iResolution.xy; - - float time = iGlobalTime; - - - for( int i=0; i<16; i++ ) - freqs[i] = clamp( 1.9*pow( texture2D( iChannel0, vec2( 0.05 + 0.5*float(i)/16.0, 0.25 ) ).x, 3.0 ), 0.0, 1.0 ); - - // camera - vec3 ta = vec3( 0.0, 0.0, 0.0 ); - -float isFast = smoothstep( 35.8, 35.81, iChannelTime[0] ); - isFast -= smoothstep( 61.8, 61.81, iChannelTime[0] ); - isFast += smoothstep( 78.0, 78.01, iChannelTime[0] ); - isFast -= smoothstep(103.0,103.01, iChannelTime[0] ); - isFast += smoothstep(140.0,140.01, iChannelTime[0] ); - isFast -= smoothstep(204.0,204.01, iChannelTime[0] ); - - float camSpeed = 1.0 + 40.0*isFast; - - - float beat = floor( max((iChannelTime[0]-35.7+0.4)/0.81,0.0) ); - time += beat*10.0*isFast; - camSpeed *= mix( 1.0, sign(sin( beat*1.0 )), isFast ); - - -float linesSpeed = smoothstep( 22.7, 22.71, iChannelTime[0] ); - linesSpeed -= smoothstep( 61.8, 61.81, iChannelTime[0] ); - linesSpeed += smoothstep( 78.0, 78.01, iChannelTime[0] ); - linesSpeed -= smoothstep(140.0,140.01, iChannelTime[0] ); - - - ta = 0.2*vec3( cos(0.1*time), 0.0*sin(0.1*time), sin(0.07*time) ); - - vec3 ro = vec3( 1.0*cos(camSpeed*0.05*time+6.28*mo.x), 0.0, 1.0*sin(camSpeed*0.05*time+6.2831*mo.x) ); - float roll = 0.25*sin(camSpeed*0.01*time); - - // camera tx - vec3 cw = normalize( ta-ro ); - vec3 cp = vec3( sin(roll), cos(roll),0.0 ); - vec3 cu = normalize( cross(cw,cp) ); - vec3 cv = normalize( cross(cu,cw) ); - vec3 rd = normalize( p.x*cu + p.y*cv + 1.2*cw ); - - float curve = smoothstep( 61.8, 71.0, iChannelTime[0] ); - curve -= smoothstep(103.0,113.0, iChannelTime[0] ); - rd.xy += curve*0.025*vec2( sin(34.0*q.y), cos(34.0*q.x) ); - rd = normalize(rd); - - - ro *= 1.0 - linesSpeed*0.5*freqs[1]; - vec3 col = castRay( ro, rd, 1.0 + 20.0*linesSpeed ); - col = 0.5*(col+col*col); - - // fade to black - col *= 1.0 - smoothstep(218.0,228.00, iChannelTime[0] ); - col *= smoothstep( 0.0, 4.00, iChannelTime[0] ); - if( iChannelTime[0]>61.8 && iChannelTime[0]<65.0 ) - col *= vec3(1.0,1.0,1.0)*clamp( (iChannelTime[0]-61.8)/(65.0-61.8), 0.0, 1.0 ); - - col *= 0.15+0.85*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.15 ); - - fragColor=vec4( col, 1.0 ); -}