Moved from VolumeRaycaster to RenderableVolume

- Removed old classes and moved code to the Renderables
- RenderableVolume is now abstract with some helpful functions
- Added swapinterval=0 to sgct config for performance analysis
This commit is contained in:
Jonas Strandstedt
2014-04-18 09:58:44 -04:00
parent 30bda3fc97
commit a6a5207a5d
17 changed files with 1100 additions and 401 deletions

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" ?>
<Cluster masterAddress="localhost">
<Settings>
<Display swapInterval="0" />
</Settings>
<Node address="localhost" port="20401">
<Window fullScreen="false">
<!-- 16:9 aspect ratio -->

View File

@@ -35,7 +35,6 @@
#include <ghoul/opencl/clprogram.h>
#include <ghoul/opencl/clkernel.h>
#include <openspace/rendering/volumeraycaster.h>
#include <openspace/flare/flare.h>
namespace openspace {

View File

@@ -1,9 +1,32 @@
/*****************************************************************************************
* *
* 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 RENDERABLEVOLUME_H
#define RENDERABLEVOLUME_H
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/volumeraycaster.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
@@ -19,25 +42,15 @@ public:
RenderableVolume(const ghoul::Dictionary& dictionary);
~RenderableVolume();
bool initialize();
bool deinitialize();
virtual void render(const Camera *camera, const psc& thisPosition);
virtual void update();
protected:
std::string findPath(const std::string& path);
ghoul::RawVolumeReader::ReadHints readHints(const ghoul::Dictionary& dictionary);
std::string findPath(const std::string& path, const std::string& relativePath);
ghoul::opengl::Texture* loadTransferFunction(const std::string& filepath);
private:
// texture
std::string _volumePath;
// Object
VolumeRaycaster *_rayCaster;
ghoul::RawVolumeReader::ReadHints _hints;
bool _programUpdateOnSave;
// relative path
std::string _relativePath;
};
} // namespace openspace

View File

@@ -22,34 +22,53 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __VOLUMERAYCASTERCL_H__
#define __VOLUMERAYCASTERCL_H__
#ifndef __RENDERABLEVOLUMECL_H__
#define __RENDERABLEVOLUMECL_H__
#include <openspace/rendering/volumeraycaster.h>
#include <openspace/engine/openspaceengine.h>
// open space includes
#include <openspace/rendering/renderablevolume.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opencl/clcontext.h>
#include <ghoul/opencl/clcommandqueue.h>
#include <ghoul/opencl/clprogram.h>
#include <ghoul/opencl/clkernel.h>
#include <ghoul/opencl/clworksize.h>
#include <ghoul/io/rawvolumereader.h>
#include <ghoul/filesystem/file.h>
#include <sgct.h>
#include <memory>
#include <mutex>
//#include <vector>
//#include <string>
#ifdef __APPLE__
#include <memory>
#else
#include <mutex>
#endif
namespace openspace {
class VolumeRaycasterCL: public VolumeRaycaster {
class RenderableVolumeCL: public RenderableVolume {
public:
VolumeRaycasterCL(const ghoul::Dictionary& dictionary);
~VolumeRaycasterCL();
// constructors & destructor
RenderableVolumeCL(const ghoul::Dictionary& dictionary);
~RenderableVolumeCL();
bool initialize();
void render(const glm::mat4& modelViewProjection);
bool deinitialize();
virtual void render(const Camera *camera, const psc& thisPosition);
virtual void update();
private:
void safeKernelCompilation();
std::string _filename;
ghoul::RawVolumeReader::ReadHints _hints;
float _stepSize;
@@ -67,16 +86,15 @@ private:
ghoul::opencl::CLCommandQueue _commands;
ghoul::opencl::CLProgram _program;
ghoul::opencl::CLKernel _kernel;
ghoul::opencl::CLWorkSize* _ws;
cl_mem _clBackTexture, _clFrontTexture, _clVolume, _clOutput;
std::string _kernelPath;
ghoul::filesystem::File* _kernelSourceFile;
bool _kernelUpdateOnSave;
std::mutex _kernelMutex;
void _safeKernelCompilation();
std::mutex* _kernelMutex;
};
} // namespace openspace
#endif // VOLUMERAYCASTER_H
#endif

View File

@@ -0,0 +1,113 @@
/*****************************************************************************************
* *
* 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 __RENDERABLEVOLUMEEXPERT_H__
#define __RENDERABLEVOLUMEEXPERT_H__
// open space includes
#include <openspace/rendering/renderablevolume.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opencl/clcontext.h>
#include <ghoul/opencl/clcommandqueue.h>
#include <ghoul/opencl/clprogram.h>
#include <ghoul/opencl/clkernel.h>
#include <ghoul/io/rawvolumereader.h>
#include <ghoul/filesystem/file.h>
#include <sgct.h>
#ifdef __APPLE__
#include <memory>
#else
#include <mutex>
#endif
namespace openspace {
class RenderableVolumeExpert: public RenderableVolume {
public:
// constructors & destructor
RenderableVolumeExpert(const ghoul::Dictionary& dictionary);
~RenderableVolumeExpert();
bool initialize();
bool deinitialize();
virtual void render(const Camera *camera, const psc& thisPosition);
virtual void update();
private:
// private methods
void safeKernelCompilation();
void safeUpdateTexture(const ghoul::filesystem::File& file);
// Volumes
std::vector<std::string> _volumePaths;
std::vector<ghoul::RawVolumeReader::ReadHints> _volumeHints;
// Textures
ghoul::opengl::Texture* _backTexture;
ghoul::opengl::Texture* _frontTexture;
ghoul::opengl::Texture* _output;
std::vector<ghoul::opengl::Texture*> _volumes;
std::vector<ghoul::opengl::Texture*> _transferFunctions;
std::vector<ghoul::filesystem::File*> _transferFunctionsFiles;
// opencl texture memory pointers
cl_mem _clBackTexture;
cl_mem _clFrontTexture;
cl_mem _clOutput;
std::vector<cl_mem> _clVolumes;
std::vector<cl_mem> _clTransferFunctions;
// opencl program
ghoul::opencl::CLContext _context;
ghoul::opencl::CLCommandQueue _commands;
ghoul::opencl::CLProgram _program;
ghoul::opencl::CLKernel _kernel;
ghoul::filesystem::File* _kernelSourceFile;
std::vector<std::pair<ghoul::opencl::CLProgram::Option, bool> > _kernelOptions;
bool _programUpdateOnSave;
// mutexes to prevent inconsistencies
std::mutex* _kernelLock;
std::mutex* _textureLock;
ghoul::opengl::FramebufferObject* _fbo;
ghoul::opengl::ProgramObject *_fboProgram;
ghoul::opengl::ProgramObject *_quadProgram;
sgct_utils::SGCTBox* _boundingBox;
GLuint _screenQuad;
};
} // namespace openspace
#endif

View File

@@ -22,55 +22,66 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __VOLUMERAYCASTERGL_H__
#define __VOLUMERAYCASTERGL_H__
#ifndef __RENDERABLEVOLUMEGL_H__
#define __RENDERABLEVOLUMEGL_H__
#include <openspace/rendering/volumeraycaster.h>
// open space includes
#include <openspace/rendering/renderablevolume.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/io/rawvolumereader.h>
#include <ghoul/filesystem/file.h>
#include <sgct.h>
#include <memory>
#ifdef __APPLE__
#include <memory>
#else
#include <mutex>
#endif
namespace openspace {
using namespace ghoul::opengl;
class VolumeRaycasterGL: public VolumeRaycaster {
class RenderableVolumeGL: public RenderableVolume {
public:
VolumeRaycasterGL(const ghoul::Dictionary& dictionary);
~VolumeRaycasterGL();
// constructors & destructor
RenderableVolumeGL(const ghoul::Dictionary& dictionary);
~RenderableVolumeGL();
bool initialize();
void render(const glm::mat4& modelViewProjection);
bool deinitialize();
virtual void render(const Camera *camera, const psc& thisPosition);
virtual void update();
private:
std::string _filename;
ghoul::RawVolumeReader::ReadHints _hints;
float _stepSize;
FramebufferObject* _fbo;
Texture* _backTexture;
Texture* _frontTexture;
Texture* _volume;
ProgramObject *_fboProgram, *_twopassProgram;
ghoul::opengl::FramebufferObject* _fbo;
ghoul::opengl::Texture* _backTexture;
ghoul::opengl::Texture* _frontTexture;
ghoul::opengl::Texture* _volume;
ghoul::opengl::ProgramObject *_fboProgram, *_twopassProgram;
sgct_utils::SGCTBox* _boundingBox;
GLuint _screenQuad;
std::mutex _shaderMutex;
std::mutex* _shaderMutex;
std::string _vshaderpath;
std::string _fshaderpath;
ghoul::filesystem::File* _vertexSourceFile;
ghoul::filesystem::File* _fragmentSourceFile;
bool _programUpdateOnSave;
void safeShaderCompilation();
void _safeShaderCompilation();
};
} // namespace openspace
#endif // VOLUMERAYCASTER_H
#endif

View File

@@ -1,44 +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 __VOLUMERAYCASTER_H__
#define __VOLUMERAYCASTER_H__
#include <ghoul/misc/dictionary.h>
namespace openspace {
class VolumeRaycaster {
public:
VolumeRaycaster() = default;
VolumeRaycaster(const ghoul::Dictionary& dictionary);
virtual ~VolumeRaycaster();
virtual bool initialize() = 0;
virtual void render(const glm::mat4& modelViewProjection) = 0;
};
} // namespace openspace
#endif // VOLUMERAYCASTER_H

View File

@@ -21,7 +21,7 @@
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
/*
#ifndef __VOLUMERAYCASTERSINGLEPASS_H__
#define __VOLUMERAYCASTERSINGLEPASS_H__
@@ -59,3 +59,4 @@ private:
} // namespace openspace
#endif // VOLUMERAYCASTER_H
*/

View File

@@ -1,3 +1,26 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
// open space includes
#include <openspace/rendering/renderablevolume.h>
@@ -6,8 +29,6 @@
#include <ghoul/filesystem/filesystem.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/volumeraycastergl.h>
#include <openspace/rendering/volumeraycastercl.h>
#include <sgct.h>
namespace {
@@ -16,109 +37,25 @@ namespace {
namespace openspace {
RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary): _volumePath("") {
RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) {
// get path if available
std::string path = "";
_relativePath = "";
if(dictionary.hasKey("Path")) {
dictionary.getValue("Path", path);
path += "/";
dictionary.getValue("Path", _relativePath);
_relativePath += "/";
}
if(dictionary.hasKey("Volume")) {
dictionary.getValue("Volume", _volumePath);
_volumePath = findPath(_volumePath, path);
}
// parse hints
ghoul::Dictionary hintsDictionary;
if(dictionary.hasKey("Hints"))
dictionary.getValue("Hints", hintsDictionary);
_hints = readHints(hintsDictionary);
_programUpdateOnSave = false;
if(dictionary.hasKey("UpdateOnSave")) {
if(dictionary.getValue("UpdateOnSave", _programUpdateOnSave)) {
}
}
ghoul::Dictionary raycasterDictionary;
raycasterDictionary.setValue("Filepath", _volumePath);
raycasterDictionary.setValue("Hints", _hints);
raycasterDictionary.setValue("ProgramUpdateOnSave", _programUpdateOnSave);
if (dictionary.hasKey("Kernel")) {
std::string kernelPath = "";
if(dictionary.getValue("Kernel", kernelPath)) {
kernelPath = findPath(kernelPath, path);
}
// opencl
raycasterDictionary.setValue("Kernel", kernelPath);
_rayCaster = new VolumeRaycasterCL(raycasterDictionary);
} else if(dictionary.hasKey("Shaders")){
ghoul::Dictionary shadersDictionary;
if(dictionary.getValue("Shaders", shadersDictionary)) {
std::string vertexShaderPath = "";
std::string fragShaderPath = "";
shadersDictionary.getValue("VertexShader", vertexShaderPath);
shadersDictionary.getValue("FragmentShader", fragShaderPath);
LDEBUG("vertexShaderPath: " << vertexShaderPath);
LDEBUG("fragShaderPath: " << fragShaderPath);
vertexShaderPath = findPath(vertexShaderPath, path);
fragShaderPath = findPath(fragShaderPath, path);
raycasterDictionary.setValue("VertexShader", vertexShaderPath);
raycasterDictionary.setValue("FragmentShader", fragShaderPath);
}
// glsl
_rayCaster = new VolumeRaycasterGL(raycasterDictionary);
}
}
RenderableVolume::~RenderableVolume() {
deinitialize();
}
bool RenderableVolume::initialize() {
return _rayCaster->initialize();
}
bool RenderableVolume::deinitialize() {
if(_rayCaster)
delete _rayCaster;
return true;
}
void RenderableVolume::render(const Camera *camera, const psc &thisPosition) {
// check so that the raycaster is set
assert(_rayCaster);
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->getViewProjectionMatrix();
double factor = pow(10.0,thisPosition[3]);
transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor));
transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f));
_rayCaster->render(transform);
}
void RenderableVolume::update() {
}
std::string RenderableVolume::findPath(const std::string& path, const std::string& relativePath) {
std::string RenderableVolume::findPath(const std::string& path) {
std::string tmp = absPath(path);
if(FileSys.fileExists(tmp))
return tmp;
tmp = absPath(relativePath + path);
tmp = absPath(_relativePath + path);
if(FileSys.fileExists(tmp))
return tmp;
@@ -130,8 +67,8 @@ std::string RenderableVolume::findPath(const std::string& path, const std::strin
ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) {
ghoul::RawVolumeReader::ReadHints hints;
hints._dimensions = glm::ivec3(1, 1, 1);
hints._format = ghoul::opengl::Texture::Format::Red;
hints._internalFormat = GL_R8;
hints._format = ghoul::opengl::Texture::Format::Red;
hints._internalFormat = GL_R8;
// parse hints
double tempValue;
@@ -186,5 +123,13 @@ ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dicti
}
return hints;
}
ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string& filepath) {
if ( ! FileSys.fileExists(filepath)) {
return nullptr;
}
return ghoul::opengl::loadTexture(filepath);
}
} // namespace openspace

View File

@@ -22,64 +22,121 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/rendering/volumeraycastercl.h>
// open space includes
#include <openspace/rendering/renderablevolumecl.h>
#include <openspace/engine/openspaceengine.h>
#include <glm/glm.hpp>
#include <ghoul/opengl/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opencl/clworksize.h>
#include <ghoul/logging/logmanager.h>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
namespace {
std::string _loggerCat = "VolumeRaycasterCL";
std::string _loggerCat = "RenderableVolumeCL";
}
namespace openspace {
VolumeRaycasterCL::VolumeRaycasterCL(const ghoul::Dictionary& dictionary):
_fbo(nullptr), _backTexture(nullptr), _frontTexture(nullptr), _volume(nullptr),
_fboProgram(nullptr), _boundingBox(nullptr), _screenQuad(0),
_kernelPath(""), _kernelSourceFile(nullptr), _kernelUpdateOnSave(false) {
RenderableVolumeCL::RenderableVolumeCL(const ghoul::Dictionary& dictionary):
RenderableVolume(dictionary),
_backTexture(nullptr), _frontTexture(nullptr), _output(nullptr),
_clBackTexture(0), _clFrontTexture(0), _clOutput(0),
_kernelSourceFile(nullptr) {
if (dictionary.hasKey("Filepath")) {
std::string filename;
if(dictionary.getValue("Filepath", filename)) {
if (FileSys.ref().fileExists(absPath(filename))) {
_filename = absPath(filename);
_kernelMutex = new std::mutex;
_filename = "";
if(dictionary.hasKey("Volume")) {
if(dictionary.getValue("Volume", _filename)) {
_filename = findPath(_filename);
}
}
ghoul::Dictionary hintsDictionary;
if(dictionary.hasKey("Hints"))
dictionary.getValue("Hints", hintsDictionary);
_hints = readHints(hintsDictionary);
/*
if(dictionary.hasKey("TransferFunctions")) {
ghoul::Dictionary transferFunctions;
if(dictionary.getValue("TransferFunctions", transferFunctions)) {
auto keys = transferFunctions.keys();
for(auto key: keys) {
std::string transferFunctionPath = "";
if(transferFunctions.getValue(key, transferFunctionPath)) {
transferFunctionPath = findPath(transferFunctionPath);
if(transferFunctionPath != "") {
ghoul::filesystem::File* tmp = new ghoul::filesystem::File(transferFunctionPath, false);
ghoul::opengl::Texture* tmpTexture = ghoul::opengl::loadTexture(tmp->path());
_transferFunctions.push_back(tmpTexture);
_transferFunctionsFiles.push_back(tmp);
}
}
}
}
}
*/
if (dictionary.hasKey("Hints")) {
if(dictionary.getValue("Hints", _hints)) {
}
if(dictionary.hasKey("UpdateOnSave")) {
dictionary.getValue("UpdateOnSave", _kernelUpdateOnSave);
}
/*
if(dictionary.hasKey("KernelOptions")) {
using namespace ghoul::opencl;
ghoul::Dictionary kernelOptions;
if(dictionary.getValue("KernelOptions", kernelOptions)) {
auto keys = kernelOptions.keys();
for(auto key: keys) {
bool value = false;
if(kernelOptions.getValue(key, value)) {
if(key == "DenormsAreZero") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::DenormsAreZero, value));
} else if(key == "FastRelaxedMath") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::FastRelaxedMath, value));
} else if(key == "FiniteMathOnly") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::FiniteMathOnly, value));
} else if(key == "KernelArgInfo") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::KernelArgInfo, value));
} else if(key == "MadEnable") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::MadEnable, value));
} else if(key == "NoSignedZero") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::NoSignedZero, value));
} else if(key == "OptDisable") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::OptDisable, value));
} else if(key == "SinglePrecisionConstant") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::SinglePrecisionConstant, value));
} else if(key == "StrictAliasing") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::StrictAliasing, value));
} else if(key == "UnsafeMathOptimizations") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::UnsafeMathOptimizations, value));
}
}
}
}
}
*/
std::string kernelPath = "";
if (dictionary.hasKey("Kernel")) {
std::string filename;
if(dictionary.getValue("Kernel", filename)) {
if (FileSys.ref().fileExists(absPath(filename))) {
_kernelPath = absPath(filename);
}
if(dictionary.getValue("Kernel", kernelPath)) {
kernelPath = findPath(kernelPath);
}
}
if (dictionary.hasKey("KernelUpdateOnSave")) {
if(dictionary.getValue("KernelUpdateOnSave", _kernelUpdateOnSave)) {
}
if (kernelPath != "") {
_kernelSourceFile = new ghoul::filesystem::File(kernelPath, false);
}
}
VolumeRaycasterCL::~VolumeRaycasterCL() {
RenderableVolumeCL::~RenderableVolumeCL() {
deinitialize();
delete _kernelMutex;
}
bool VolumeRaycasterCL::initialize() {
bool RenderableVolumeCL::initialize() {
assert(_filename != "");
// ------ VOLUME READING ----------------
ghoul::RawVolumeReader rawReader(_hints);
@@ -129,8 +186,8 @@ bool VolumeRaycasterCL::initialize() {
_fbo = new ghoul::opengl::FramebufferObject();
_fbo->activate();
int x = sgct::Engine::instance()->getActiveXResolution();
int y = sgct::Engine::instance()->getActiveYResolution();
size_t x = sgct::Engine::instance()->getActiveXResolution();
size_t y = sgct::Engine::instance()->getActiveYResolution();
_backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_output = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
@@ -151,44 +208,55 @@ bool VolumeRaycasterCL::initialize() {
_clOutput = _context.createTextureFromGLTexture(CL_MEM_WRITE_ONLY, *_output);
auto privateCallback = [this](const ghoul::filesystem::File& file) {
_safeKernelCompilation();
safeKernelCompilation();
};
_kernelSourceFile = new ghoul::filesystem::File(_kernelPath, false);
_kernelSourceFile = new ghoul::filesystem::File(_kernelSourceFile->path(), false);
if(_kernelUpdateOnSave)
_kernelSourceFile->setCallback(privateCallback);
privateCallback(*_kernelSourceFile);
safeKernelCompilation();
size_t local_x = 32;
size_t local_y = 32;
while (local_x > 1) {
if(x % local_x == 0)
break;
local_x /= 2;
}
while (local_y > 1) {
if(y % local_y == 0)
break;
local_y /= 2;
}
_ws = new ghoul::opencl::CLWorkSize ({x,y}, {local_x,local_y});
return true;
}
bool RenderableVolumeCL::deinitialize() {
delete _ws;
_ws = nullptr;
return true;
}
void VolumeRaycasterCL::_safeKernelCompilation() {
if(_context.isValidContext()) {
void RenderableVolumeCL::render(const Camera *camera, const psc &thisPosition) {
ghoul::opencl::CLProgram tmpProgram = _context.createProgram(_kernelSourceFile->path());
tmpProgram.setOption(ghoul::opencl::CLProgram::Option::OptDisable, true);
if(tmpProgram.build()) {
ghoul::opencl::CLKernel tmpKernel = tmpProgram.createKernel("volumeraycaster");
if(tmpKernel.isValidKernel()) {
tmpKernel.setArgument(0, &_clFrontTexture);
tmpKernel.setArgument(1, &_clBackTexture);
tmpKernel.setArgument(2, &_clVolume);
tmpKernel.setArgument(3, &_clOutput);
// do the actual assignment behind locked doors
_kernelMutex.lock();
_program = tmpProgram;
_kernel = tmpKernel;
_kernelMutex.unlock();
LDEBUG("Done updating kernel");
}
}
}
}
if( ! _kernel.isValidKernel())
return;
void VolumeRaycasterCL::render(const glm::mat4& modelViewProjection) {
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->getViewProjectionMatrix();
double factor = pow(10.0,thisPosition[3]);
transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor));
transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f));
if(_kernel.isValidKernel()) {
_stepSize = 0.01f;
@@ -196,7 +264,7 @@ void VolumeRaycasterCL::render(const glm::mat4& modelViewProjection) {
GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_fboProgram->activate();
_fboProgram->setUniform("modelViewProjection", modelViewProjection);
_fboProgram->setUniform("modelViewProjection", transform);
// Draw backface
glDrawBuffer(GL_COLOR_ATTACHMENT0);
@@ -222,24 +290,10 @@ void VolumeRaycasterCL::render(const glm::mat4& modelViewProjection) {
// ------ DRAW TO SCREEN ----------------
glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO
size_t x = sgct::Engine::instance()->getActiveXResolution();
size_t y = sgct::Engine::instance()->getActiveYResolution();
size_t local_x = 32;
size_t local_y = 32;
while (local_x > 1) {
if(x % local_x == 0)
break;
local_x /= 2;
}
while (local_y > 1) {
if(y % local_y == 0)
break;
local_y /= 2;
}
ghoul::opencl::CLWorkSize ws({x,y}, {local_x,local_y});
glFinish();
_commands.enqueueKernelBlocking(_kernel, ws);
_commands.enqueueKernelBlocking(_kernel, *_ws);
_commands.finish();
_quadProgram->activate();
glActiveTexture(GL_TEXTURE0);
@@ -252,30 +306,94 @@ void VolumeRaycasterCL::render(const glm::mat4& modelViewProjection) {
_quadProgram->deactivate();
/*
_twopassProgram->activate();
_twopassProgram->setUniform("stepSize", _stepSize);
// Set textures
glActiveTexture(GL_TEXTURE0);
_backTexture->bind();
glActiveTexture(GL_TEXTURE1);
_frontTexture->bind();
glActiveTexture(GL_TEXTURE2);
_volume->bind();
// Draw screenquad
glClearColor(0.2f, 0.2f, 0.2f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_twopassProgram->deactivate();
*/
}
}
}// namespace openspace
void RenderableVolumeCL::update() {
}
void RenderableVolumeCL::safeKernelCompilation() {
std::string _loggerCat = "RenderableVolumeCL::safeKernelCompilation";
if(_context.isValidContext()) {
ghoul::opencl::CLProgram tmpProgram = _context.createProgram(_kernelSourceFile->path());
tmpProgram.setOption(ghoul::opencl::CLProgram::Option::OptDisable, true);
tmpProgram.setOption(ghoul::opencl::CLProgram::Option::KernelArgInfo, true);
if(tmpProgram.build()) {
ghoul::opencl::CLKernel tmpKernel = tmpProgram.createKernel("volumeraycaster");
if(tmpKernel.isValidKernel()) {
tmpKernel.setArgument(0, &_clFrontTexture);
tmpKernel.setArgument(1, &_clBackTexture);
tmpKernel.setArgument(2, &_clVolume);
tmpKernel.setArgument(3, &_clOutput);
// do the actual assignment behind locked doors
_kernelMutex->lock();
_program = tmpProgram;
_kernel = tmpKernel;
_kernelMutex->unlock();
LDEBUG("Done updating kernel");
} else {
LWARNING("Kernel is not valid");
}
} else {
LWARNING("Could not build CLProgram");
}
} else {
LWARNING("No valid CLContext");
}
}
/*
void RenderableVolumeCL::safeUpdateTexture(const ghoul::filesystem::File& file) {
int fileID = 0;
for (fileID = 0; fileID < _transferFunctionsFiles.size(); ++fileID) {
if (_transferFunctionsFiles.at(fileID) == &file) {
//LDEBUG("Transferfunction found at id " << fileID);
break;
}
}
if(fileID == _transferFunctionsFiles.size())
return;
LDEBUG("Updating transferfunction");
// create the new texture
ghoul::opengl::Texture* newTexture = ghoul::opengl::loadTexture(file.path());
if(newTexture) {
// upload the new texture and create a cl memory
newTexture->uploadTexture();
cl_mem clNewTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *newTexture);
if(clNewTexture == 0) {
delete newTexture;
return;
}
// everything is ok, critical point to replace current texture pointers
_textureLock->lock();
// deallocate current texture
delete _transferFunctions.at(fileID);
clReleaseMemObject(_clTransferFunctions.at(fileID));
// set the new texture
_transferFunctions.at(fileID) = newTexture;
_clTransferFunctions.at(fileID) = clNewTexture;
// update kernel
// __kernel arguments(front, back, output, [_volumes], .. fileID))
_kernel.setArgument(3 + _volumes.size() + fileID, &clNewTexture);
// end of critical section
_textureLock->unlock();
}
}
*/
} // namespace openspace

View File

@@ -0,0 +1,503 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
// open space includes
#include <openspace/rendering/renderablevolumeexpert.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/opengl/texturereader.h>
#include <ghoul/opencl/clworksize.h>
#include <ghoul/filesystem/filesystem.h>
#include <algorithm>
namespace {
std::string _loggerCat = "RenderableVolumeExpert";
size_t countKernelArguments(ghoul::opencl::CLKernel& kernel) {
using ghoul::opencl::CLKernel;
CLKernel::AddressQualifier adq;
CLKernel::AccessQualifier acq;
CLKernel::TypeQualifier atq;
size_t arguments = 0;
do {
adq = kernel.argumentAddressQualifier(arguments);
acq = kernel.argumentAccessQualifier(arguments);
atq = kernel.argumentTypeQualifier(arguments);
++arguments;
} while (adq != CLKernel::AddressQualifier::ERROR &&
acq != CLKernel::AccessQualifier::ERROR &&
atq != CLKernel::TypeQualifier::ERROR);
return arguments - 1;
}
}
namespace openspace {
RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictionary):
RenderableVolume(dictionary),
_backTexture(nullptr), _frontTexture(nullptr), _output(nullptr),
_clBackTexture(0), _clFrontTexture(0), _clOutput(0),
_kernelSourceFile(nullptr), _programUpdateOnSave(false) {
_kernelLock = new std::mutex;
_textureLock = new std::mutex;
if(dictionary.hasKey("Volumes")) {
ghoul::Dictionary volumes;
if(dictionary.getValue("Volumes", volumes)) {
auto keys = volumes.keys();
for(auto key: keys) {
ghoul::Dictionary volume;
if(volumes.getValue(key, volume)) {
if (volume.hasKey("File")) {
std::string file = "";
if (volume.getValue("File", file)) {
file = findPath(file);
if (file != "") {
// parse hints
ghoul::Dictionary hintsDictionary;
if(volume.hasKey("Hints"))
volume.getValue("Hints", hintsDictionary);
ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary);
_volumePaths.push_back(file);
_volumeHints.push_back(hints);
}
}
}
}
}
}
}
if(dictionary.hasKey("TransferFunctions")) {
ghoul::Dictionary transferFunctions;
if(dictionary.getValue("TransferFunctions", transferFunctions)) {
auto keys = transferFunctions.keys();
for(auto key: keys) {
std::string transferFunctionPath = "";
if(transferFunctions.getValue(key, transferFunctionPath)) {
transferFunctionPath = findPath(transferFunctionPath);
ghoul::opengl::Texture* tmpTexture = loadTransferFunction(transferFunctionPath);
if(tmpTexture) {
ghoul::filesystem::File* tmp = new ghoul::filesystem::File(transferFunctionPath, false);
_transferFunctions.push_back(tmpTexture);
_transferFunctionsFiles.push_back(tmp);
}
}
}
}
}
std::string kernelPath = "";
if (dictionary.hasKey("Kernel")) {
ghoul::Dictionary kernelDictionary;
if(dictionary.getValue("Kernel", kernelDictionary)) {
if(kernelDictionary.getValue("Source", kernelPath)) {
kernelPath = findPath(kernelPath);
}
if(kernelDictionary.hasKey("UpdateOnSave")) {
kernelDictionary.getValue("UpdateOnSave", _programUpdateOnSave);
}
if(kernelDictionary.hasKey("Options")) {
using namespace ghoul::opencl;
ghoul::Dictionary kernelOptions;
if(kernelDictionary.getValue("Options", kernelOptions)) {
auto keys = kernelOptions.keys();
for(auto key: keys) {
bool value = false;
if(kernelOptions.getValue(key, value)) {
if(key == "DenormsAreZero") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::DenormsAreZero, value));
} else if(key == "FastRelaxedMath") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::FastRelaxedMath, value));
} else if(key == "FiniteMathOnly") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::FiniteMathOnly, value));
} else if(key == "KernelArgInfo") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::KernelArgInfo, value));
} else if(key == "MadEnable") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::MadEnable, value));
} else if(key == "NoSignedZero") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::NoSignedZero, value));
} else if(key == "OptDisable") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::OptDisable, value));
} else if(key == "SinglePrecisionConstant") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::SinglePrecisionConstant, value));
} else if(key == "StrictAliasing") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::StrictAliasing, value));
} else if(key == "UnsafeMathOptimizations") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::UnsafeMathOptimizations, value));
}
}
}
}
}
}
}
if (kernelPath != "") {
_kernelSourceFile = new ghoul::filesystem::File(kernelPath, false);
}
}
RenderableVolumeExpert::~RenderableVolumeExpert() {
deinitialize();
delete _textureLock;
delete _kernelLock;
}
bool RenderableVolumeExpert::initialize() {
if(_kernelSourceFile == nullptr) {
LERROR("Could not find the kernel file!");
return false;
}
_context = OsEng.clContext();
auto textureCallback = [this](const ghoul::filesystem::File& file) {
safeUpdateTexture(file);
};
auto kernelCallback = [this](const ghoul::filesystem::File& file) {
safeKernelCompilation();
};
for(auto texture: _transferFunctions) {
texture->uploadTexture();
cl_mem transferMem = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *texture);
_clTransferFunctions.push_back(transferMem);
}
if(_programUpdateOnSave) {
_kernelSourceFile->setCallback(kernelCallback);
for(auto texture: _transferFunctionsFiles) {
texture->setCallback(textureCallback);
}
}
for (int i = 0; i < _volumePaths.size(); ++i) {
ghoul::RawVolumeReader rawReader(_volumeHints.at(i));
ghoul::opengl::Texture* volume = rawReader.read(_volumePaths.at(i));
volume->uploadTexture();
cl_mem volumeTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *volume);
_volumes.push_back(volume);
_clVolumes.push_back(volumeTexture);
}
// ------ SETUP GEOMETRY ----------------
const GLfloat size = 1.0f;
const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh)
// x y z s t
-size, -size, 0.0f, 0.0f, 0.0f,
size, size, 0.0f, 1.0f, 1.0f,
-size, size, 0.0f, 0.0f, 1.0f,
-size, -size, 0.0f, 0.0f, 0.0f,
size, -size, 0.0f, 1.0f, 0.0f,
size, size, 0.0f, 1.0f, 1.0f
};
GLuint vertexPositionBuffer;
glGenVertexArrays(1, &_screenQuad); // generate array
glBindVertexArray(_screenQuad); // bind array
glGenBuffers(1, &vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_texcoord_data), vertex_texcoord_data, GL_STATIC_DRAW);
// Vertex positions
GLuint vertexLocation = 2;
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), reinterpret_cast<void*>(0));
// Texture coordinates
GLuint texcoordLocation = 0;
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(3*sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer
glBindVertexArray(0); //unbind array
_boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular);
// ------ SETUP SHADERS -----------------
// TODO error control or better design pattern
if( ! OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram)) {
LERROR("Could not find 'RaycastProgram'");
return false;
}
if( ! OsEng.ref().configurationManager().getValue("Quad", _quadProgram)) {
LERROR("Could not find 'Quad'");
return false;
}
// ------ SETUP FBO ---------------------
_fbo = new ghoul::opengl::FramebufferObject();
_fbo->activate();
int x = sgct::Engine::instance()->getActiveXResolution();
int y = sgct::Engine::instance()->getActiveYResolution();
_backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_output = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_backTexture->uploadTexture();
_frontTexture->uploadTexture();
_output->uploadTexture();
_fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0);
_fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1);
_fbo->deactivate();
_context = OsEng.clContext();
_commands = _context.createCommandQueue();
_clBackTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_backTexture);
_clFrontTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_frontTexture);
_clOutput = _context.createTextureFromGLTexture(CL_MEM_WRITE_ONLY, *_output);
// Compile kernels
safeKernelCompilation();
return true;
}
bool RenderableVolumeExpert::deinitialize() {
return true;
}
void RenderableVolumeExpert::render(const Camera *camera, const psc &thisPosition) {
// check so that the raycaster is set
//assert(_rayCaster);
if( ! _kernel.isValidKernel())
return;
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->getViewProjectionMatrix();
double factor = pow(10.0,thisPosition[3]);
transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor));
transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f));
// ------ DRAW TO FBO -------------------
GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_fboProgram->activate();
_fboProgram->setUniform("modelViewProjection", transform);
// Draw backface
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearColor(0.2f, 0.2f, 0.2f, 0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
_boundingBox->draw();
glDisable(GL_CULL_FACE);
// Draw frontface
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.2f, 0.2f, 0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
_boundingBox->draw();
glDisable(GL_CULL_FACE);
_fboProgram->deactivate();
_fbo->deactivate();
// ------ DRAW TO SCREEN ----------------
glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO
size_t x = sgct::Engine::instance()->getActiveXResolution();
size_t y = sgct::Engine::instance()->getActiveYResolution();
size_t local_x = 32;
size_t local_y = 32;
while (local_x > 1) {
if(x % local_x == 0)
break;
local_x /= 2;
}
while (local_y > 1) {
if(y % local_y == 0)
break;
local_y /= 2;
}
ghoul::opencl::CLWorkSize ws({x,y}, {local_x,local_y});
_textureLock->lock();
_kernelLock->lock();
glFinish();
_commands.enqueueKernelBlocking(_kernel, ws);
_commands.finish();
_quadProgram->activate();
glActiveTexture(GL_TEXTURE0);
_output->bind();
glClearColor(0.0f, 0.0f, 0.0f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_kernelLock->unlock();
_textureLock->unlock();
_quadProgram->deactivate();
}
void RenderableVolumeExpert::update() {
}
void RenderableVolumeExpert::safeKernelCompilation() {
if(_context.isValidContext()) {
ghoul::opencl::CLProgram tmpProgram = _context.createProgram(_kernelSourceFile->path());
for(auto option: _kernelOptions) {
tmpProgram.setOption(option.first, option.second);
}
if(tmpProgram.build()) {
ghoul::opencl::CLKernel tmpKernel = tmpProgram.createKernel("volumeraycaster");
if(tmpKernel.isValidKernel()) {
auto begin = _kernelOptions.begin();
auto end = _kernelOptions.end();
auto f = std::find(begin, end, std::make_pair(ghoul::opencl::CLProgram::Option::KernelArgInfo, true));
int maxarguments = 1024;
bool argumentError = false;
if (f != end) {
LDEBUG("Checking argument types");
using ghoul::opencl::CLKernel;
maxarguments = countKernelArguments(tmpKernel);
for (int i = 3; i<maxarguments; ++i) {
CLKernel::AccessQualifier acq = tmpKernel.argumentAccessQualifier(i);
CLKernel::AccessQualifier expected = CLKernel::AccessQualifier::READ_ONLY;
if (acq != expected) {
LWARNING("Argument " << i << " is '" <<
CLKernel::AccessQualifierName(acq) <<"', expected '" <<
CLKernel::AccessQualifierName(expected) << "'");
argumentError = true;
}
}
}
if(argumentError)
return;
tmpKernel.setArgument(0, &_clFrontTexture);
tmpKernel.setArgument(1, &_clBackTexture);
tmpKernel.setArgument(2, &_clOutput);
size_t argumentNr = 3;
for(auto volume: _clVolumes) {
tmpKernel.setArgument(argumentNr, &volume);
++argumentNr;
}
for(auto transferFunction: _clTransferFunctions) {
tmpKernel.setArgument(argumentNr, &transferFunction);
++argumentNr;
}
if (argumentNr > maxarguments) {
LWARNING("More arguments set than kernel accepts.");
}
// do the actual assignment behind locked doors
_kernelLock->lock();
_program = tmpProgram;
_kernel = tmpKernel;
_kernelLock->unlock();
LDEBUG("Done updating kernel");
}
}
}
}
void RenderableVolumeExpert::safeUpdateTexture(const ghoul::filesystem::File& file) {
int fileID = 0;
for (fileID = 0; fileID < _transferFunctionsFiles.size(); ++fileID) {
if (_transferFunctionsFiles.at(fileID) == &file) {
//LDEBUG("Transferfunction found at id " << fileID);
break;
}
}
if(fileID == _transferFunctionsFiles.size())
return;
LDEBUG("Updating transferfunction");
// create the new texture
ghoul::opengl::Texture* newTexture = loadTransferFunction(file.path());
//ghoul::opengl::Texture* newTexture = ghoul::opengl::loadTexture(file.path());
if(newTexture) {
// upload the new texture and create a cl memory
newTexture->uploadTexture();
cl_mem clNewTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *newTexture);
if(clNewTexture == 0) {
delete newTexture;
return;
}
// everything is ok, critical point to replace current texture pointers
_textureLock->lock();
// deallocate current texture
delete _transferFunctions.at(fileID);
clReleaseMemObject(_clTransferFunctions.at(fileID));
// set the new texture
_transferFunctions.at(fileID) = newTexture;
_clTransferFunctions.at(fileID) = clNewTexture;
// update kernel
// __kernel arguments(front, back, output, [_volumes], .. fileID))
_kernel.setArgument(3 + _volumes.size() + fileID, &clNewTexture);
// end of critical section
_textureLock->unlock();
}
}
} // namespace openspace

View File

@@ -22,59 +22,81 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/rendering/volumeraycastergl.h>
// open space includes
#include <openspace/rendering/renderablevolumegl.h>
#include <openspace/engine/openspaceengine.h>
#include <glm/glm.hpp>
#include <ghoul/opengl/texturereader.h>
#include <ghoul/opencl/clworksize.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/io/rawvolumereader.h>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
namespace {
std::string _loggerCat = "VolumeRaycasterGL";
std::string _loggerCat = "RenderableVolumeGL";
}
namespace openspace {
VolumeRaycasterGL::VolumeRaycasterGL(const ghoul::Dictionary& dictionary):
_fbo(nullptr), _backTexture(nullptr), _frontTexture(nullptr), _volume(nullptr),
_fboProgram(nullptr), _twopassProgram(nullptr), _boundingBox(nullptr), _screenQuad(0) {
RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary):
RenderableVolume(dictionary),
_backTexture(nullptr), _frontTexture(nullptr), _screenQuad(0),
_programUpdateOnSave(false) {
_shaderMutex = new std::mutex;
if (dictionary.hasKey("Filepath")) {
std::string filename;
if(dictionary.getValue("Filepath", filename)) {
if (FileSys.ref().fileExists(absPath(filename))) {
_filename = absPath(filename);
_filename = "";
if(dictionary.hasKey("Volume")) {
if(dictionary.getValue("Volume", _filename)) {
_filename = findPath(_filename);
}
}
LDEBUG("filename: " << _filename);
ghoul::Dictionary hintsDictionary;
if(dictionary.hasKey("Hints"))
dictionary.getValue("Hints", hintsDictionary);
_hints = readHints(hintsDictionary);
std::string vshaderpath = "";
std::string fshaderpath = "";
if (dictionary.hasKey("Shaders")) {
ghoul::Dictionary shaderDictionary;
if(dictionary.getValue("Shaders", shaderDictionary)) {
if (shaderDictionary.hasKey("VertexShader")) {
shaderDictionary.getValue("VertexShader", vshaderpath);
}
if (shaderDictionary.hasKey("FragmentShader")) {
shaderDictionary.getValue("FragmentShader", fshaderpath);
}
vshaderpath = findPath(vshaderpath);
fshaderpath = findPath(fshaderpath);
_vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false);
_fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false);
_twopassProgram = new ghoul::opengl::ProgramObject("TwoPassProgram");
ghoul::opengl::ShaderObject* vertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex,vshaderpath);
ghoul::opengl::ShaderObject* fragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment,fshaderpath);
_twopassProgram->attachObject(vertexShader);
_twopassProgram->attachObject(fragmentShader);
}
}
if (dictionary.hasKey("Hints")) {
if(dictionary.getValue("Hints", _hints)) {
}
}
_vshaderpath = "";
_fshaderpath = "";
if (dictionary.hasKey("VertexShader")) {
dictionary.getValue("VertexShader", _vshaderpath);
if(dictionary.hasKey("UpdateOnSave")) {
dictionary.getValue("UpdateOnSave", _programUpdateOnSave);
}
if (dictionary.hasKey("FragmentShader")) {
dictionary.getValue("FragmentShader", _fshaderpath);
}
_twopassProgram = new ProgramObject("TwoPassProgram");
ShaderObject* vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex,_vshaderpath);
ShaderObject* fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment,_fshaderpath);
_twopassProgram->attachObject(vertexShader);
_twopassProgram->attachObject(fragmentShader);
}
VolumeRaycasterGL::~VolumeRaycasterGL() {
RenderableVolumeGL::~RenderableVolumeGL() {
deinitialize();
if(_fbo)
delete _fbo;
if(_backTexture)
@@ -87,12 +109,12 @@ VolumeRaycasterGL::~VolumeRaycasterGL() {
delete _boundingBox;
}
bool VolumeRaycasterGL::initialize() {
bool RenderableVolumeGL::initialize() {
assert(_filename != "");
// ------ VOLUME READING ----------------
// ------ VOLUME READING ----------------
ghoul::RawVolumeReader rawReader(_hints);
_volume = rawReader.read(_filename);
// ------ SETUP GEOMETRY ----------------
const GLfloat size = 1.0f;
const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh)
@@ -132,13 +154,13 @@ bool VolumeRaycasterGL::initialize() {
OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram);
auto privateCallback = [this](const ghoul::filesystem::File& file) {
_safeShaderCompilation();
safeShaderCompilation();
};
_vertexSourceFile = new ghoul::filesystem::File(_vshaderpath, false);
_fragmentSourceFile = new ghoul::filesystem::File(_fshaderpath, false);
_vertexSourceFile->setCallback(privateCallback);
_fragmentSourceFile->setCallback(privateCallback);
if(_programUpdateOnSave) {
_vertexSourceFile->setCallback(privateCallback);
_fragmentSourceFile->setCallback(privateCallback);
}
_twopassProgram->compileShaderObjects();
_twopassProgram->linkProgramObject();
_twopassProgram->setUniform("texBack", 0);
@@ -147,13 +169,13 @@ bool VolumeRaycasterGL::initialize() {
//OsEng.ref().configurationManager().getValue("TwoPassProgram", _twopassProgram);
// ------ SETUP FBO ---------------------
_fbo = new FramebufferObject();
_fbo = new ghoul::opengl::FramebufferObject();
_fbo->activate();
int x = sgct::Engine::instance()->getActiveXResolution();
int y = sgct::Engine::instance()->getActiveYResolution();
_backTexture = new Texture(glm::size3_t(x,y,1));
_frontTexture = new Texture(glm::size3_t(x,y,1));
_backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_backTexture->uploadTexture();
_frontTexture->uploadTexture();
_fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0);
@@ -161,17 +183,34 @@ bool VolumeRaycasterGL::initialize() {
_fbo->deactivate();
return true;
}
void VolumeRaycasterGL::render(const glm::mat4& modelViewProjection) {
bool RenderableVolumeGL::deinitialize() {
return true;
}
void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) {
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->getViewProjectionMatrix();
double factor = pow(10.0,thisPosition[3]);
transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor));
transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f));
_stepSize = 0.01f;
// ------ DRAW TO FBO -------------------
GLuint sgctFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO
GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_fboProgram->activate();
_fboProgram->setUniform("modelViewProjection", modelViewProjection);
_fboProgram->setUniform("modelViewProjection", transform);
// Draw backface
glDrawBuffer(GL_COLOR_ATTACHMENT0);
@@ -196,6 +235,12 @@ void VolumeRaycasterGL::render(const glm::mat4& modelViewProjection) {
// ------ DRAW TO SCREEN ----------------
glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO
// Draw screenquad
glClearColor(0.2f, 0.2f, 0.2f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_shaderMutex->lock();
_twopassProgram->activate();
_twopassProgram->setUniform("stepSize", _stepSize);
@@ -207,25 +252,30 @@ void VolumeRaycasterGL::render(const glm::mat4& modelViewProjection) {
glActiveTexture(GL_TEXTURE2);
_volume->bind();
// Draw screenquad
glClearColor(0.2f, 0.2f, 0.2f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_twopassProgram->deactivate();
_shaderMutex->unlock();
}
void VolumeRaycasterGL::_safeShaderCompilation() {
_shaderMutex.lock();
void RenderableVolumeGL::update() {
}
void RenderableVolumeGL::safeShaderCompilation() {
_shaderMutex->lock();
_twopassProgram->rebuildFromFile();
_twopassProgram->compileShaderObjects();
_twopassProgram->linkProgramObject();
_twopassProgram->setUniform("texBack", 0);
_twopassProgram->setUniform("texFront", 1);
_twopassProgram->setUniform("texVolume", 2);
_shaderMutex.unlock();
_shaderMutex->unlock();
}
}// namespace openspace
} // namespace openspace

View File

@@ -1,42 +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/rendering/volumeraycaster.h>
#include <openspace/engine/openspaceengine.h>
#include <glm/glm.hpp>
#include <ghoul/filesystem/filesystem.h>
#include <iostream>
#include <cmath>
#include <cstdio>
namespace openspace {
VolumeRaycaster::VolumeRaycaster(const ghoul::Dictionary& dictionary) {}
VolumeRaycaster::~VolumeRaycaster() {}
}// namespace openspace

View File

@@ -22,6 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
/*
#include <openspace/rendering/volumeraycastersinglepass.h>
#include <openspace/engine/openspaceengine.h>
@@ -135,3 +136,4 @@ void VolumeRaycasterSinglePass::render(const glm::mat4& modelViewProjection) {
}
}// namespace openspace
*/

View File

@@ -26,9 +26,14 @@
#include <cassert>
// renderables
#include <openspace/rendering/renderableplanet.h>
#include <openspace/rendering/renderablevolume.h>
#include <openspace/rendering/renderablevolumeexpert.h>
#include <openspace/rendering/renderablevolumecl.h>
#include <openspace/rendering/renderablevolumegl.h>
#include <openspace/flare/flare.h>
// positioninformation
#include <openspace/scenegraph/constantpositioninformation.h>
#include <openspace/scenegraph/spicepositioninformation.h>
@@ -54,11 +59,15 @@ void FactoryManager::initialize() {
// Add Renderables
_manager->factoryByType<Renderable>()->
registerClass<RenderablePlanet>("RenderablePlanet");
registerClass<RenderablePlanet>("RenderablePlanet");
_manager->factoryByType<Renderable>()->
registerClass<RenderableVolume>("RenderableVolume");
registerClass<RenderableVolumeCL>("RenderableVolumeCL");
_manager->factoryByType<Renderable>()->
registerClass<Flare>("RenderableFlare");
registerClass<RenderableVolumeGL>("RenderableVolumeGL");
_manager->factoryByType<Renderable>()->
registerClass<RenderableVolumeExpert>("RenderableVolumeExpert");
_manager->factoryByType<Renderable>()->
registerClass<Flare>("RenderableFlare");
// Add PositionInformations
_manager->factoryByType<PositionInformation>()->