Fix texture management

This commit is contained in:
deltaoscarmike
2018-08-22 20:07:11 +02:00
parent 7d2e16b75f
commit c0ff137cb4
8 changed files with 232 additions and 223 deletions

View File

@ -1,60 +0,0 @@
#ifndef HLSLTRANSLATOR_CPP_
#define HLSLTRANSLATOR_CPP_
#include <memory>
#include <fstream>
#include <iostream>
#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

View File

@ -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 <sys/types.h>
#include "projectM-opengl.h"
#include <iostream>
#include <memory>
#include <cstdlib>
class HLSLTranslator {
public:
std::string parse(const std::string & shaderType, const char *fileName, const std::string &fullSource);
};
#endif

View File

@ -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 \

View File

@ -9,10 +9,13 @@
#include "ShaderEngine.hpp"
#include "BeatDetect.hpp"
#include "Texture.hpp"
#include "HLSLTranslator.hpp"
#include "HLSLParser.h"
#include "GLSLGenerator.h"
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include <glm/gtc/type_ptr.hpp>
#include <set>
#include <regex>
#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<std::string, TextureSamplerDesc>::const_iterator iter = pmShader.textures.cbegin();
for ( ; iter != pmShader.textures.cend(); ++iter)
{
std::map<std::string, TextureSamplerDesc>::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<std::string> texsizes;
std::map<std::string, TextureSamplerDesc>::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<std::string>::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<std::string, TextureSamplerDesc>::const_iterator iter = shader.textures.begin(); iter
!= shader.textures.end(); ++iter)
std::map<std::string, Texture*> texsizes;
// Set samplers
for (std::map<std::string, TextureSamplerDesc>::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<std::string, Texture*>::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++;
}
}

View File

@ -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)

View File

@ -25,13 +25,14 @@ public:
GLuint texID;
GLenum type;
std::string name;
int width;
int height;
bool userTexture;
std::vector<Sampler*> 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);

View File

@ -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<std::string> 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<std::string, Texture*>::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()

View File

@ -17,7 +17,7 @@ class TextureManager
Texture * mainTexture;
std::vector<std::string> 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<std::string> extensions;
@ -35,7 +35,7 @@ public:
void updateMainTexture();
std::string getRandomTextureName(std::string rand_name);
TextureSamplerDesc getRandomTextureName(std::string rand_name);
void clearRandomTextures();
};