mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-27 15:29:26 -06:00
Using new ghoul ProgramObject functionality
- Fixed risk of memory leak in SceneGraph (deleting shaders)
This commit is contained in:
Submodule ext/ghoul updated: 5a8a150468...44fec6ce6f
@@ -45,7 +45,6 @@
|
||||
// #define FLARE_ONLY
|
||||
|
||||
#include <openspace/flare/flare.h>
|
||||
#include <openspace/util/shadercreator.h>
|
||||
|
||||
#define ABUFFER_SINGLE_LINKED 1
|
||||
#define ABUFFER_FIXED 2
|
||||
@@ -76,7 +75,6 @@ public:
|
||||
InteractionHandler& interactionHandler();
|
||||
RenderEngine& renderEngine();
|
||||
scripting::ScriptEngine& scriptEngine();
|
||||
ShaderCreator& shaderBuilder();
|
||||
|
||||
// SGCT callbacks
|
||||
bool initializeGL();
|
||||
@@ -116,7 +114,6 @@ private:
|
||||
ghoul::opencl::CLContext _context;
|
||||
|
||||
sgct::SharedVector<char> _synchronizationBuffer;
|
||||
ShaderCreator _shaderBuilder;
|
||||
};
|
||||
|
||||
#define OsEng (openspace::OpenSpaceEngine::ref())
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
// std includes
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
@@ -118,6 +120,10 @@ private:
|
||||
std::map<std::string, SceneGraphNode*> _allNodes;
|
||||
|
||||
std::string _sceneGraphToLoad;
|
||||
|
||||
std::mutex _programUpdateLock;
|
||||
std::set<ghoul::opengl::ProgramObject*> _programsToUpdate;
|
||||
std::vector<ghoul::opengl::ProgramObject*> _programs;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __SHADERCREATOR_H__
|
||||
#define __SHADERCREATOR_H__
|
||||
|
||||
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
class ShaderCreator {
|
||||
|
||||
public:
|
||||
ShaderCreator();
|
||||
~ShaderCreator();
|
||||
|
||||
void createSourceFile(bool b);
|
||||
void sourceFileExtension(const std::string& extension);
|
||||
void sourceFileHeader(const std::string& header);
|
||||
|
||||
ghoul::opengl::ProgramObject* buildShader(const std::string& name, const std::string& vpath, const std::string& fpath, const std::string& gpath = "");
|
||||
|
||||
private:
|
||||
|
||||
void _generateSource(const std::string& filename);
|
||||
std::string _loadSource(const std::string& filename, unsigned int depth = 0);
|
||||
std::string _generateFilename(const std::string& filename);
|
||||
|
||||
bool _createSourceFile;
|
||||
std::string _sourceFileExtension;
|
||||
std::string _sourceFileHeader;
|
||||
unsigned int _maxDepth;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,8 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <${SHADERS}/ABuffer/constants.hglsl>
|
||||
|
||||
#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED
|
||||
layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture;
|
||||
layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture;
|
||||
|
||||
@@ -89,8 +89,9 @@ bool ABuffer::initializeABuffer() {
|
||||
addFunc("${SHADERS}/ABuffer/abufferSort.hglsl");
|
||||
addFunc("${SHADERS}/ABuffer/abufferAddToBuffer.hglsl");
|
||||
addFunc("${SHADERS}/ABuffer/abufferStruct.hglsl");
|
||||
addFunc("${SHADERS}/PowerScaling/powerScaling_fs.hglsl");
|
||||
addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl");
|
||||
addFunc("${SHADERS}/PowerScaling/powerScaling_fs.hglsl");
|
||||
addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl");
|
||||
addFunc("${SHADERS}/PowerScaling/powerScalingMath.hglsl");
|
||||
|
||||
// ============================
|
||||
// GEOMETRY (quad)
|
||||
@@ -182,9 +183,11 @@ bool ABuffer::updateShader() {
|
||||
|
||||
using ghoul::opengl::ShaderObject;
|
||||
using ghoul::opengl::ProgramObject;
|
||||
ShaderCreator sc = OsEng.shaderBuilder();
|
||||
ghoul::opengl::ProgramObject* resolveShader = sc.buildShader("ABuffer resolve", absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), _fragmentShaderPath);
|
||||
if( ! resolveShader) {
|
||||
ProgramObject* resolveShader = ProgramObject::Build("ABuffer resolve",
|
||||
"${SHADERS}/ABuffer/abufferResolveVertex.glsl",
|
||||
_fragmentShaderPath);
|
||||
|
||||
if( ! resolveShader) {
|
||||
LERROR("Resolve shader not updated");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -221,17 +221,6 @@ bool OpenSpaceEngine::initialize()
|
||||
//int samples = sqrt(sgct::Engine::instance()->getActiveWindowPtr()->getNumberOfAASamples());
|
||||
//LDEBUG("samples: " << samples);
|
||||
|
||||
int x1, xSize, y1, ySize;
|
||||
sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize);
|
||||
std::string sourceHeader = "";
|
||||
sourceHeader += "#define SCREEN_WIDTH " + std::to_string(xSize) + "\n";
|
||||
sourceHeader += "#define SCREEN_HEIGHT " + std::to_string(ySize) + "\n";
|
||||
sourceHeader += "#define ABUFFER_SINGLE_LINKED " + std::to_string(ABUFFER_SINGLE_LINKED) + "\n";
|
||||
sourceHeader += "#define ABUFFER_FIXED " + std::to_string(ABUFFER_FIXED) + "\n";
|
||||
sourceHeader += "#define ABUFFER_DYNAMIC " + std::to_string(ABUFFER_DYNAMIC) + "\n";
|
||||
sourceHeader += "#define ABUFFER_IMPLEMENTATION " + std::to_string(ABUFFER_IMPLEMENTATION) + "\n";
|
||||
_shaderBuilder.createSourceFile(true);
|
||||
_shaderBuilder.sourceFileHeader(sourceHeader);
|
||||
|
||||
// Register the filepaths from static function enables easy testing
|
||||
// registerFilePaths();
|
||||
@@ -357,13 +346,6 @@ ScriptEngine& OpenSpaceEngine::scriptEngine()
|
||||
return _scriptEngine;
|
||||
}
|
||||
|
||||
|
||||
ShaderCreator& OpenSpaceEngine::shaderBuilder()
|
||||
{
|
||||
// TODO custom assert (ticket #5)
|
||||
return _shaderBuilder;
|
||||
}
|
||||
|
||||
bool OpenSpaceEngine::initializeGL()
|
||||
{
|
||||
return _renderEngine.initializeGL();
|
||||
|
||||
@@ -114,8 +114,7 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary)
|
||||
_fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false);
|
||||
|
||||
|
||||
ShaderCreator sc = OsEng.shaderBuilder();
|
||||
_fieldlinesProgram = sc.buildShader("FieldlinesProgram", vshaderpath, fshaderpath);
|
||||
_fieldlinesProgram = ghoul::opengl::ProgramObject::Build("FieldlinesProgram", vshaderpath, fshaderpath);
|
||||
|
||||
dictionary.getValue("UpdateOnSave", _programUpdateOnSave);
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <openspace/rendering/planets/renderableplanet.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/constants.h>
|
||||
#include <openspace/util/shadercreator.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
@@ -47,6 +46,7 @@
|
||||
#include <ghoul/opengl/shadermanager.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <chrono>
|
||||
@@ -149,87 +149,105 @@ SceneGraph::~SceneGraph()
|
||||
bool SceneGraph::initialize()
|
||||
{
|
||||
LDEBUG("Initializing SceneGraph");
|
||||
|
||||
LDEBUG("Creating ProgramObjects");
|
||||
|
||||
using ghoul::opengl::ShaderObject;
|
||||
using ghoul::opengl::ProgramObject;
|
||||
|
||||
ShaderCreator sc = OsEng.shaderBuilder();
|
||||
ProgramObject* tmpProgram;
|
||||
|
||||
typedef std::chrono::high_resolution_clock clock_;
|
||||
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
||||
int x1, xSize, y1, ySize;
|
||||
sgct::Engine::instance()->
|
||||
getActiveWindowPtr()->
|
||||
getCurrentViewportPixelCoords(x1, y1, xSize, ySize);
|
||||
|
||||
std::chrono::time_point<clock_> beginning(clock_::now());
|
||||
// TODO: Make this file creation dynamic and better in every way
|
||||
// TODO: If the screen size changes it is enough if this file is regenerated to
|
||||
// recompile all necessary files
|
||||
std::ofstream os(absPath("${SHADERS}/ABuffer/constants.hglsl"));
|
||||
os << "#define SCREEN_WIDTH " << xSize << "\n"
|
||||
<< "#define SCREEN_HEIGHT " << ySize << "\n"
|
||||
<< "#define ABUFFER_SINGLE_LINKED 1\n"
|
||||
<< "#define ABUFFER_FIXED 2\n"
|
||||
<< "#define ABUFFER_DYNAMIC 3\n"
|
||||
<< "#define ABUFFER_IMPLEMENTATION 1\n";
|
||||
os.close();
|
||||
|
||||
// pscstandard
|
||||
tmpProgram = sc.buildShader("pscstandard",
|
||||
"${SHADERS}/pscstandard_vs.glsl",
|
||||
"${SHADERS}/pscstandard_fs.glsl");
|
||||
// TODO: Figure out why the callback is called twice
|
||||
ghoul::opengl::ProgramObject::ProgramObjectCallback cb = [this](ghoul::opengl::ProgramObject* program) {
|
||||
_programUpdateLock.lock();
|
||||
_programsToUpdate.insert(program);
|
||||
_programUpdateLock.unlock();
|
||||
};
|
||||
|
||||
// Start Timing for building SceneGraph shaders
|
||||
typedef std::chrono::high_resolution_clock clock_;
|
||||
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
||||
std::chrono::time_point<clock_> beginning(clock_::now());
|
||||
|
||||
// pscstandard
|
||||
tmpProgram = ProgramObject::Build("pscstandard",
|
||||
"${SHADERS}/pscstandard_vs.glsl",
|
||||
"${SHADERS}/pscstandard_fs.glsl",
|
||||
cb);
|
||||
if( ! tmpProgram) return false;
|
||||
_programs.push_back(tmpProgram);
|
||||
OsEng.ref().configurationManager().setValue("pscShader", tmpProgram);
|
||||
|
||||
// RaycastProgram
|
||||
tmpProgram = sc.buildShader("RaycastProgram",
|
||||
"${SHADERS}/exitpoints.vert",
|
||||
"${SHADERS}/exitpoints.frag");
|
||||
if( ! tmpProgram) return false;
|
||||
tmpProgram = ProgramObject::Build("RaycastProgram",
|
||||
"${SHADERS}/exitpoints.vert",
|
||||
"${SHADERS}/exitpoints.frag",
|
||||
cb);
|
||||
if (!tmpProgram) return false;
|
||||
_programs.push_back(tmpProgram);
|
||||
OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram);
|
||||
|
||||
|
||||
// // TwoPassProgram
|
||||
// tmpProgram = sc.buildShader("TwoPassProgram",
|
||||
// "${SHADERS}/twopassraycaster.vert",
|
||||
// "${SHADERS}/twopassraycaster.frag");
|
||||
// if( ! tmpProgram) return false;
|
||||
// tmpProgram->setUniform("texBack", 0);
|
||||
// tmpProgram->setUniform("texFront", 1);
|
||||
// tmpProgram->setUniform("texVolume", 2);
|
||||
// OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram);
|
||||
|
||||
// Quad
|
||||
tmpProgram = sc.buildShader("Quad",
|
||||
"${SHADERS}/quadVert.glsl",
|
||||
"${SHADERS}/quadFrag.glsl");
|
||||
if (!tmpProgram) return false;
|
||||
tmpProgram->setUniform("quadTex", 0);
|
||||
OsEng.ref().configurationManager().setValue("Quad", tmpProgram);
|
||||
|
||||
// Star program
|
||||
tmpProgram = sc.buildShader("Star",
|
||||
tmpProgram = ProgramObject::Build("Star",
|
||||
"${SHADERS}/star_vs.glsl",
|
||||
"${SHADERS}/star_fs.glsl",
|
||||
"${SHADERS}/star_ge.glsl");
|
||||
"${SHADERS}/star_ge.glsl",
|
||||
cb);
|
||||
if (!tmpProgram) return false;
|
||||
_programs.push_back(tmpProgram);
|
||||
OsEng.ref().configurationManager().setValue("StarProgram", tmpProgram);
|
||||
|
||||
// Point program
|
||||
tmpProgram = sc.buildShader("Point",
|
||||
tmpProgram = ProgramObject::Build("Point",
|
||||
"${SHADERS}/star_vs.glsl",
|
||||
"${SHADERS}/star_fs.glsl",
|
||||
"${SHADERS}/star_ge.glsl");
|
||||
"${SHADERS}/star_ge.glsl",
|
||||
cb);
|
||||
if (!tmpProgram) return false;
|
||||
_programs.push_back(tmpProgram);
|
||||
OsEng.ref().configurationManager().setValue("PointProgram", tmpProgram);
|
||||
|
||||
// Grid program
|
||||
tmpProgram = sc.buildShader("Grid",
|
||||
tmpProgram = ProgramObject::Build("Grid",
|
||||
"${SHADERS}/grid_vs.glsl",
|
||||
"${SHADERS}/grid_fs.glsl");
|
||||
"${SHADERS}/grid_fs.glsl",
|
||||
cb);
|
||||
if (!tmpProgram) return false;
|
||||
_programs.push_back(tmpProgram);
|
||||
OsEng.ref().configurationManager().setValue("GridProgram", tmpProgram);
|
||||
|
||||
|
||||
|
||||
// Done building shaders
|
||||
double elapsed = std::chrono::duration_cast<second_>(clock_::now()-beginning).count();
|
||||
LINFO("Time to load shaders: " << elapsed);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceneGraph::deinitialize()
|
||||
{
|
||||
clearSceneGraph();
|
||||
|
||||
// clean up all programs
|
||||
_programsToUpdate.clear();
|
||||
for (auto program : _programs) {
|
||||
delete program;
|
||||
}
|
||||
_programs.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -257,6 +275,13 @@ void SceneGraph::evaluate(Camera* camera)
|
||||
|
||||
void SceneGraph::render(const RenderData& data)
|
||||
{
|
||||
_programUpdateLock.lock();
|
||||
for (auto program : _programsToUpdate) {
|
||||
LDEBUG("Attempting to recompile " << program->name());
|
||||
program->rebuildFromFile();
|
||||
}
|
||||
_programsToUpdate.erase(_programsToUpdate.begin(), _programsToUpdate.end());
|
||||
_programUpdateLock.unlock();
|
||||
if (_root)
|
||||
_root->render(data);
|
||||
}
|
||||
@@ -474,7 +499,8 @@ SceneGraphNode* SceneGraph::sceneGraphNode(const std::string& name) const {
|
||||
}
|
||||
|
||||
scripting::ScriptEngine::LuaLibrary SceneGraph::luaLibrary() {
|
||||
scripting::ScriptEngine::LuaLibrary sceneGraphLibrary = {
|
||||
//scripting::ScriptEngine::LuaLibrary sceneGraphLibrary = {
|
||||
return {
|
||||
"",
|
||||
{
|
||||
{
|
||||
@@ -498,8 +524,7 @@ scripting::ScriptEngine::LuaLibrary SceneGraph::luaLibrary() {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return std::move(sceneGraphLibrary);
|
||||
//return std::move(sceneGraphLibrary);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/util/shadercreator.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/shaderobject.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
|
||||
#include <regex>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
// #include <ifstream>
|
||||
// #include <ofstream>
|
||||
|
||||
using ghoul::opengl::ProgramObject;
|
||||
using ghoul::opengl::ShaderObject;
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ShaderCreator";
|
||||
const std::string defaultSourceFileExtension = "OpenSpaceGenerated.glsl";
|
||||
const std::string separator = "//=====================================================================\n";
|
||||
const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex;
|
||||
const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment;
|
||||
const ShaderObject::ShaderType gsType = ShaderObject::ShaderType::ShaderTypeGeometry;
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
ShaderCreator::ShaderCreator():
|
||||
_createSourceFile(false),
|
||||
_sourceFileExtension(defaultSourceFileExtension),
|
||||
_sourceFileHeader(""),
|
||||
_maxDepth(2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ShaderCreator::~ShaderCreator() {
|
||||
|
||||
}
|
||||
|
||||
void ShaderCreator::createSourceFile(bool b) {
|
||||
_createSourceFile = b;
|
||||
}
|
||||
|
||||
void ShaderCreator::sourceFileExtension(const std::string& extension) {
|
||||
if(extension != "") {
|
||||
_sourceFileExtension = extension;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderCreator::sourceFileHeader(const std::string& header) {
|
||||
_sourceFileHeader = header;
|
||||
}
|
||||
|
||||
ghoul::opengl::ProgramObject* ShaderCreator::buildShader(
|
||||
const std::string& name, const std::string& vpath, const std::string& fpath, const std::string& gpath)
|
||||
{
|
||||
std::string vsPath = absPath(vpath);
|
||||
std::string fsPath = absPath(fpath);
|
||||
std::string gsPath = absPath(gpath);
|
||||
|
||||
if( ! FileSys.fileExists(vsPath))
|
||||
return nullptr;
|
||||
if( ! FileSys.fileExists(fsPath))
|
||||
return nullptr;
|
||||
if (gsPath != "" && !FileSys.fileExists(gsPath))
|
||||
return nullptr;
|
||||
|
||||
if(_createSourceFile) {
|
||||
_generateSource(vsPath);
|
||||
_generateSource(fsPath);
|
||||
|
||||
vsPath = _generateFilename(vsPath);
|
||||
fsPath = _generateFilename(fsPath);
|
||||
}
|
||||
|
||||
ProgramObject* po = new ProgramObject(name);
|
||||
ShaderObject* vs = new ShaderObject(vsType, vsPath, name + " Vertex");
|
||||
ShaderObject* fs = new ShaderObject(fsType, fsPath, name + " Fragment");
|
||||
po->attachObject(vs);
|
||||
po->attachObject(fs);
|
||||
|
||||
if (gsPath != "") {
|
||||
_generateSource(gsPath);
|
||||
gsPath = _generateFilename(gsPath);
|
||||
ShaderObject* gs = new ShaderObject(gsType, gsPath, name + " Geometry");
|
||||
po->attachObject(gs);
|
||||
}
|
||||
|
||||
if ( po->compileShaderObjects() && po->linkProgramObject())
|
||||
return po;
|
||||
|
||||
// unsuccessful compilation, cleanup and return nullptr
|
||||
delete po;
|
||||
po = nullptr;
|
||||
return po;
|
||||
}
|
||||
|
||||
void ShaderCreator::_generateSource(const std::string& filename) {
|
||||
std::string generatedSource = "";
|
||||
if(_sourceFileHeader != "")
|
||||
generatedSource += separator + "// HEADER\n" + separator + _sourceFileHeader + "\n";
|
||||
generatedSource += _loadSource(filename);
|
||||
|
||||
std::ofstream of(_generateFilename(filename));
|
||||
of << generatedSource;
|
||||
of.close();
|
||||
}
|
||||
|
||||
std::string ShaderCreator::_loadSource(const std::string& filename, unsigned int depth) {
|
||||
std::string contents = "", line;
|
||||
std::ifstream f(filename);
|
||||
|
||||
// Pre-allocate memory so the return string doesn't have to resize too often
|
||||
// f.seekg( 0, std::ios::end );
|
||||
// unsigned int fsize = f.tellg();
|
||||
// f.seekg( 0);
|
||||
// contents.reserve(fsize*3);
|
||||
// line.reserve(fsize*3);
|
||||
|
||||
contents += "\n";
|
||||
contents += separator;
|
||||
contents += "// Filename: " + filename + "\n";
|
||||
// contents += "// Size: " + std::to_string(fsize) + "\n";
|
||||
contents += separator;
|
||||
if(depth > _maxDepth) {
|
||||
contents += "// TOO DEEP";
|
||||
return contents;
|
||||
}
|
||||
|
||||
if( ! FileSys.fileExists(filename)){
|
||||
contents += "// FILE NOT FOUND\n";
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::regex e1(R"(^\s*#include \"(.+)\"\s*)");
|
||||
std::regex e2(R"(^\s*#include <(.+)>\s*)");
|
||||
while(std::getline(f, line)) {
|
||||
std::smatch m;
|
||||
if(std::regex_search(line, m, e1)) {
|
||||
using namespace ghoul::filesystem;
|
||||
std::string includeFilename = m[1];
|
||||
File f(filename);
|
||||
includeFilename = f.directoryName() + FileSystem::PathSeparator + includeFilename;
|
||||
//includeFilename = filename.substr(0, filename.find_last_of("/")+1) + includeFilename;
|
||||
line = _loadSource(includeFilename, depth + 1);
|
||||
} else if(std::regex_search(line, m, e2)) {
|
||||
std::string includeFilename = m[1];
|
||||
line = _loadSource(absPath(includeFilename), depth + 1);
|
||||
}
|
||||
|
||||
contents += line + "\n";
|
||||
}
|
||||
f.close();
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::string ShaderCreator::_generateFilename(const std::string& filename) {
|
||||
// If way of confirming and creating a directory this could be a good solution
|
||||
// to avoid cluttering in folders
|
||||
// if(_cacheFolder != "") {
|
||||
// size_t delimiter = filename.find_last_of("/");
|
||||
// std::string file = filename.substr(delimiter+1, filename.length() - delimiter);
|
||||
// std::string path = filename.substr(0, filename.find_last_of("/"));
|
||||
|
||||
// return path + "/" + _cacheFolder + "/" + file + "." + _sourceFileExtension;
|
||||
// }
|
||||
|
||||
return filename + "." + _sourceFileExtension;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user