diff --git a/src/libprojectM/Renderer/HLSLTranslator.cpp b/src/libprojectM/Renderer/HLSLTranslator.cpp deleted file mode 100644 index 94a2ac04e..000000000 --- a/src/libprojectM/Renderer/HLSLTranslator.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef HLSLTRANSLATOR_CPP_ -#define HLSLTRANSLATOR_CPP_ - -#include -#include -#include - -#include "HLSLTranslator.hpp" - -using namespace M4; - - -std::string HLSLTranslator::parse(const std::string & shaderType, const char *fileName, const std::string &fullSource) { - // alloc - GLSLGenerator generator; - Allocator allocator; - - HLSLTree tree( &allocator ); - HLSLParser parser(&allocator, &tree); - - // preprocess define macros - std::string sourcePreprocessed; - parser.ApplyPreprocessor(fileName, fullSource.c_str(), fullSource.size(), sourcePreprocessed); - - // parse - if( !parser.Parse(fileName, sourcePreprocessed.c_str(), sourcePreprocessed.size()) ) { - std::cerr << "Failed to parse HLSL (" << shaderType << ") shader" << std::endl; - -#ifndef DUMP_SHADERS_ON_ERROR - std::cerr << "Source: " << std::endl << sourcePreprocessed << std::endl; -#else - std::ofstream out("/tmp/shader_" + shaderType + ".txt"); - out << fullSource; - out.close(); - - std::ofstream out2("/tmp/shader_preproc_" + shaderType + ".txt"); - out2 << sourcePreprocessed; - out2.close(); -#endif - return std::string(); - } - - // generate GLSL - if (!generator.Generate(&tree, GLSLGenerator::Target_FragmentShader, GLSLGenerator::Version_140, "PS")) { - std::cerr << "Failed to transpile HLSL (" << shaderType << ") shader to GLSL" << std::endl; -#ifndef DUMP_SHADERS_ON_ERROR - std::cerr << "Source: " << std::endl << sourcePreprocessed << std::endl; -#else - std::ofstream out2("/tmp/shader_preproc_" + shaderType + ".txt"); - out2 << sourcePreprocessed; - out2.close(); -#endif - return std::string(); - } - - return std::string(generator.GetResult()); -} - - -#endif diff --git a/src/libprojectM/Renderer/HLSLTranslator.hpp b/src/libprojectM/Renderer/HLSLTranslator.hpp deleted file mode 100644 index a965a84c9..000000000 --- a/src/libprojectM/Renderer/HLSLTranslator.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * HLSLTranslator - * - * Translate HLSL (aka directX shader lang) to GLSL. - * Needed because the presets all contain directX-style shaders, and we want GLSL so we can run on things that aren't windows computers. - * - * Also worth looking into generating SPIR-V for Vulkan support, someday. - * - * Created on: May 27, 2018 - * Author: mischa spiegelmock - * - * actual conversion is done by: https://github.com/Thekla/hlslparser - */ - -#ifndef HLSLTRANSLATOR_HPP_ -#define HLSLTRANSLATOR_HPP_ - -#include "Common.hpp" -#include "projectM-opengl.h" -#include "HLSLParser.h" -#include "GLSLGenerator.h" -#include -#include "projectM-opengl.h" -#include -#include -#include - -class HLSLTranslator { - public: - std::string parse(const std::string & shaderType, const char *fileName, const std::string &fullSource); -}; - -#endif diff --git a/src/libprojectM/Renderer/Makefile.am b/src/libprojectM/Renderer/Makefile.am index 4e6c4f6c5..a15709946 100644 --- a/src/libprojectM/Renderer/Makefile.am +++ b/src/libprojectM/Renderer/Makefile.am @@ -43,8 +43,7 @@ libRenderer_la_SOURCES = \ hlslparser/src/CodeWriter.h hlslparser/src/GLSLGenerator.cpp \ hlslparser/src/HLSLTokenizer.cpp hlslparser/src/HLSLTree.h \ hlslparser/src/Engine.cpp hlslparser/src/GLSLGenerator.h hlslparser/src/HLSLParser.cpp \ - hlslparser/src/HLSLTokenizer.h \ - HLSLTranslator.cpp HLSLTranslator.hpp + hlslparser/src/HLSLTokenizer.h libRenderer_la_CPPFLAGS = ${my_CFLAGS} \ -include $(top_builddir)/config.h \ diff --git a/src/libprojectM/Renderer/ShaderEngine.cpp b/src/libprojectM/Renderer/ShaderEngine.cpp index e99b39a65..9f7f27058 100644 --- a/src/libprojectM/Renderer/ShaderEngine.cpp +++ b/src/libprojectM/Renderer/ShaderEngine.cpp @@ -9,10 +9,13 @@ #include "ShaderEngine.hpp" #include "BeatDetect.hpp" #include "Texture.hpp" -#include "HLSLTranslator.hpp" +#include "HLSLParser.h" +#include "GLSLGenerator.h" #include // glm::mat4 #include // glm::translate, glm::rotate, glm::scale, glm::perspective #include +#include +#include #ifdef USE_GLES #define GLSL_VERSION "300 es" @@ -255,12 +258,6 @@ std::string PresetShaderIncludes = "" "#define blur3_min _c13.z\n" "#define blur3_max _c13.w\n" -"// previous-frame-image samplers:\n" -"uniform sampler2D sampler_main;\n" -"uniform sampler2D sampler_fc_main;\n" -"uniform sampler2D sampler_pc_main;\n" -"uniform sampler2D sampler_fw_main;\n" -"uniform sampler2D sampler_pw_main;\n" "#define sampler_FC_main sampler_fc_main\n" "#define sampler_PC_main sampler_pc_main\n" "#define sampler_FW_main sampler_fw_main\n" @@ -275,27 +272,6 @@ std::string PresetShaderIncludes = "" "#define lum(x) (dot(x,float3(0.32,0.49,0.29)))\n" "#define tex2d tex2D\n" "#define tex3d tex3D\n" - - - -"// built-in noise textures:\n" -"uniform sampler2D sampler_noise_lq;\n" -"uniform sampler2D sampler_noise_lq_lite;\n" -"uniform sampler2D sampler_noise_mq;\n" -"uniform sampler2D sampler_noise_hq;\n" -"uniform sampler3D sampler_noisevol_lq;\n" -"uniform sampler3D sampler_noisevol_hq;\n" -"uniform float4 texsize_noise_lq;\n" -"uniform float4 texsize_noise_lq_lite;\n" -"uniform float4 texsize_noise_mq;\n" -"uniform float4 texsize_noise_hq;\n" -"uniform float4 texsize_noisevol_lq;\n" -"uniform float4 texsize_noisevol_hq;\n" - -"// procedural blur textures:\n" -"uniform sampler2D sampler_blur1;\n" -"uniform sampler2D sampler_blur2;\n" -"uniform sampler2D sampler_blur3;\n" ; @@ -543,7 +519,6 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha // replace shader_body with entry point function found = program.find("shader_body"); - size_t program_start = found; if (found != std::string::npos) { //std::cout << "first 'shader_body' found at: " << int(found) << std::endl; @@ -573,6 +548,23 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha pmShader.textures.clear(); + + // Add builtin textures + pmShader.textures["main"] = textureManager->getTexture("main", GL_REPEAT, GL_LINEAR); + pmShader.textures["fc_main"] = textureManager->getTexture("main", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["pc_main"] = textureManager->getTexture("main", GL_CLAMP_TO_EDGE, GL_NEAREST); + pmShader.textures["fw_main"] = textureManager->getTexture("main", GL_REPEAT, GL_LINEAR); + pmShader.textures["pw_main"] = textureManager->getTexture("main", GL_REPEAT, GL_NEAREST); + + pmShader.textures["noise_lq"] = textureManager->getTexture("noise_lq", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["noise_lq_lite"] = textureManager->getTexture("noise_lq_lite", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["noise_mq"] = textureManager->getTexture("noise_mq", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["noise_hq"] = textureManager->getTexture("noise_hq", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["noisevol_lq"] = textureManager->getTexture("noisevol_lq", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["noisevol_hq"] = textureManager->getTexture("noisevol_hq", GL_CLAMP_TO_EDGE, GL_LINEAR); + + + // set up texture samplers for all samplers references in the shader program found = 0; found = program.find("sampler_", found); @@ -591,13 +583,9 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha if (texDesc.first == NULL) { - if (lowerCaseName.substr(0, 4) == "rand") + if (lowerCaseName.substr(0, 4) == "rand" || lowerCaseName.substr(2, 5) == "_rand") { - std::string random_name = textureManager->getRandomTextureName(lowerCaseName); - if (random_name.size() > 0) - { - texDesc = textureManager->getTexture(random_name, GL_REPEAT, GL_LINEAR); - } + texDesc = textureManager->getRandomTextureName(sampler); } else { @@ -611,31 +599,15 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha } else { - // The shader declares a new sampler -> declaring it with a "uniform" outside the shader body - if (texDesc.first->userTexture) { - if (found < program_start) { - int index = found; - while(index >= 0 && program[index] != '\n') { index--; } - program.insert(index+1, "uniform "); - found += 8; - program_start += 8; - } - } - - // Add built-in textures - // Add user textures only if used - if (!texDesc.first->userTexture || found > program_start) + std::map::const_iterator iter = pmShader.textures.cbegin(); + for ( ; iter != pmShader.textures.cend(); ++iter) { - std::map::const_iterator iter = pmShader.textures.cbegin(); - for ( ; iter != pmShader.textures.cend(); ++iter) - { - if (iter->first == sampler) - break; - } - - if (iter == pmShader.textures.cend()) - pmShader.textures[sampler] = texDesc; + if (iter->first == sampler) + break; } + + if (iter == pmShader.textures.cend()) + pmShader.textures[sampler] = texDesc; } } @@ -644,21 +616,13 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha textureManager->clearRandomTextures(); - // blur programs - blur1_enabled = false; - blur2_enabled = false; - blur3_enabled = false; - - if (program.find("GetMain") != std::string::npos || program.find("GetPixel") != std::string::npos) - { - pmShader.textures["main"] = textureManager->getTexture("main", GL_REPEAT, GL_LINEAR); - } - found = program.find("GetBlur3"); if (found != std::string::npos) { blur1_enabled = blur2_enabled = blur3_enabled = true; pmShader.textures["blur3"] = textureManager->getTexture("blur3", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["blur2"] = textureManager->getTexture("blur2", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["blur1"] = textureManager->getTexture("blur1", GL_CLAMP_TO_EDGE, GL_LINEAR); } else { @@ -667,6 +631,7 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha { blur1_enabled = blur2_enabled = true; pmShader.textures["blur2"] = textureManager->getTexture("blur2", GL_CLAMP_TO_EDGE, GL_LINEAR); + pmShader.textures["blur1"] = textureManager->getTexture("blur1", GL_CLAMP_TO_EDGE, GL_LINEAR); } else { @@ -709,11 +674,89 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha default: shaderTypeString = "Other"; } + M4::GLSLGenerator generator; + M4::Allocator allocator; + + M4::HLSLTree tree( &allocator ); + M4::HLSLParser parser(&allocator, &tree); + + // preprocess define macros + std::string sourcePreprocessed; + if (!parser.ApplyPreprocessor(shaderFilename.c_str(), fullSource.c_str(), fullSource.size(), sourcePreprocessed)) { + std::cerr << "Failed to preprocess HLSL(step1) " << shaderTypeString << " shader" << std::endl; + +#ifndef DUMP_SHADERS_ON_ERROR + std::cerr << "Source: " << std::endl << fullSource << std::endl; +#else + std::ofstream out("/tmp/shader_" + shaderTypeString + "_step1.txt"); + out << fullSource; + out.close(); +#endif + return GL_FALSE; + } + + // Remove previous shader declarations + std::smatch matches; + while(std::regex_search(sourcePreprocessed, matches, std::regex("sampler(2D|3D|)(\\s+|\\().*"))) { + sourcePreprocessed.replace(matches.position(), matches.length(), ""); + } + + // Remove previous texsize declarations + while(std::regex_search(sourcePreprocessed, matches, std::regex("float4\\s+texsize_.*"))) { + sourcePreprocessed.replace(matches.position(), matches.length(), ""); + } + + // Declare samplers + std::set texsizes; + std::map::const_iterator iter_samplers = pmShader.textures.cbegin(); + for ( ; iter_samplers != pmShader.textures.cend(); ++iter_samplers) + { + Texture * texture = iter_samplers->second.first; + + if (texture->type == GL_TEXTURE_3D) { + sourcePreprocessed.insert(0, "uniform sampler3D sampler_" + iter_samplers->first + ";\n"); + } else { + sourcePreprocessed.insert(0, "uniform sampler2D sampler_" + iter_samplers->first + ";\n"); + } + + texsizes.insert(iter_samplers->first); + texsizes.insert(texture->name); + } + + // Declare texsizes + std::set::const_iterator iter_texsizes = texsizes.cbegin(); + for ( ; iter_texsizes != texsizes.cend(); ++iter_texsizes) + { + sourcePreprocessed.insert(0, "uniform float4 texsize_" + *iter_texsizes + ";\n"); + } + + // transpile from HLSL (aka preset shader aka directX shader) to GLSL (aka OpenGL shader lang) - HLSLTranslator translator = HLSLTranslator(); - std::string glslSource = translator.parse(shaderTypeString, shaderFilename.c_str(), fullSource); - if (glslSource.empty()) { - std::cerr << "Failed to translate " << shaderTypeString << std::endl; + + // parse + if( !parser.Parse(shaderFilename.c_str(), sourcePreprocessed.c_str(), sourcePreprocessed.size()) ) { + std::cerr << "Failed to parse HLSL(step2) " << shaderTypeString << " shader" << std::endl; + +#ifndef DUMP_SHADERS_ON_ERROR + std::cerr << "Source: " << std::endl << sourcePreprocessed << std::endl; +#else + std::ofstream out2("/tmp/shader_" + shaderTypeString + "_step2.txt"); + out2 << sourcePreprocessed; + out2.close(); +#endif + return GL_FALSE; + } + + // generate GLSL + if (!generator.Generate(&tree, M4::GLSLGenerator::Target_FragmentShader, M4::GLSLGenerator::Version_140, "PS")) { + std::cerr << "Failed to transpile HLSL(step3) " << shaderTypeString << " shader to GLSL" << std::endl; +#ifndef DUMP_SHADERS_ON_ERROR + std::cerr << "Source: " << std::endl << sourcePreprocessed << std::endl; +#else + std::ofstream out2("/tmp/shader_" + shaderTypeString + "_step2.txt"); + out2 << sourcePreprocessed; + out2.close(); +#endif return GL_FALSE; } @@ -721,22 +764,22 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha // copmile the preset shader fragment shader with the standard vertex shader and cross our fingers GLuint ret = 0; if (shaderType == PresentWarpShader) { - ret = CompileShaderProgram(presetWarpVertexShader, glslSource, shaderTypeString); // returns new program + ret = CompileShaderProgram(presetWarpVertexShader, generator.GetResult(), shaderTypeString); // returns new program } else { - ret = CompileShaderProgram(presetCompVertexShader, glslSource, shaderTypeString); // returns new program + ret = CompileShaderProgram(presetCompVertexShader, generator.GetResult(), shaderTypeString); // returns new program } if (ret != GL_FALSE) { std::cerr << "Successfull compilation of " << shaderTypeString << std::endl; } else { - std::cerr << "Compilation error of " << shaderTypeString << std::endl; + std::cerr << "Compilation error (step3) of " << shaderTypeString << std::endl; #ifndef DUMP_SHADERS_ON_ERROR - std::cerr << "Source:" << std::endl << *glslSource.get() << std::endl; + std::cerr << "Source:" << std::endl << generator.GetResult() << std::endl; #else - std::ofstream out2("/tmp/shader_glsl_" + shaderTypeString + ".txt"); - out2 << glslSource; - out2.close(); + std::ofstream out3("/tmp/shader_" + shaderTypeString + "_step3.txt"); + out3 << generator.GetResult(); + out3.close(); #endif } @@ -862,12 +905,15 @@ void ShaderEngine::SetupTextures(GLuint program, const Shader &shader) { uint texNum = 0; - for (std::map::const_iterator iter = shader.textures.begin(); iter - != shader.textures.end(); ++iter) + std::map texsizes; + + // Set samplers + for (std::map::const_iterator iter_samplers = shader.textures.begin(); iter_samplers + != shader.textures.end(); ++iter_samplers) { - std::string texName = iter->first; - Texture * texture = iter->second.first; - Sampler * sampler = iter->second.second; + std::string texName = iter_samplers->first; + Texture * texture = iter_samplers->second.first; + Sampler * sampler = iter_samplers->second.second; std::string samplerName = "sampler_" + texName; // https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Binding_textures_to_samplers @@ -877,24 +923,33 @@ void ShaderEngine::SetupTextures(GLuint program, const Shader &shader) continue; } + texsizes[texName] = texture; + texsizes[texture->name] = texture; glActiveTexture(GL_TEXTURE0 + texNum); glBindTexture(texture->type, texture->texID); glBindSampler(texNum, sampler->samplerID); glUniform1i(param, texNum); + texNum++; + } - std::string texsizeName = "texsize_" + texName; + + // Set texsizes + std::map::const_iterator iter_textures = texsizes.cbegin(); + for ( ; iter_textures != texsizes.cend(); ++iter_textures) + { + Texture * texture = iter_textures->second; + + std::string texsizeName = "texsize_" + iter_textures->first; GLint textSizeParam = glGetUniformLocation(program, texsizeName.c_str()); - if (param >= 0) { + if (textSizeParam >= 0) { glUniform4f(textSizeParam, texture->width, texture->height, 1 / (float) texture->width, 1 / (float) texture->height); } else { - std::cerr << "invalid texsize name " << texsizeName << std::endl; - return; + // unused uniform have been optimized out by glsl compiler + continue; } - - texNum++; } } diff --git a/src/libprojectM/Renderer/Texture.cpp b/src/libprojectM/Renderer/Texture.cpp index f2c7b8a60..7e1d895bb 100644 --- a/src/libprojectM/Renderer/Texture.cpp +++ b/src/libprojectM/Renderer/Texture.cpp @@ -19,8 +19,9 @@ Sampler::~Sampler() -Texture::Texture(const int _width, const int _height, const bool _userTexture) : +Texture::Texture(const std::string &_name, const int _width, const int _height, const bool _userTexture) : type(GL_TEXTURE_2D), + name(_name), width(_width), height(_height), userTexture(_userTexture) @@ -31,9 +32,10 @@ Texture::Texture(const int _width, const int _height, const bool _userTexture) : glBindTexture(GL_TEXTURE_2D, 0); } -Texture::Texture(const GLuint _texID, const GLenum _type, const int _width, const int _height, const bool _userTexture) : +Texture::Texture(const std::string &_name, const GLuint _texID, const GLenum _type, const int _width, const int _height, const bool _userTexture) : texID(_texID), type(_type), + name(_name), width(_width), height(_height), userTexture(_userTexture) diff --git a/src/libprojectM/Renderer/Texture.hpp b/src/libprojectM/Renderer/Texture.hpp index 04bc9d5eb..8bf08f068 100644 --- a/src/libprojectM/Renderer/Texture.hpp +++ b/src/libprojectM/Renderer/Texture.hpp @@ -25,13 +25,14 @@ public: GLuint texID; GLenum type; + std::string name; int width; int height; bool userTexture; std::vector samplers; - Texture(const int _width, const int _height, const bool _userTexture); - Texture(const GLuint _texID, const GLenum _type, const int _width, const int _height, const bool _userTexture); + Texture(const std::string & _name, const int _width, const int _height, const bool _userTexture); + Texture(const std::string & _name, const GLuint _texID, const GLenum _type, const int _width, const int _height, const bool _userTexture); ~Texture(); Sampler *getSampler(const GLint _wrap_mode, const GLint _filter_mode); diff --git a/src/libprojectM/Renderer/TextureManager.cpp b/src/libprojectM/Renderer/TextureManager.cpp index a132fd507..290583825 100644 --- a/src/libprojectM/Renderer/TextureManager.cpp +++ b/src/libprojectM/Renderer/TextureManager.cpp @@ -40,10 +40,13 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX extensions.push_back(".dib"); Preload(); - loadTextureDir(); + + loadTextureDir(std::string(DATADIR_PATH) + "/presets"); + loadTextureDir(std::string(DATADIR_PATH) + "/textures"); + loadTextureDir(_presetsURL); // Create main texture ans associated samplers - mainTexture = new Texture(texsizeX, texsizeY, false); + mainTexture = new Texture("main", texsizeX, texsizeY, false); mainTexture->getSampler(GL_REPEAT, GL_LINEAR); mainTexture->getSampler(GL_REPEAT, GL_NEAREST); mainTexture->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); @@ -70,9 +73,9 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX int w2 = ((w+3)/16)*16; int h2 = ((h+3)/4)*4; - Texture * textureBlur = new Texture(w2, h2, false); - textureBlur->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); std::string texname = "blur" + std::to_string(i/2+1) + ((i%2) ? "" : "doNOTuseME"); + Texture * textureBlur = new Texture(texname, w2, h2, false); + textureBlur->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); textures[texname] = textureBlur; blurTextures.push_back(textureBlur); } @@ -83,7 +86,7 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX glGenTextures(1, &noise_texture_lq_lite); glBindTexture(GL_TEXTURE_2D, noise_texture_lq_lite); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_FLOAT, noise.noise_lq_lite); - Texture * textureNoise_lq_lite = new Texture(noise_texture_lq_lite, GL_TEXTURE_2D, 32, 32, false); + Texture * textureNoise_lq_lite = new Texture("noise_lq_lite", noise_texture_lq_lite, GL_TEXTURE_2D, 32, 32, false); textureNoise_lq_lite->getSampler(GL_REPEAT, GL_LINEAR); textures["noise_lq_lite"] = textureNoise_lq_lite; @@ -91,7 +94,7 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX glGenTextures(1, &noise_texture_lq); glBindTexture(GL_TEXTURE_2D, noise_texture_lq); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_FLOAT, noise.noise_lq); - Texture * textureNoise_lq = new Texture(noise_texture_lq, GL_TEXTURE_2D, 256, 256, false); + Texture * textureNoise_lq = new Texture("noise_lq", noise_texture_lq, GL_TEXTURE_2D, 256, 256, false); textureNoise_lq->getSampler(GL_REPEAT, GL_LINEAR); textures["noise_lq"] = textureNoise_lq; @@ -99,7 +102,7 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX glGenTextures(1, &noise_texture_mq); glBindTexture(GL_TEXTURE_2D, noise_texture_mq); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_FLOAT, noise.noise_mq); - Texture * textureNoise_mq = new Texture(noise_texture_mq, GL_TEXTURE_2D, 256, 256, false); + Texture * textureNoise_mq = new Texture("noise_mq", noise_texture_mq, GL_TEXTURE_2D, 256, 256, false); textureNoise_mq->getSampler(GL_REPEAT, GL_LINEAR); textures["noise_mq"] = textureNoise_mq; @@ -107,7 +110,7 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX glGenTextures(1, &noise_texture_hq); glBindTexture(GL_TEXTURE_2D, noise_texture_hq); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_FLOAT, noise.noise_hq); - Texture * textureNoise_hq = new Texture(noise_texture_hq, GL_TEXTURE_2D, 256, 256, false); + Texture * textureNoise_hq = new Texture("noise_hq", noise_texture_hq, GL_TEXTURE_2D, 256, 256, false); textureNoise_hq->getSampler(GL_REPEAT, GL_LINEAR); textures["noise_hq"] = textureNoise_hq; @@ -115,7 +118,7 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX glGenTextures( 1, &noise_texture_lq_vol ); glBindTexture( GL_TEXTURE_3D, noise_texture_lq_vol ); glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 32 ,32 ,32 ,0 ,GL_RGB ,GL_FLOAT ,noise.noise_lq_vol); - Texture * textureNoise_lq_vol = new Texture(noise_texture_lq_vol, GL_TEXTURE_3D, 32, 32, false); + Texture * textureNoise_lq_vol = new Texture("noisevol_lq", noise_texture_lq_vol, GL_TEXTURE_3D, 32, 32, false); textureNoise_lq_vol->getSampler(GL_REPEAT, GL_LINEAR); textures["noisevol_lq"] = textureNoise_lq_vol; @@ -123,7 +126,7 @@ TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX glGenTextures( 1, &noise_texture_hq_vol ); glBindTexture( GL_TEXTURE_3D, noise_texture_hq_vol ); glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 32, 32, 32, 0, GL_RGB, GL_FLOAT, noise.noise_hq_vol); - Texture * textureNoise_hq_vol = new Texture(noise_texture_hq_vol, GL_TEXTURE_3D, 32, 32, false); + Texture * textureNoise_hq_vol = new Texture("noisevol_hq", noise_texture_hq_vol, GL_TEXTURE_3D, 32, 32, false); textureNoise_hq_vol->getSampler(GL_REPEAT, GL_LINEAR); textures["noisevol_hq"] = textureNoise_hq_vol; } @@ -147,9 +150,9 @@ void TextureManager::Preload() ,&width,&height); - Texture * newTex = new Texture(tex, GL_TEXTURE_2D, width, height, true); + Texture * newTex = new Texture("M", tex, GL_TEXTURE_2D, width, height, true); newTex->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); - textures["M.tga"] = newTex; + textures["M"] = newTex; // tex = SOIL_load_OGL_texture_from_memory( // project_data, @@ -160,9 +163,9 @@ void TextureManager::Preload() // | SOIL_FLAG_MULTIPLY_ALPHA // ,&width,&height); - // newTex = new Texture(tex, GL_TEXTURE_2D, width, height, true); + // newTex = new Texture("project", tex, GL_TEXTURE_2D, width, height, true); // newTex->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); - // textures["project.tga"] = newTex; + // textures["project"] = newTex; tex = SOIL_load_OGL_texture_from_memory( headphones_data, @@ -173,9 +176,9 @@ void TextureManager::Preload() | SOIL_FLAG_MULTIPLY_ALPHA ,&width,&height); - newTex = new Texture(tex, GL_TEXTURE_2D, width, height, true); + newTex = new Texture("headphones", tex, GL_TEXTURE_2D, width, height, true); newTex->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); - textures["headphones.tga"] = newTex; + textures["headphones"] = newTex; } void TextureManager::Clear() @@ -189,24 +192,38 @@ void TextureManager::Clear() TextureSamplerDesc TextureManager::getTexture(const std::string fullName, const GLenum defaultWrap, const GLenum defaultFilter) { - std::string name; + std::string fileName = fullName; + std::string unqualifiedName; GLint wrap_mode; GLint filter_mode; - ExtractTextureSettings(fullName, wrap_mode, filter_mode, name); - if (textures.find(name) == textures.end()) + // Remove extension + std::string lowerCaseFileName(fullName); + std::transform(lowerCaseFileName.begin(), lowerCaseFileName.end(), lowerCaseFileName.begin(), tolower); + for (size_t x = 0; x < extensions.size(); x++) + { + size_t found = lowerCaseFileName.find(extensions[x]); + if (found != std::string::npos) + { + fileName.replace(int(found), extensions[x].size(), ""); + break; + } + } + + ExtractTextureSettings(fileName, wrap_mode, filter_mode, unqualifiedName); + if (textures.find(unqualifiedName) == textures.end()) { return TextureSamplerDesc(NULL, NULL); } - if (fullName == name) { + if (fileName == unqualifiedName) { // Warp and filter mode not specified in sampler name // applying default wrap_mode = defaultWrap; filter_mode = defaultFilter; } - Texture * texture = textures[name]; + Texture * texture = textures[unqualifiedName]; Sampler * sampler = texture->getSampler(wrap_mode, filter_mode); return TextureSamplerDesc(texture, sampler); @@ -216,10 +233,15 @@ TextureSamplerDesc TextureManager::getTexture(const std::string fullName, const TextureSamplerDesc TextureManager::tryLoadingTexture(const std::string name) { TextureSamplerDesc texDesc; + GLint wrap_mode; + GLint filter_mode; + std::string unqualifiedName; + + ExtractTextureSettings(name, wrap_mode, filter_mode, unqualifiedName); for (size_t x = 0; x < extensions.size(); x++) { - std::string filename = name + extensions[x]; + std::string filename = unqualifiedName + extensions[x]; std::string fullURL = presetsURL + PATH_SEPARATOR + filename; texDesc = loadTexture(name, fullURL); @@ -249,8 +271,13 @@ TextureSamplerDesc TextureManager::loadTexture(const std::string name, const std return TextureSamplerDesc(NULL, NULL); } - Texture * newTexture = new Texture(tex, GL_TEXTURE_2D, width, height, true); - Sampler * sampler = newTexture->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR); + GLint wrap_mode; + GLint filter_mode; + std::string unqualifiedName; + + ExtractTextureSettings(name, wrap_mode, filter_mode, unqualifiedName); + Texture * newTexture = new Texture(unqualifiedName, tex, GL_TEXTURE_2D, width, height, true); + Sampler * sampler = newTexture->getSampler(wrap_mode, filter_mode); textures[name] = newTexture; @@ -258,10 +285,8 @@ TextureSamplerDesc TextureManager::loadTexture(const std::string name, const std } -void TextureManager::loadTextureDir() +void TextureManager::loadTextureDir(const std::string &dirname) { - std::string dirname = std::string(DATADIR_PATH) + "/presets"; - DIR * m_dir; // Allocate a new a stream given the current directory name @@ -309,15 +334,29 @@ void TextureManager::loadTextureDir() } } -std::string TextureManager::getRandomTextureName(std::string random_id) +TextureSamplerDesc TextureManager::getRandomTextureName(std::string random_id) { + GLint wrap_mode; + GLint filter_mode; + std::string unqualifiedName; + + ExtractTextureSettings(random_id, wrap_mode, filter_mode, unqualifiedName); std::vector user_texture_names; + size_t separator = unqualifiedName.find("_"); + std::string textureNameFilter; + + if (separator != std::string::npos) + { + textureNameFilter = unqualifiedName.substr(separator+1); + unqualifiedName = unqualifiedName.substr(0, separator); + } for(std::map::const_iterator iter = textures.begin(); iter != textures.end(); iter++) { if (iter->second->userTexture) { - user_texture_names.push_back(iter->first); + if (textureNameFilter.empty() || iter->first.find(textureNameFilter) == 0) + user_texture_names.push_back(iter->first); } } @@ -325,10 +364,16 @@ std::string TextureManager::getRandomTextureName(std::string random_id) { std::string random_name = user_texture_names[rand() % user_texture_names.size()]; random_textures.push_back(random_id); - textures[random_id] = textures[random_name]; - return random_name; + + Texture * randomTexture = new Texture(*textures[random_name]); + Sampler * sampler = randomTexture->getSampler(wrap_mode, filter_mode); + randomTexture->name = unqualifiedName; + textures[random_id] = randomTexture; + + return TextureSamplerDesc(randomTexture, sampler); } - else return ""; + + return TextureSamplerDesc(NULL, NULL); } void TextureManager::clearRandomTextures() diff --git a/src/libprojectM/Renderer/TextureManager.hpp b/src/libprojectM/Renderer/TextureManager.hpp index 649d56585..b1a798242 100644 --- a/src/libprojectM/Renderer/TextureManager.hpp +++ b/src/libprojectM/Renderer/TextureManager.hpp @@ -17,7 +17,7 @@ class TextureManager Texture * mainTexture; std::vector random_textures; - void loadTextureDir(); + void loadTextureDir(const std::string & dirname); TextureSamplerDesc loadTexture(const std::string name, const std::string imageUrl); void ExtractTextureSettings(const std::string qualifiedName, GLint &_wrap_mode, GLint &_filter_mode, std::string & name); std::vector extensions; @@ -35,7 +35,7 @@ public: void updateMainTexture(); - std::string getRandomTextureName(std::string rand_name); + TextureSamplerDesc getRandomTextureName(std::string rand_name); void clearRandomTextures(); };