From a64dbcc81e8f02193ddb1326616ff461f9c7f8fd Mon Sep 17 00:00:00 2001 From: ruofeidu Date: Sun, 17 Dec 2017 14:47:05 -0500 Subject: [PATCH] TexturesManager is done. --- .gitignore | 4 +- DuEngine/DuConfig.cpp | 16 +++-- DuEngine/DuConfig.h | 6 +- DuEngine/DuEngine.cpp | 95 +++++++----------------- DuEngine/DuEngine.h | 25 ++----- DuEngine/DuEngine.vcxproj | 2 + DuEngine/DuEngine.vcxproj.filters | 6 ++ DuEngine/DuScene.cpp | 70 +++++++----------- DuEngine/DuUtils.cpp | 8 --- DuEngine/DuUtils.h | 1 - DuEngine/GameOfLife.glsl | 17 ----- DuEngine/GameOfLife.ini | 6 -- DuEngine/GameOfLifeA.glsl | 75 ------------------- DuEngine/PathManager.cpp | 87 ++++++++++++++++++++++ DuEngine/PathManager.h | 37 ++++++++++ DuEngine/ShaderToy.cpp | 6 +- DuEngine/TexturesManager.cpp | 61 ++++++++++++++++ DuEngine/TexturesManager.h | 16 +++++ Math/ChaosGame.glsl | 116 +++++------------------------- Math/ChaosGame.ini | 5 +- Math/ChaosGameA.glsl | 37 ++++++++++ 21 files changed, 343 insertions(+), 353 deletions(-) delete mode 100644 DuEngine/GameOfLife.glsl delete mode 100644 DuEngine/GameOfLife.ini delete mode 100644 DuEngine/GameOfLifeA.glsl create mode 100644 DuEngine/PathManager.cpp create mode 100644 DuEngine/PathManager.h create mode 100644 Math/ChaosGameA.glsl diff --git a/.gitignore b/.gitignore index e2bcf15..4009dff 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,9 @@ *.log *.mp4 *.avi - +DuEngine/*.ini +DuEngine/*.glsl +DuEngine/*.cmd SHSaliency/ Friends/ diff --git a/DuEngine/DuConfig.cpp b/DuEngine/DuConfig.cpp index 9fb4d61..34cbafe 100644 --- a/DuEngine/DuConfig.cpp +++ b/DuEngine/DuConfig.cpp @@ -5,14 +5,16 @@ using namespace std; std::string DuConfig::DefaultName = "config.ini"; -DuConfig::DuConfig() { - m_bErrorIfNameNotFound = true; - Load(DefaultName); +DuConfig::DuConfig() : DuConfig(DefaultName) { } -DuConfig::DuConfig(const string &filename) { +DuConfig::DuConfig(string filename) { m_bErrorIfNameNotFound = true; Load(filename); + m_name = filename.substr(0, filename.size() - 4); + if (!m_name.compare("config")) { + m_name = "default"; + } } static string Trim(string str) { @@ -23,7 +25,7 @@ static string Trim(string str) { return str.substr(first, last - first + 1); } -bool DuConfig::Load(const string &filename) { +bool DuConfig::Load(string filename) { m_mEntries.clear(); // Open file. ifstream in(filename.c_str()); @@ -100,6 +102,10 @@ double DuConfig::GetDouble(const string &name) const { return atof(GetString(name).c_str()); } +std::string DuConfig::GetName() const { + return m_name; +} + bool DuConfig::HasKey(const string& name) const { return (m_mEntries.find(name) != m_mEntries.end()); } diff --git a/DuEngine/DuConfig.h b/DuEngine/DuConfig.h index 27d835e..17deb17 100644 --- a/DuEngine/DuConfig.h +++ b/DuEngine/DuConfig.h @@ -9,11 +9,12 @@ class DuConfig { public: static std::string DefaultName; + std::string m_name; public: DuConfig(); - DuConfig(const std::string &filename); - bool Load(const std::string &filename); + DuConfig(std::string filename); + bool Load(std::string filename); void SetErrorIfNameNotFound(bool error) { m_bErrorIfNameNotFound = error; } @@ -23,6 +24,7 @@ class DuConfig int GetInt(const std::string &name) const; float GetFloat(const std::string &name) const; double GetDouble(const std::string &name) const; + std::string GetName() const; public: std::vector GetKeyList() const; diff --git a/DuEngine/DuEngine.cpp b/DuEngine/DuEngine.cpp index 6900cce..3bf473e 100644 --- a/DuEngine/DuEngine.cpp +++ b/DuEngine/DuEngine.cpp @@ -23,6 +23,7 @@ DuEngine::GC DuEngine::gc; DuEngine::DuEngine() { camera = new Camera(); m_window = Window::GetInstance(); + m_textureManager = new TexturesManager(); } DuEngine* DuEngine::GetInstance() { @@ -86,51 +87,22 @@ void g_reshape(int width, int height) { void DuEngine::start(int argc, char* argv[]) { // setup configuration files and the scene name - if (argc > 1) { - m_configName = std::string(argv[1]); - config = new DuConfig(m_configName); - m_sceneName = m_configName.substr(0, m_configName.size() - 4); - } else { - config = new DuConfig(DuConfig::DefaultName); - m_sceneName = "default"; - } - - // setup shaders path and presets path - m_shadersPath = std::string(argv[0]); - - // automatically search the default shader path from the upper-level folders - for (int i = 3; i >= 0; --i) { - if (i == 0) { - m_shadersPath = ""; - } else { - auto keywords = repeatstring("../", i) + "DuEngine/"; - if (m_shadersPath.find(keywords) != std::string::npos) { - m_shadersPath = keywords; - break; - } - } - } - m_shadersPath = config->GetStringWithDefault("shaders_path", m_shadersPath); -#if VERBOSE_OUTPUT - if (m_shadersPath.size() > 0) { - info("Relative Path: " + m_shadersPath); - } -#endif - m_presetsPath = config->GetStringWithDefault("presets_path", m_shadersPath + "presets/"); - m_resourcesPath = config->GetStringWithDefault("resources_path", m_presetsPath); - + m_config = argc > 1 ? new DuConfig(std::string(argv[1])) : new DuConfig(); + m_path = new PathManager(std::string(argv[0]), m_config); + // setup the default m_window width and height - m_defaultWidth = config->GetIntWithDefault("window_width", m_defaultWidth); - m_defaultHeight = config->GetIntWithDefault("window_height", m_defaultHeight); - string _windowTitle = config->GetStringWithDefault("window_title", "DuRenderer | " + m_sceneName); + m_defaultWidth = m_config->GetIntWithDefault("window_width", m_defaultWidth); + m_defaultHeight = m_config->GetIntWithDefault("window_height", m_defaultHeight); + string _windowTitle = m_config->GetStringWithDefault("window_title", "DuRenderer | " + m_config->GetName()); m_window->init(argc, argv, m_defaultWidth, m_defaultHeight, _windowTitle); // setup recording - m_recording = config->GetBoolWithDefault("recording", m_recording); - m_recordPath = config->GetStringWithDefault("record_path", m_sceneName); - m_recordStart = config->GetIntWithDefault("record_start", m_recordStart); - m_recordEnd = config->GetIntWithDefault("record_end", m_recordEnd); - m_recordVideo = config->GetBoolWithDefault("record_video", m_recordVideo); + m_recording = m_config->GetBoolWithDefault("recording", m_recording); + m_recordPath = m_config->GetStringWithDefault("record_path", m_config->GetName()); + m_recordStart = m_config->GetIntWithDefault("record_start", m_recordStart); + m_recordEnd = m_config->GetIntWithDefault("record_end", m_recordEnd); + m_recordVideo = m_config->GetBoolWithDefault("record_video", m_recordVideo); + // initialize the scene, shaders, and presets initScene(); @@ -157,10 +129,7 @@ void DuEngine::keyboard(unsigned char key, int x, int y, bool up) { break; } } - - if (keyboardTexture) { - keyboardTexture->onKeyPress(key, up); - } + m_textureManager->updateKeyboard(key, up); } void DuEngine::special(int key, int x, int y, bool up) { @@ -174,17 +143,19 @@ void DuEngine::special(int key, int x, int y, bool up) { case GLUT_KEY_F2: // Take screenshot - this->takeScreenshot(); + m_takeSingleScreenShot = true; break; case GLUT_KEY_F5: m_shadertoy->recompile(); break; case GLUT_KEY_F6: - // Video Pause - for (const auto& t : videoTextures) { - t->togglePaused(); - } + m_textureManager->togglePause(); + case GLUT_KEY_F9: + // Debug iFrame + debug(to_string(getFrameNumber())); + break; + case GLUT_KEY_F10: // Debug Mouse debug(ShaderToyUniforms::GetMouseString()); @@ -195,14 +166,7 @@ void DuEngine::special(int key, int x, int y, bool up) { break; } } - if (keyboardTexture) { - keyboardTexture->onKeyPress(key, up); - // hack the four arrows for ShaderToy - if (100 <= key && key <= 103) { - key -= 63; - } - keyboardTexture->onKeyPress(key, up); - } + m_textureManager->updateKeyboard(key, up); } void DuEngine::mousePress(int button, int state, int x, int y) { @@ -236,23 +200,12 @@ void DuEngine::toggleFullScreen() { } } -int DuEngine::getNumFrameFromVideos() { - int ans = 0; - for (const auto &v : videoTextures) { - ans = std::max(ans, v->getNumVideoFrame()); - } - return ans; -} - void DuEngine::printHelp() { info("Help:\n\tF1:\tReset everything.\n\tF2:\tTake Screenshot.\n\tF5:\tReset Time\n\tF6:\tPause\n\tF11:\tFullscreen.\n"); } void DuEngine::takeScreenshot(string folderName) { - if (m_isPathCreated.find(folderName) == m_isPathCreated.end()) { - CreateDirectory(folderName.c_str(), NULL); - m_isPathCreated.insert(folderName); - } + m_path->createPathIfNotExisted(folderName); if (m_recordVideo) { if (m_video == nullptr) { @@ -275,7 +228,7 @@ void DuEngine::takeScreenshot(string folderName) { m_video->release(); } } else { - cv::imwrite(folderName + "/" + this->m_configName.substr(0, m_configName.size() - 4) + "_" + to_string(getFrameNumber()) + ".png", img); + cv::imwrite(folderName + "/" + m_config->GetName() + "_" + to_string(getFrameNumber()) + ".png", img); } } diff --git a/DuEngine/DuEngine.h b/DuEngine/DuEngine.h index d52ccea..83fd9fd 100644 --- a/DuEngine/DuEngine.h +++ b/DuEngine/DuEngine.h @@ -3,6 +3,7 @@ #include "ShaderToy.h" #include "DuConfig.h" #include "TexturesManager.h" +#include "PathManager.h" #include "Camera.h" #include "Window.h" #include "DuUtils.h" @@ -19,10 +20,6 @@ void g_reshape(int width, int height); class DuEngine { friend class ShaderToy; - friend class Texture; - friend class TextureVideo; - friend class TextureKeyboard; - friend class TextureSH; public: static DuEngine *GetInstance(); @@ -31,11 +28,7 @@ class DuEngine protected: TexturesManager* m_textureManager; - - vector videoTextures; - TextureKeyboard* keyboardTexture; - Texture* fontTexture; - vector textures; + PathManager* m_path; public: void render(); @@ -48,7 +41,7 @@ class DuEngine void reshape(int width, int height); int getFrameNumber(); - string getPresetsPath() { return m_presetsPath; } + string getPresetsPath() { return m_path->getPresetPath(); } private: DuEngine(); @@ -57,18 +50,11 @@ class DuEngine Camera* camera; Window* m_window; ShaderToy* m_shadertoy; - DuConfig* config; - string m_configName; - string m_sceneName; + DuConfig* m_config; bool m_fullscreen = false; bool m_recording = false; bool m_paused = false; - string m_shadersPath = ""; - string m_presetsPath = ""; - string m_resourcesPath = ""; - unordered_set m_isPathCreated; - string m_recordPath = ""; int m_recordStart = 0; int m_recordEnd = 100; @@ -76,12 +62,11 @@ class DuEngine cv::VideoWriter* m_video = nullptr; int m_defaultWidth = 1280; int m_defaultHeight = 720; + bool m_takeSingleScreenShot = false; private: void toggleFullScreen(); - int getNumFrameFromVideos(); - void printHelp(); class GC diff --git a/DuEngine/DuEngine.vcxproj b/DuEngine/DuEngine.vcxproj index 3841b37..b08c625 100644 --- a/DuEngine/DuEngine.vcxproj +++ b/DuEngine/DuEngine.vcxproj @@ -135,6 +135,7 @@ + @@ -170,6 +171,7 @@ + diff --git a/DuEngine/DuEngine.vcxproj.filters b/DuEngine/DuEngine.vcxproj.filters index 596e954..8f4f15c 100644 --- a/DuEngine/DuEngine.vcxproj.filters +++ b/DuEngine/DuEngine.vcxproj.filters @@ -165,6 +165,9 @@ Source Files\Uniforms + + Source Files + @@ -263,6 +266,9 @@ Header Files\FrameBuffer + + Header Files\Utils + diff --git a/DuEngine/DuScene.cpp b/DuEngine/DuScene.cpp index 8ace39f..b7eeab0 100644 --- a/DuEngine/DuScene.cpp +++ b/DuEngine/DuScene.cpp @@ -16,72 +16,53 @@ void DuEngine::initScene() { m_shadertoy = new ShaderToy(DuEngine::GetInstance()); - auto vertexShaderName = config->GetStringWithDefault("shader_vert", m_shadersPath + "shadertoy.vert.glsl"); - auto uniformShaderName = config->GetStringWithDefault("shader_uniform", m_shadersPath + "shadertoy.uniforms.glsl"); - auto mainShaderName = config->GetStringWithDefault("shader_main", m_shadersPath + "shadertoy.main.glsl"); + auto vertexShaderName = m_path->getVertexShader(); + auto uniformShaderName = m_path->getUniformShader(); + auto mainShaderName = m_path->getMainShader(); for (int buffer = 0; buffer < 1 + m_shadertoy->getNumFrameBuffers(); ++buffer) { auto suffix = !buffer ? "" : string(1, char('A' + buffer - 1)); auto prefix = !buffer ? "" : suffix + "_"; auto fbo = m_shadertoy->getBuffer(buffer); ShaderToyUniforms* uniforms = (ShaderToyUniforms*)(fbo->getUniforms()); - - // replace the fragment shader name with $Name and buffer prefix / suffix - auto fragmentShaderName = config->GetStringWithDefault("shader_frag", m_shadersPath + "shadertoy.default.glsl"); - if (fragmentShaderName.find("$Name") != string::npos) { - fragmentShaderName.replace(fragmentShaderName.find("$Name"), 5, m_sceneName); - } - if (fragmentShaderName.find(".glsl") != string::npos) { - // add framebuffer suffix for multipass rendering - fragmentShaderName.replace(fragmentShaderName.find(".glsl"), 5, suffix + ".glsl"); - } else { - fragmentShaderName += suffix + ".glsl"; - } - + auto fragmentShaderName = m_path->getFragmentShader(suffix); fbo->loadShadersLinkUniforms(vertexShaderName, fragmentShaderName, uniformShaderName, mainShaderName); // bind channel textures - auto channels_count = config->GetIntWithDefault(prefix + "channels_count", 0); + auto channels_count = m_config->GetIntWithDefault(prefix + "channels_count", 0); for (int i = 0; i < channels_count; ++i) { string iPrefix = prefix + "iChannel" + to_string(i) + "_"; - auto type = config->GetStringWithDefault(iPrefix + "type", "unknown"); + auto type = m_config->GetStringWithDefault(iPrefix + "type", "unknown"); std::transform(type.begin(), type.end(), type.begin(), ::tolower); - auto fileName = smartFilePath(config->GetStringWithDefault(iPrefix + "tex", ""), m_resourcesPath); - Texture::QueryFileNameByType(type, fileName, m_presetsPath); + auto fileName = m_path->getResource(iPrefix + "tex"); + Texture::QueryFileNameByType(type, fileName, m_path->getPresetPath()); auto textureType = Texture::QueryType(type); - auto textureFilter = Texture::QueryFilter(config->GetStringWithDefault(iPrefix + "filter", "mipmap")); - auto textureWarp = Texture::QueryWarp(config->GetStringWithDefault(iPrefix + "wrap", "repeat")); - auto vFlip = config->GetBoolWithDefault(iPrefix + "vflip", true); - auto fps = config->GetIntWithDefault(iPrefix + "fps", 25); - auto startFrame = config->GetIntWithDefault(iPrefix + "startFrame", 1); - auto endFrame = config->GetIntWithDefault(iPrefix + "endFrame", 100); + auto textureFilter = Texture::QueryFilter(m_config->GetStringWithDefault(iPrefix + "filter", "mipmap")); + auto textureWarp = Texture::QueryWarp(m_config->GetStringWithDefault(iPrefix + "wrap", "repeat")); + auto vFlip = m_config->GetBoolWithDefault(iPrefix + "vflip", true); + auto fps = m_config->GetIntWithDefault(iPrefix + "fps", 25); + auto startFrame = m_config->GetIntWithDefault(iPrefix + "startFrame", 1); + auto endFrame = m_config->GetIntWithDefault(iPrefix + "endFrame", 100); Texture* t = nullptr; switch (textureType) { case TextureType::Noise: - vFlip = config->GetBoolWithDefault(iPrefix + "vflip", false); + vFlip = m_config->GetBoolWithDefault(iPrefix + "vflip", false); case TextureType::RGB: - t = new Texture2D(fileName, vFlip, textureFilter, textureWarp); + t = m_textureManager->addTexture2D(fileName, vFlip, textureFilter, textureWarp); break; case TextureType::VideoFile: - t = new TextureVideoFile(fileName, vFlip, textureFilter, textureWarp); - videoTextures.push_back((TextureVideo*)t); + t = m_textureManager->addVideoFile(fileName, vFlip, textureFilter, textureWarp); break; case TextureType::VideoSequence: - t = new TextureVideoSequence(fileName, fps, startFrame, endFrame, textureFilter, textureWarp); - videoTextures.push_back((TextureVideo*)t); + t = m_textureManager->addVideoSequence(fileName, fps, startFrame, endFrame, textureFilter, textureWarp); break; case TextureType::Keyboard: - if (!keyboardTexture) - keyboardTexture = new TextureKeyboard(); - t = keyboardTexture; + t = m_textureManager->addKeyboard(); break; case TextureType::Font: - if (!fontTexture) { - fontTexture = new TextureFont(textureFilter, textureWarp); - } - t = fontTexture; + t = m_textureManager->addFont(textureFilter, textureWarp); break; case TextureType::FrameBuffer: int bufferID = (int)(type[0] - 'a'); @@ -101,12 +82,11 @@ void DuEngine::initScene() { } } - auto vec2_buffers_count = config->GetIntWithDefault("vec2_buffers_count", 0); + auto vec2_buffers_count = m_config->GetIntWithDefault("vec2_buffers_count", 0); uniforms->intVec2Buffers(vec2_buffers_count); for (int i = 0; i < vec2_buffers_count; ++i) { - string s = "vec2_buffers" + to_string(i) + "_file"; - auto fileName = smartFilePath(config->GetString(s), m_resourcesPath); + auto fileName = m_path->getResource("vec2_buffers" + to_string(i) + "_file"); uniforms->bindVec2Buffer(i, fileName); } } @@ -120,7 +100,7 @@ int DuEngine::getFrameNumber() { void DuEngine::render() { if (!m_paused) { - for (const auto& v : videoTextures) v->update(); + m_textureManager->update(); m_shadertoy->render(); glutSwapBuffers(); @@ -130,6 +110,10 @@ void DuEngine::render() { if (m_recording && m_recordStart <= getFrameNumber() && getFrameNumber() <= m_recordEnd) { this->takeScreenshot(m_recordPath); } + if (m_takeSingleScreenShot) { + m_takeSingleScreenShot = false; + this->takeScreenshot(); + } } void DuEngine::updateFPS(float timeDelta, float averageTimeDelta) { diff --git a/DuEngine/DuUtils.cpp b/DuEngine/DuUtils.cpp index da40e2d..d04ecb2 100644 --- a/DuEngine/DuUtils.cpp +++ b/DuEngine/DuUtils.cpp @@ -61,14 +61,6 @@ string repeatstring(string s, int cnt) { return res; } -string smartFilePath(string fileName, string path) { - if (fileName.size() > 2 && fileName[1] == ':') { - return fileName; - } else { - return path + fileName; - } -} - void onError() { system("pause"); exit(EXIT_FAILURE); diff --git a/DuEngine/DuUtils.h b/DuEngine/DuUtils.h index 3a018f4..951460a 100644 --- a/DuEngine/DuUtils.h +++ b/DuEngine/DuUtils.h @@ -12,7 +12,6 @@ void onError(); // file systems bool dirExists(const std::string& dirName_in); string getTimeForFileName(); -string smartFilePath(string fileName, string path); // string utilities string repeatstring(string s, int cnt); diff --git a/DuEngine/GameOfLife.glsl b/DuEngine/GameOfLife.glsl deleted file mode 100644 index d92bee3..0000000 --- a/DuEngine/GameOfLife.glsl +++ /dev/null @@ -1,17 +0,0 @@ -// https://www.shadertoy.com/view/XstGRf -// Created by inigo quilez - iq/2016 -// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 - -float hash1( float n ) -{ - return fract(sin(n)*138.5453123); -} - - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - fragColor = vec4( texelFetch( iChannel0, ivec2(fragCoord), 0 ).xxx, 1.0 ); - - //float f = step(0.5, hash1(fragCoord.x*13.0+hash1(fragCoord.y*71.1))); - //fragColor.r = f; -} \ No newline at end of file diff --git a/DuEngine/GameOfLife.ini b/DuEngine/GameOfLife.ini deleted file mode 100644 index fc254c9..0000000 --- a/DuEngine/GameOfLife.ini +++ /dev/null @@ -1,6 +0,0 @@ -shader_frag = $Name.glsl -channels_count = 1 -buffers_count = 1 -iChannel0_type = A -A_channels_count = 1 -A_iChannel0_type = A diff --git a/DuEngine/GameOfLifeA.glsl b/DuEngine/GameOfLifeA.glsl deleted file mode 100644 index b12e194..0000000 --- a/DuEngine/GameOfLifeA.glsl +++ /dev/null @@ -1,75 +0,0 @@ - -// Created by inigo quilez - iq/2016 -// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 - - -// Conway's Game of Life - http://www.iquilezles.org/www/articles/gameoflife/gameoflife.htm -// -// State based simulation. Buffer A contains the simulated world, and it reads and writes to -// itself to perform the simulation. -// -// I implemented three variants of the algorithm with different interpretations - -// VARIANT = 0: traditional -// VARIANT = 1: box fiter -// VARIANT = 2: high pass filter - -#define VARIANT 0 - - -int Cell( in ivec2 p ) -{ - // do wrapping - ivec2 r = ivec2(textureSize(iChannel0, 0)); - p = (p+r) % r; - - // fetch texel - return (texelFetch(iChannel0, p, 0 ).x > 0.5 ) ? 1 : 0; -} - -float hash1( float n ) -{ - return fract(sin(n)*138.5453123); -} - -void mainImage( out vec4 fragColor, in vec2 fragCoord ) -{ - ivec2 px = ivec2( fragCoord ); - -#if VARIANT==0 - int k = Cell(px+ivec2(-1,-1)) + Cell(px+ivec2(0,-1)) + Cell(px+ivec2(1,-1)) - + Cell(px+ivec2(-1, 0)) + Cell(px+ivec2(1, 0)) - + Cell(px+ivec2(-1, 1)) + Cell(px+ivec2(0, 1)) + Cell(px+ivec2(1, 1)); - - int e = Cell(px); - - float f = ( ((k==2)&&(e==1)) || (k==3) ) ? 1.0 : 0.0; - -#endif - -#if VARIANT==1 - int k = Cell(px+ivec2(-1,-1)) + Cell(px+ivec2(0,-1)) + Cell(px+ivec2(1,-1)) - + Cell(px+ivec2(-1, 0)) + Cell(px ) + Cell(px+ivec2(1, 0)) - + Cell(px+ivec2(-1, 1)) + Cell(px+ivec2(0, 1)) + Cell(px+ivec2(1, 1)); - - int e = Cell(px); - - float f = ( ((k==4)&&(e==1)) || (k==3) ) ? 1.0 : 0.0; - -#endif - - -#if VARIANT==2 - int k = -Cell(px+ivec2(-1,-1)) - Cell(px+ivec2(0,-1)) - Cell(px+ivec2(1,-1)) - -Cell(px+ivec2(-1, 0)) + 8*Cell(px) - Cell(px+ivec2(1, 0)) - -Cell(px+ivec2(-1, 1)) - Cell(px+ivec2(0, 1)) - Cell(px+ivec2(1, 1)); - - float f = (abs(k+3)*abs(2*k-11)<=9) ? 1.0 : 0.0; - - -#endif - - if( iFrame < 4 ) f = step(0.5, hash1(fragCoord.x*13.0+hash1(fragCoord.y*71.1))); - - fragColor = vec4( f, 0.0, 0.0, 0.0 ); -} \ No newline at end of file diff --git a/DuEngine/PathManager.cpp b/DuEngine/PathManager.cpp new file mode 100644 index 0000000..85ff99b --- /dev/null +++ b/DuEngine/PathManager.cpp @@ -0,0 +1,87 @@ +#include "stdafx.h" +#include "PathManager.h" +#include "DuUtils.h" + +PathManager::PathManager(string executionPath, DuConfig* config) { + // setup shaders path and presets path + m_shadersPath = executionPath; + m_config = config; + + // automatically search the default shader path from the upper-level folders + for (int i = 3; i >= 0; --i) { + if (i == 0) { + m_shadersPath = ""; + } else { + auto keywords = repeatstring("../", i) + "DuEngine/"; + if (m_shadersPath.find(keywords) != string::npos) { + m_shadersPath = keywords; + break; + } + } + } + m_shadersPath = config->GetStringWithDefault("shaders_path", m_shadersPath); +#if VERBOSE_OUTPUT + if (m_shadersPath.size() > 0) { + info("Relative Path: " + m_shadersPath); + } +#endif + m_presetsPath = config->GetStringWithDefault("presets_path", m_shadersPath + "presets/"); + m_resourcesPath = config->GetStringWithDefault("resources_path", m_presetsPath); +} + +string PathManager::getShader(string str) { + return m_shadersPath + str; +} + +string PathManager::getPreset(string str) { + return m_presetsPath + str; +} + +string PathManager::getResource(string str) { + auto fileName = m_config->GetStringWithDefault(str, ""); + return smartPath(m_resourcesPath, fileName); +} + +string PathManager::getVertexShader() { + return m_config->GetStringWithDefault("shader_vert", m_shadersPath + "shadertoy.vert.glsl"); +} + +string PathManager::getUniformShader() { + return m_config->GetStringWithDefault("shader_uniform", m_shadersPath + "shadertoy.uniforms.glsl"); +} + +string PathManager::getMainShader() { + return m_config->GetStringWithDefault("shader_main", m_shadersPath + "shadertoy.main.glsl"); +} + +string PathManager::getFragmentShader(string bufferSuffix) { + auto res = m_config->GetStringWithDefault("shader_frag", m_shadersPath + "shadertoy.default.glsl"); + if (res.find("$Name") != string::npos) { + res.replace(res.find("$Name"), 5, m_config->GetName()); + } + if (res.find(".glsl") != string::npos) { + // add framebuffer suffix for multipass rendering + res.replace(res.find(".glsl"), 5, bufferSuffix + ".glsl"); + } else { + res += bufferSuffix + ".glsl"; + } + return res; +} + +void PathManager::createPathIfNotExisted(const string & str) { + if (isPathCreated(str)) return; + CreateDirectory(str.c_str(), NULL); + m_isPathCreated.insert(str); +} + +bool PathManager::isPathCreated(const string & str) { + return m_isPathCreated.find(str) != m_isPathCreated.end(); +} + +string PathManager::smartPath(string path, string fileName) { + if (fileName.size() > 2 && fileName[1] == ':') { + return fileName; + } else { + return path + fileName; + } +} diff --git a/DuEngine/PathManager.h b/DuEngine/PathManager.h new file mode 100644 index 0000000..40597a4 --- /dev/null +++ b/DuEngine/PathManager.h @@ -0,0 +1,37 @@ +#pragma once +#include "stdafx.h" +#include "DuConfig.h" + +using namespace std; + +class PathManager +{ +public: + PathManager(string executionPath, DuConfig* config); + + string getShaderPath() { return m_shadersPath; }; + string getPresetPath() { return m_presetsPath; }; + string getResourcePath() { return m_resourcesPath; }; + + string getShader(string str); + string getPreset(string str); + string getResource(string str); + string getVertexShader(); + string getUniformShader(); + string getMainShader(); + // replace the fragment shader name with $Name and buffer prefix / suffix + string getFragmentShader(string bufferSuffix); + + void createPathIfNotExisted(const string &str); + +private: + DuConfig* m_config; + string m_shadersPath = ""; + string m_presetsPath = ""; + string m_resourcesPath = ""; + unordered_set m_isPathCreated; + bool isPathCreated(const string &str); + +private: + string smartPath(string fileName, string path); +}; diff --git a/DuEngine/ShaderToy.cpp b/DuEngine/ShaderToy.cpp index c4bf2cd..8b2d0fe 100644 --- a/DuEngine/ShaderToy.cpp +++ b/DuEngine/ShaderToy.cpp @@ -11,13 +11,13 @@ ShaderToy::ShaderToy(DuEngine * _renderer, double _width, double _height, int _x0, double _y0) { auto geometry = new ShaderToyGeometry(_width, _height, _x0, _y0); - auto numChannels = _renderer->config->GetIntWithDefault("channels_count", 0); + auto numChannels = _renderer->m_config->GetIntWithDefault("channels_count", 0); m_screenBuffer = new ShaderToyScreenBuffer(geometry, numChannels); - auto buffers_count = _renderer->config->GetIntWithDefault("buffers_count", 0); + auto buffers_count = _renderer->m_config->GetIntWithDefault("buffers_count", 0); for (int i = 0; i < buffers_count; ++i) { auto prefix = string(1, char('A' + i)); - auto numChannels = _renderer->config->GetIntWithDefault(prefix + "_channels_count", 0); + auto numChannels = _renderer->m_config->GetIntWithDefault(prefix + "_channels_count", 0); m_frameBuffers.push_back(new ShaderToyFrameBuffer(geometry, numChannels)); } #if VERBOSE_OUTPUT diff --git a/DuEngine/TexturesManager.cpp b/DuEngine/TexturesManager.cpp index 8d11a2c..efa983b 100644 --- a/DuEngine/TexturesManager.cpp +++ b/DuEngine/TexturesManager.cpp @@ -6,9 +6,70 @@ TexturesManager* TexturesManager::GetInstance() { return s_Instance; } +void TexturesManager::update() { + for (const auto& v : m_videos) v->update(); +} + void TexturesManager::reset() { } +void TexturesManager::togglePause() { + for (const auto& t : m_videos) { + t->togglePaused(); + } +} + +void TexturesManager::updateKeyboard(unsigned char key, bool up) { + if (!m_keyboard) return; + + m_keyboard->onKeyPress(key, up); + // hack the four arrows for ShaderToy + if (100 <= key && key <= 103) { + key -= 63; + } + else + // hack the capitalization of a-z + if (65 <= key && key <= 90) { + key += 97 - 65; + } + if (97 <= key && key <= 122) { + key -= 97 - 65; + } + + m_keyboard->onKeyPress(key, up); +} + +Texture * TexturesManager::addVideoFile(string filename, bool vflip, TextureFilter filter, TextureWarp warp) { + auto t = new TextureVideoFile(filename, vflip, filter, warp); + addVideoTexture((TextureVideo*)t); + return t; +} + +Texture * TexturesManager::addVideoSequence(string fileName, int fps, int startFrame, int endFrame, TextureFilter filter, TextureWarp warp) { + auto t = new TextureVideoSequence(fileName, fps, startFrame, endFrame, filter, warp); + addVideoTexture((TextureVideo*)t); + return t; +} + +Texture * TexturesManager::addTexture2D(string fileName, bool vFlip, TextureFilter filter, TextureWarp warp) { + auto t = new Texture2D(fileName, vFlip, filter, warp); + return t; +} + +Texture * TexturesManager::addKeyboard() { + if (!m_keyboard) m_keyboard = new TextureKeyboard(); + return m_keyboard; +} + +Texture * TexturesManager::addFont(TextureFilter filter, TextureWarp warp) { + if (!m_font) m_font = new TextureFont(filter, warp); + return m_font; +} + +void TexturesManager::addVideoTexture(TextureVideo * tex) { + m_videos.push_back(tex); +} + TexturesManager *TexturesManager::s_Instance = new TexturesManager(); TexturesManager::GC TexturesManager::gc; diff --git a/DuEngine/TexturesManager.h b/DuEngine/TexturesManager.h index 1779579..fde1cfa 100644 --- a/DuEngine/TexturesManager.h +++ b/DuEngine/TexturesManager.h @@ -17,10 +17,26 @@ class TexturesManager { public: + TexturesManager() {}; static TexturesManager *GetInstance(); + void update(); void reset(); + void togglePause(); + void updateKeyboard(unsigned char key, bool up); + + Texture* addKeyboard(); + Texture* addFont(TextureFilter filter, TextureWarp warp); + Texture* addVideoFile(string fileName, bool vFlip, TextureFilter filter, TextureWarp warp); + Texture* addVideoSequence(string fileName, int fps, int startFrame, int endFrame, TextureFilter filter, TextureWarp warp); + Texture* addTexture2D(string fileName, bool vFlip, TextureFilter filter, TextureWarp warp); private: + void addVideoTexture(TextureVideo* tex); + vector m_videos; + TextureKeyboard* m_keyboard; + Texture* m_font; + vector m_textures; + static TexturesManager *s_Instance; class GC diff --git a/Math/ChaosGame.glsl b/Math/ChaosGame.glsl index 6c28255..620130d 100644 --- a/Math/ChaosGame.glsl +++ b/Math/ChaosGame.glsl @@ -1,109 +1,25 @@ -// https://www.shadertoy.com/view/4tfBWX -// Radius of points being drawn -const float RADIUS = 1.0; +/* -// Offset from image border -const float OFFSET = 10.0; +This shader is an attempt to rewrite dbrgn's shader +in a shorter and more efficient way, by utilizing +one of Shadertoys buffers. -// Seed for hash function -const vec2 SEED = vec2(0.5, 0.7); +He does a great job explaining, what's going on and +I highly suggest you go check out his shader +before you go any further! -// Speed: Number of points per second -const float SPEED = 50.0; +https://www.shadertoy.com/view/4tfBWX -// Starting points -#define A scale(vec2(0.5, 1.0)) -#define B scale(vec2(1.0, 0.0)) -#define C scale(vec2(0.0, 0.0)) +All the magic is in Buffer A... This layer is boring... -/** - * Scale coordinates between 0.1 to the output image resolution, with the specified border offset. - */ -vec2 scale(vec2 coords) { - return coords * (iResolution.xy - OFFSET * 2.0) + OFFSET; -} +PS: The shader goes a bit funny if you resize it, +but it should go back to normal after about 3 seconds. -/** - * Return whether the `fragCoord` pair is within `RADIUS` of `point`. - */ -bool isPixel(vec2 fragCoord, vec2 point) { - return distance(fragCoord, point) < RADIUS; -} +*/ -/** - * Random function from http://shadertoy.wikia.com/wiki/Noise - */ -vec2 rand(vec2 p) { - return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); -} - -/** - * Randomly choose a point A, B or C with 1/3 probability. - */ -vec2 randABC(vec2 seed) { - vec2 r = rand(seed); - if (r.x < (1.0/3.0)) { - return A; - } else if (r.x < (1.0/3.0*2.0)) { - return B; - } else { - return C; - } -} - -/** - * Return whether the `fragCoord` coordinate pair is a valid point in the - * sequence of points derived from the `start` point. - */ -bool validPoint(vec2 fragCoord, vec2 start) { - int iteration = int(iTime * SPEED); // Add 1 point per second - - if (isPixel(fragCoord, start)) { - return true; - } - - // We start at the starting point - vec2 currentPoint = start; - - // Increment every second - for (int i = 0; i < iteration; i++) { - // First, derive a different seed for each iteration. - vec2 seed = vec2(float(i) * 0.001, float(i) * 0.002 / 3.0); - vec2 targetPoint = randABC(seed); - currentPoint = currentPoint + ((targetPoint - currentPoint) / 2.0); - if (isPixel(fragCoord, currentPoint)) { - return true; - } - } - - return false; -} - -void mainImage(out vec4 fragColor, in vec2 fragCoord) +void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - vec4 red = vec4(1.0, 0.0, 0.0, 1.0); - vec4 white = vec4(1.0, 1.0, 1.0, 1.0); - vec4 black = vec4(0.0, 0.0, 0.0, 1.0); - vec4 color = vec4(fragCoord.xy / iResolution.xy * 1.4, 1.0, 1.0); // Nicer colors depending on XY coords - - // Random starting point - vec2 R = scale(rand(SEED)); - - // Determine whether this is a start point - bool isStartPoint = - isPixel(fragCoord, A) || - isPixel(fragCoord, B) || - isPixel(fragCoord, C); - - // Determine whether this is a valid point (depending on time) - bool isValidPoint = - validPoint(fragCoord, R); - - if (isStartPoint) { - fragColor = red; - } else if (isValidPoint) { - fragColor = color; - } else { - fragColor = black; - } + vec2 uv = fragCoord.xy / iResolution.xy; + fragColor = step(.5, texture(iChannel0, uv)); + fragColor *= vec4(1.4*uv, 1.0, 1.0); } \ No newline at end of file diff --git a/Math/ChaosGame.ini b/Math/ChaosGame.ini index 4b076e6..47ccee1 100644 --- a/Math/ChaosGame.ini +++ b/Math/ChaosGame.ini @@ -1,3 +1,6 @@ shader_frag = $Name.glsl channels_count = 1 -iChannel0_type = London +iChannel0_type = A +buffers_count = 1 +A_channels_count = 1 +A_iChannel0_type = A diff --git a/Math/ChaosGameA.glsl b/Math/ChaosGameA.glsl new file mode 100644 index 0000000..9008cf9 --- /dev/null +++ b/Math/ChaosGameA.glsl @@ -0,0 +1,37 @@ +// https://www.shadertoy.com/view/XtXBWf +// Define the three points of the triangle (Rule 1) +const int len = 3; +const vec2 points[len] = vec2[len]( + vec2(.5, .9), vec2(.2, .1), vec2(.8, .1) +); + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + // Restore last frame + vec2 uv = fragCoord.xy / iResolution.xy; + fragColor = texture(iChannel0, uv); + + + // Setup-if-statement: + // Resets the scene every 3 seconds. + // (in case this shader runs at 60 fps, which it most likely will) + if(iFrame % 180 < 2) + { + fragColor = vec4(.0); + float d = 2. / iResolution.y; + + // Draws a random starting point. (Rule 2) + // (starting point is always drawn in the middle, + // but it does work with every point, on the canvas!) + uv = (2.*uv-1.) / vec2(1.,iResolution.x/iResolution.y); + fragColor += 1.-step(d, length(uv)); + //fragColor += 1.-step(d, length(uv)); + + return; + } + + + // Checks, whether uv is inbetween one of the endpoints and + // a point, which has been drawn previously. (Rule 3, but backwards) + fragColor += texture(iChannel0, 2.*(uv-points[iFrame%len]/2.)); +} \ No newline at end of file