solve merge conflict

This commit is contained in:
Michael Nilsson
2016-03-30 09:51:34 -04:00
78 changed files with 2619 additions and 313 deletions

2
.gitignore vendored
View File

@@ -44,6 +44,7 @@ include/openspace/version.h
data/scene/67P/obj/67P_rotated_5_130.obj
data/spice/NewHorizonsKernels/
data/spice/RosettaKernels/
data/scene/plutoprojectionhybrid/textures/
data/scene/plutoprojectionhybrid/textures/Shenk_180.jpg
data/scene/plutoprojectionhybrid/textures/barycenter.png
data/scene/plutoprojectionhybrid/textures/defaultProj.png
@@ -105,6 +106,7 @@ data/scene/newhorizons/models/NewHorizonsCleanModel.obj
data/scene/newhorizons/textures/NHTextureFlipCol.jpg
data/scene/newhorizons/textures/goldfoilbump.tif
data/scene/newhorizons/textures/labels.png
data/scene/pluto/textures/
data/scene/pluto/textures/Shenk_180.jpg
data/scene/pluto/textures/pluto_highres_180.jpg
data/scene/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt

View File

@@ -36,7 +36,7 @@ set(GHOUL_BASE_DIR "${OPENSPACE_BASE_DIR}/ext/ghoul")
include(${OPENSPACE_CMAKE_EXT_DIR}/support_macros.cmake)
include(${OPENSPACE_CMAKE_EXT_DIR}/module_common.cmake)
include(${GHOUL_BASE_DIR}/ext/CopySharedLibraries.cmake)
include(${GHOUL_BASE_DIR}/support/cmake/CopySharedLibraries.cmake)
test_compiler_compatibility()
cleanup_project()

View File

@@ -25,7 +25,7 @@
set(APPLICATION_NAME Launcher)
set(APPLICATION_LINK_TO_OPENSPACE ON)
include (${GHOUL_BASE_DIR}/ext/handle_external_library.cmake)
include (${GHOUL_BASE_DIR}/support/cmake/handle_external_library.cmake)
set(application_path ${OPENSPACE_APPS_DIR}/Launcher)

View File

@@ -130,4 +130,4 @@ return {
},
GuiName = "/Solar/67PTrail"
}
}
}

View File

@@ -0,0 +1,51 @@
return {
{
Name = "ToyVolume 1",
Parent = "Sun",
Ephemeris = {
Type = "Static",
Position = {0, 0, 0, 0}
},
Renderable = {
Type = "RenderableToyVolume",
Color = {1.0, 0.0, 0.0, 0.7},
Translation = {0, 0, 0},
Rotation = {0.5, 0, 0},
ScalingExponent = 11
},
GuiName = "/Volumes/ToyVolume1"
},
{
Name = "ToyVolume 2",
Parent = "Earth",
Ephemeris = {
Type = "Static",
Position = {0, 0, 0, 0}
},
Renderable = {
Type = "RenderableToyVolume",
Color = {1.0, 0.8, 0.0, 0.7},
Translation = {0.0, 0.0, 0.0},
Scaling = {5.0, 2.5, 5.0},
ScalingExponent = 6
},
GuiName = "/Volumes/ToyVolume2"
},
{
Name = "ToyVolume 3",
Parent = "Earth",
Ephemeris = {
Type = "Static",
Translation = {0, 0, 0, 0}
},
Renderable = {
Type = "RenderableToyVolume",
Scaling = {2.0, 2.0, 2.0},
Rotation = {3.14/2.0, 0, 0},
Color = {1.0, 1.0, 1.0, 0.7},
Translation = {0.0, 0.0, 0.0},
ScalingExponent = 6
},
GuiName = "/Volumes/ToyVolume3"
}
}

View File

@@ -125,4 +125,4 @@ return {
},
GuiName = "/Solar/VestaTrail"
}
}
}

View File

@@ -34,8 +34,11 @@
#include <vector>
#include <map>
#include <openspace/rendering/volume.h>
#include <openspace/rendering/renderer.h>
#include <openspace/rendering/raycasterlistener.h>
#include <openspace/util/updatestructures.h>
namespace ghoul {
@@ -54,7 +57,7 @@ class RenderableVolume;
class Camera;
class Scene;
class ABufferRenderer : public Renderer {
class ABufferRenderer : public Renderer, public RaycasterListener {
public:
ABufferRenderer();
virtual ~ABufferRenderer();
@@ -69,42 +72,52 @@ public:
void update();
void render(float blackoutFactor, bool doPerformanceMeasurements) override;
/**
* Update render data
* Responsible for calling renderEngine::setRenderData
*/
virtual void updateRendererData() override;
virtual void raycastersChanged(VolumeRaycaster& raycaster, bool attached) override;
private:
void clear();
void updateResolution();
ghoul::Dictionary createResolveDictionary();
std::unique_ptr<ghoul::opengl::ProgramObject> createResolveProgram(const ghoul::Dictionary& dict);
void updateRaycastData();
void updateResolveDictionary();
Camera* _camera;
Scene* _scene;
glm::ivec2 _resolution;
bool _dirtyResolution;
bool _dirtyRendererData;
bool _dirtyRaycastData;
bool _dirtyResolveDictionary;
std::unique_ptr<ghoul::opengl::ProgramObject> _resolveProgram;
/**
* When a volume is attached or detached from the scene graph,
* the resolve program needs to be recompiled.
* The #_volumes vector keeps track of which volumes that can
* be rendered using the current resolve program.
* The #_volumes map keeps track of which volumes that can
* be rendered using the current resolve program, along with their raycast data
* (id, namespace, etc)
*/
std::vector<Volume*> _volumes;
std::map<VolumeRaycaster*, RaycastData> _raycastData;
std::map<VolumeRaycaster*, std::unique_ptr<ghoul::opengl::ProgramObject>> _boundsPrograms;
std::vector<std::string> _helperPaths;
GLuint _screenQuad;
GLuint _anchorPointerTexture;
GLuint _anchorPointerTextureInitializer;
GLuint _atomicCounterBuffer;
GLuint _fragmentBuffer;
GLuint _fragmentTexture;
GLuint _vertexPositionBuffer;
int _nAaSamples;
ghoul::Dictionary _resolveDictionary;
GLuint _screenQuad;
GLuint _anchorPointerTexture;
GLuint _anchorPointerTextureInitializer;
GLuint _atomicCounterBuffer;
GLuint _fragmentBuffer;
GLuint _fragmentTexture;
GLuint _vertexPositionBuffer;
int _nAaSamples;
ghoul::Dictionary _rendererData;
}; // ABufferRenderer

View File

@@ -32,8 +32,9 @@
#include <vector>
#include <map>
#include <openspace/rendering/volume.h>
#include <openspace/rendering/raycasterlistener.h>
#include <openspace/rendering/renderer.h>
#include <openspace/util/updatestructures.h>
namespace ghoul {
class Dictionary;
@@ -53,13 +54,16 @@ class RenderableVolume;
class Camera;
class Scene;
class FramebufferRenderer : public Renderer {
class FramebufferRenderer : public Renderer, public RaycasterListener {
public:
FramebufferRenderer();
virtual ~FramebufferRenderer();
void initialize() override;
void deinitialize() override;
void updateResolution();
void updateRaycastData();
void setCamera(Camera* camera) override;
void setScene(Scene* scene) override;
@@ -73,11 +77,34 @@ public:
* Responsible for calling renderEngine::setRenderData
*/
virtual void updateRendererData() override;
virtual void raycastersChanged(VolumeRaycaster& raycaster, bool attached) override;
private:
std::map<VolumeRaycaster*, RaycastData> _raycastData;
std::map<VolumeRaycaster*, std::unique_ptr<ghoul::opengl::ProgramObject>> _exitPrograms;
std::map<VolumeRaycaster*, std::unique_ptr<ghoul::opengl::ProgramObject>> _raycastPrograms;
std::unique_ptr<ghoul::opengl::ProgramObject> _resolveProgram;
GLuint _screenQuad;
GLuint _vertexPositionBuffer;
GLuint _mainColorTexture;
GLuint _mainDepthTexture;
GLuint _exitColorTexture;
GLuint _mainFramebuffer;
GLuint _exitDepthTexture;
GLuint _exitFramebuffer;
bool _dirtyRaycastData;
bool _dirtyResolution;
Camera* _camera;
Scene* _scene;
glm::vec2 _resolution;
glm::vec2 _resolution;
int _nAaSamples;
ghoul::Dictionary _rendererData;
}; // FramebufferRenderer
} // openspace

View File

@@ -0,0 +1,39 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 __RAYCASTERLISTENER_H__
#define __RAYCASTERLISTENER_H__
namespace openspace {
class VolumeRaycaster;
class RaycasterListener {
public:
virtual void raycastersChanged(VolumeRaycaster& raycaster, bool attached) = 0;
}; // RaycasterListener
} // openspace
#endif // __RAYCASTERLISTENER_H__

View File

@@ -0,0 +1,53 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 __RAYCASTERMANAGER_H__
#define __RAYCASTERMANAGER_H__
#include <vector>
namespace openspace {
class VolumeRaycaster;
class RaycasterListener;
class RaycasterManager {
public:
RaycasterManager();
~RaycasterManager();
void attachRaycaster(VolumeRaycaster& raycaster);
void detachRaycaster(VolumeRaycaster& raycaster);
bool isAttached(VolumeRaycaster& raycaster);
const std::vector<VolumeRaycaster*>& raycasters();
void addListener(RaycasterListener& listener);
void removeListener(RaycasterListener& listener);
private:
std::vector<VolumeRaycaster*> _raycasters;
std::vector<RaycasterListener*> _listeners;
}; // Volume
} // openspace
#endif // __RAYCASTERMANAGER_H__

View File

@@ -1,3 +1,4 @@
/*****************************************************************************************
* *
* OpenSpace *
@@ -29,7 +30,6 @@
#include <openspace/properties/scalarproperty.h>
#include <openspace/util/powerscaledscalar.h>
#include <openspace/util/updatestructures.h>
#include <openspace/rendering/volume.h>
#include <ghoul/opengl/programobject.h>
@@ -45,8 +45,7 @@ namespace ghoul {
namespace openspace {
// Forward declare to minimize dependencies
struct RenderData;
struct UpdateData;
class Camera;
class PowerScaledCoordinate;
@@ -67,9 +66,9 @@ public:
void setBoundingSphere(const PowerScaledScalar& boundingSphere);
const PowerScaledScalar& getBoundingSphere();
virtual void render(const RenderData& data) = 0;
virtual void render(const RenderData& data);
virtual void render(const RenderData& data, RendererTasks& rendererTask);
virtual void update(const UpdateData& data);
virtual std::vector<Volume*> volumesToRender(const RenderData& data) const;
bool isVisible() const;
@@ -80,12 +79,12 @@ public:
bool getBody(std::string& body);
void setBody(std::string& body);
protected:
void setPscUniforms(ghoul::opengl::ProgramObject* program, const Camera* camera, const PowerScaledCoordinate& position);
void onEnabledChange(std::function<void(bool)> callback);
static void setPscUniforms(ghoul::opengl::ProgramObject& program, const Camera& camera, const PowerScaledCoordinate& position);
private:
properties::BoolProperty _enabled;
PowerScaledScalar boundingSphere_;
std::string _startTime;
std::string _endTime;

View File

@@ -31,6 +31,7 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/rendering/screenspacerenderable.h>
namespace ghoul {
namespace fontrendering {
class Font;
@@ -49,6 +50,7 @@ class Camera;
class SyncBuffer;
class Scene;
class Renderer;
class RaycasterManager;
class ScreenLog;
class ScreenSpaceRenderable;
@@ -77,6 +79,7 @@ public:
Camera* camera() const;
Renderer* renderer() const;
RendererImplementation rendererImplementation() const;
RaycasterManager& raycasterManager();
// sgct wrapped functions
bool initializeGL();
@@ -156,6 +159,8 @@ private:
Camera* _mainCamera;
Scene* _sceneGraph;
RaycasterManager* _raycasterManager;
std::unique_ptr<Renderer> _renderer;
RendererImplementation _rendererImplementation;
ghoul::Dictionary _rendererData;

View File

@@ -0,0 +1,125 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 <string>
#include <vector>
#include <openspace/util/updatestructures.h>
namespace ghoul {
namespace opengl {
class Texture;
class ProgramObject;
}
}
namespace openspace {
class RenderData;
class RaycastData;
class VolumeRaycaster {
public:
/**
* Destructor
*/
virtual ~VolumeRaycaster() {};
/**
* Render the volume's entry points (front face of the bounding geometry)
*/
virtual void renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) = 0;
/**
* Render the volume's exit points (back face of the bounding geometry)
*/
virtual void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) = 0;
/**
* Prepare the volume for the ABuffer's resolve step.
* Make sure textures are up to date, bind them to texture units, set program uniforms etc.
*/
virtual void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) {};
/**
* Clean up for the volume after the ABuffer's resolve step.
* Make sure texture units are deinitialized, etc.
*/
virtual void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) {};
/**
* Return a path the file to use as vertex shader
*
* The shader preprocessor will have acceess to
* A #{namespace} variable (unique per helper file)
*/
virtual std::string getBoundsVsPath() const = 0;
/*
* Return a path to a file with the functions, uniforms and fragment shader in variables
* required to generate the fragment color and depth.
*
* Should define the function:
* Fragment getFragment()
*
* The shader preprocessor will have acceess to
* A #{namespace} variable (unique per helper file)
*/
virtual std::string getBoundsFsPath() const = 0 ;
/**
* Return a path to a file with all the uniforms, functions etc
* required to perform ray casting through this volume.
*
* The header should define the following two functions:
* vec4 sample#{id}(vec3 samplePos, vec3 dir, float occludingAlpha, inout float maxStepSize)
* (return color of sample)
* float stepSize#{id}(vec3 samplePos, vec3 dir)
* (return the preferred step size at this sample position)
*
* The shader preprocessor will have acceess to
* An #{id} variable (unique per volume)
* A #{namespace} variable (unique per helper file)
*/
virtual std::string getRaycastPath() const = 0;
/**
* Return a path to a glsl file with helper functions required for the
* transformation and raycast steps.
* This file will be included once per shader program generated,
* regardless of how many volumes say they require the file.
* Ideal to avoid redefinitions of helper functions.
*
* The shader preprocessor will have access to the #{namespace} variable (unique per helper file)
* which should be a prefix to all symbols defined by the helper
*/
virtual std::string getHelperPath() const = 0;
}; // Raycaster
} // openspace
#endif // __VOLUMERAYCASTER_H__

View File

@@ -41,7 +41,6 @@
namespace openspace {
class Volume;
class SceneGraphNode;
// Notifications:
@@ -83,12 +82,8 @@ public:
/*
* Render visible SceneGraphNodes using the provided camera
*/
void render(const RenderData& data);
void render(const RenderData& data, RendererTasks& tasks);
/*
* Return a vector of volumes to render and their acciciated render data
*/
std::vector<std::pair<Volume*, RenderData>> volumesToRender(const RenderData& data) const;
/*
* Returns the root SceneGraphNode
*/

View File

@@ -66,7 +66,7 @@ public:
void update(const UpdateData& data);
void evaluate(const Camera* camera, const psc& parentPosition = psc());
void render(const RenderData& data);
void render(const RenderData& data, RendererTasks& tasks);
void updateCamera(Camera* camera) const;
//void addNode(SceneGraphNode* child);
@@ -90,7 +90,6 @@ public:
void setRenderable(Renderable* renderable);
const Renderable* renderable() const;
Renderable* renderable();
std::vector<std::pair<Volume*, RenderData>> volumesToRender(const RenderData& data) const;
// @TODO Remove once the scalegraph is in effect ---abock
void setEphemeris(Ephemeris* eph) {

View File

@@ -30,6 +30,8 @@
namespace openspace {
class VolumeRaycaster;
struct InitializeData {
};
@@ -47,6 +49,21 @@ struct RenderData {
bool doPerformanceMeasurement;
};
struct RaycasterTask {
VolumeRaycaster* raycaster;
RenderData renderData;
};
struct RendererTasks {
std::vector<RaycasterTask> raycasterTasks;
};
struct RaycastData {
int id;
std::string namespaceName;
};
}
#endif // __UPDATESTRUCTURES_H__

View File

@@ -96,4 +96,4 @@ create_new_module(
"Base"
base_module
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
)
)

View File

@@ -67,6 +67,7 @@ namespace openspace {
{
Vertex vv;
memcpy(vv.location, v.location, sizeof(GLfloat) * 3);
vv.location[3] = 0.0;
memcpy(vv.tex, v.tex, sizeof(GLfloat) * 2);
memcpy(vv.normal, v.normal, sizeof(GLfloat) * 3);
_vertices.push_back(vv);

View File

@@ -162,7 +162,7 @@ void RenderableConstellationBounds::render(const RenderData& data) {
glm::mat4 viewMatrix = data.camera.viewMatrix();
glm::mat4 projectionMatrix = data.camera.projectionMatrix();
setPscUniforms(_program.get(), &data.camera, data.position);
setPscUniforms(*_program.get(), data.camera, data.position);
_program->setUniform("exponent", _distance);
_program->setUniform("ViewProjection", data.camera.viewProjectionMatrix());

View File

@@ -200,7 +200,7 @@ void RenderableModel::render(const RenderData& data) {
_programObject->setUniform("sun_pos", _sunPosition.vec3());
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
_programObject->setUniform("_performShading", _performShading);

View File

@@ -162,7 +162,7 @@ void RenderablePath::render(const RenderData& data) {
_programObject->setUniform("ModelTransform", transform);
_programObject->setUniform("color", _lineColor);
_programObject->setUniform("lastPosition", _lastPosition);
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
if (_drawLine) {
glLineWidth(_lineWidth);

View File

@@ -206,7 +206,7 @@ void RenderablePlane::render(const RenderData& data) {
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", transform);
setPscUniforms(_shader.get(), &data.camera, data.position);
setPscUniforms(*_shader.get(), data.camera, data.position);
ghoul::opengl::TextureUnit unit;
unit.activate();

View File

@@ -213,7 +213,7 @@ void RenderablePlanet::render(const RenderData& data)
_programObject->setUniform("transparency", _alpha);
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
_programObject->setUniform("_performShading", _performShading);

View File

@@ -162,7 +162,7 @@ void RenderableSphere::render(const RenderData& data) {
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", transform);
setPscUniforms(_shader.get(), &data.camera, data.position);
setPscUniforms(*_shader.get(), data.camera, data.position);
_shader->setUniform("alpha", _transparency);
ghoul::opengl::TextureUnit unit;

View File

@@ -212,7 +212,7 @@ void RenderableSphericalGrid::render(const RenderData& data){
_gridProgram->setIgnoreUniformLocationError(IgnoreError::Yes);
_gridProgram->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_gridProgram->setUniform("ModelTransform", transform);
setPscUniforms(_gridProgram, &data.camera, data.position);
setPscUniforms(*_gridProgram, data.camera, data.position);
_gridProgram->setUniform("gridColor", _gridColor);
glLineWidth(0.5f);

View File

@@ -203,7 +203,7 @@ void RenderableStars::render(const RenderData& data) {
_program->setUniform("scaleFactor", _scaleFactor);
_program->setUniform("minBillboardSize", _minBillboardSize);
setPscUniforms(_program.get(), &data.camera, data.position);
setPscUniforms(*_program.get(), data.camera, data.position);
_program->setUniform("scaling", scaling);
ghoul::opengl::TextureUnit psfUnit;

View File

@@ -155,7 +155,7 @@ void RenderableTrail::render(const RenderData& data) {
// setup the data to the shader
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
_programObject->setUniform("color", _lineColor);
_programObject->setUniform("nVertices", static_cast<unsigned int>(_vertexArray.size()));

View File

@@ -72,5 +72,7 @@ create_new_module(
endif ()
set_property(TARGET cdf PROPERTY FOLDER "External")
endif ()
# Boost
find_package(Boost REQUIRED)
target_include_directories(openspace-module-kameleon SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
#include_external_library(${onscreengui_module} Imgui ${CMAKE_CURRENT_SOURCE_DIR}/ext/kameleon)

View File

@@ -140,7 +140,7 @@ void RenderableCrawlingLine::render(const RenderData& data) {
_program->setUniform("_alpha", alpha);
_program->setUniform("color", _lineColor);
setPscUniforms(_program.get(), &data.camera, data.position);
setPscUniforms(*_program.get(), data.camera, data.position);
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);

View File

@@ -549,7 +549,7 @@ void RenderableFov::render(const RenderData& data) {
// setup the data to the shader
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", glm::mat4(1));
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
if (openspace::ImageSequencer2::ref().isReady())
_drawFOV = ImageSequencer2::ref().instrumentActive(_instrumentID);

View File

@@ -331,7 +331,7 @@ void RenderableModelProjection::render(const RenderData& data) {
_viewProjection = data.camera.viewProjectionMatrix();
_programObject->setUniform("ViewProjection", _viewProjection);
_programObject->setUniform("ModelTransform", _transform);
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
textureBind();
_geometry->render();

View File

@@ -147,7 +147,7 @@ void RenderablePlaneProjection::render(const RenderData& data) {
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", transform);
setPscUniforms(_shader.get(), &data.camera, data.position);
setPscUniforms(*_shader.get(), data.camera, data.position);
ghoul::opengl::TextureUnit unit;
unit.activate();

View File

@@ -541,7 +541,7 @@ void RenderablePlanetProjection::render(const RenderData& data){
_programObject->setUniform("ViewProjection" , data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform" , _transform);
_programObject->setUniform("boresight" , _boresight);
setPscUniforms(_programObject.get(), &data.camera, data.position);
setPscUniforms(*_programObject.get(), data.camera, data.position);
textureBind();

View File

@@ -136,7 +136,7 @@ void RenderableShadowCylinder::render(const RenderData& data){
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", _transform);
_shader->setUniform("shadowColor", _shadowColor);
setPscUniforms(_shader.get(), &data.camera, data.position);
setPscUniforms(*_shader.get(), data.camera, data.position);
glBindVertexArray(_vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, static_cast<GLsizei>(_vertices.size()));

View File

@@ -0,0 +1,43 @@
#########################################################################################
# #
# OpenSpace #
# #
# Copyright (c) 2014-2016 #
# #
# 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_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletoyvolume.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/toyvolumeraycaster.h
)
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletoyvolume.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/toyvolumeraycaster.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})
create_new_module(
"ToyVolume"
toyvolume_module
${HEADER_FILES} ${SOURCE_FILES}
)

View File

@@ -0,0 +1 @@
set (DEFAULT_MODULE ON)

View File

@@ -0,0 +1,140 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 <modules/toyvolume/rendering/renderabletoyvolume.h>
#include <modules/toyvolume/rendering/toyvolumeraycaster.h>
#include <openspace/rendering/renderable.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/raycastermanager.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <ghoul/opengl/ghoul_gl.h>
namespace {
const std::string GlslRayCastPath = "${MODULES}/toyvolume/shaders/rayCast.glsl";
const std::string GlslBoundsVsPath = "${MODULES}/toyvolume/shaders/boundsVs.glsl";
const std::string GlslBoundsFsPath = "${MODULES}/toyvolume/shaders/boundsFs.glsl";
}
namespace openspace {
RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _scalingExponent("scalingExponent", "Scaling Exponent", 1, -10, 20)
, _stepSize("stepSize", "Step Size", 0.02, 0.01, 1)
, _scaling("scaling", "Scaling", glm::vec3(1.0, 1.0, 1.0), glm::vec3(0.0), glm::vec3(10.0))
, _translation("translation", "Translation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0), glm::vec3(10.0))
, _rotation("rotation", "Euler rotation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0), glm::vec3(6.28))
, _color("color", "Color", glm::vec4(1.0, 0.0, 0.0, 0.1), glm::vec4(0.0), glm::vec4(1.0)) {
float scalingExponent, stepSize;
glm::vec3 scaling, translation, rotation;
glm::vec4 color;
if (dictionary.getValue("ScalingExponent", scalingExponent)) {
_scalingExponent = scalingExponent;
}
if (dictionary.getValue("Scaling", scaling)) {
_scaling = scaling;
}
if (dictionary.getValue("Translation", translation)) {
_translation = translation;
}
if (dictionary.getValue("Rotation", rotation)) {
_rotation = rotation;
}
if (dictionary.getValue("Color", color)) {
_color = color;
}
if (dictionary.getValue("StepSize", stepSize)) {
_stepSize = stepSize;
}
}
RenderableToyVolume::~RenderableToyVolume() {}
bool RenderableToyVolume::initialize() {
_raycaster = std::make_unique<ToyVolumeRaycaster>(ToyVolumeRaycaster(_color));
_raycaster->initialize();
OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get());
std::function<void(bool)> onChange = [&](bool enabled) {
if (enabled) {
OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get());
}
else {
OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get());
}
};
onEnabledChange(onChange);
addProperty(_scaling);
addProperty(_scalingExponent);
addProperty(_stepSize);
addProperty(_translation);
addProperty(_rotation);
addProperty(_color);
return true;
}
bool RenderableToyVolume::deinitialize() {
if (_raycaster) {
OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get());
_raycaster = nullptr;
}
return true;
}
bool RenderableToyVolume::isReady() const {
return true;
}
void RenderableToyVolume::update(const UpdateData& data) {
if (_raycaster) {
glm::mat4 transform = glm::translate(glm::mat4(1.0), static_cast<glm::vec3>(_translation) * std::pow(10.0f, static_cast<float>(_scalingExponent)));
glm::vec3 eulerRotation = static_cast<glm::vec3>(_rotation);
transform = glm::rotate(transform, eulerRotation.x, glm::vec3(1, 0, 0));
transform = glm::rotate(transform, eulerRotation.y, glm::vec3(0, 1, 0));
transform = glm::rotate(transform, eulerRotation.z, glm::vec3(0, 0, 1));
transform = glm::scale(transform, static_cast<glm::vec3>(_scaling) * std::pow(10.0f, static_cast<float>(_scalingExponent)));
_raycaster->setColor(_color);
_raycaster->setStepSize(_stepSize);
_raycaster->setModelTransform(transform);
_raycaster->setTime(data.time);
}
}
void RenderableToyVolume::render(const RenderData& data, RendererTasks& tasks) {
RaycasterTask task{ _raycaster.get(), data };
tasks.raycasterTasks.push_back(task);
}
}

View File

@@ -0,0 +1,62 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 __RENDERABLETOYVOLUME_H__
#define __RENDERABLETOYVOLUME_H__
#include <openspace/properties/vectorproperty.h>
#include <openspace/util/boxgeometry.h>
#include <openspace/util/blockplaneintersectiongeometry.h>
#include <openspace/rendering/renderable.h>
#include <modules/toyvolume/rendering/toyvolumeraycaster.h>
namespace openspace {
struct RenderData;
class RenderableToyVolume : public Renderable {
public:
RenderableToyVolume(const ghoul::Dictionary& dictionary);
~RenderableToyVolume();
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data, RendererTasks& tasks) override;
void update(const UpdateData& data) override;
private:
properties::Vec3Property _scaling;
properties::IntProperty _scalingExponent;
properties::FloatProperty _stepSize;
properties::Vec3Property _translation;
properties::Vec3Property _rotation;
properties::Vec4Property _color;
std::unique_ptr<ToyVolumeRaycaster> _raycaster;
};
}
#endif // __RENDERABLETOYVOLUME_H__

View File

@@ -0,0 +1,131 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 <modules/toyvolume/rendering/toyvolumeraycaster.h>
#include <glm/glm.hpp>
#include <ghoul/opengl/ghoul_gl.h>
#include <sstream>
#include <ghoul/opengl/programobject.h>
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/util/updatestructures.h>
#include <openspace/rendering/renderable.h>
namespace {
const std::string GlslRaycastPath = "${MODULES}/toyvolume/shaders/raycast.glsl";
const std::string GlslBoundsVsPath = "${MODULES}/toyvolume/shaders/boundsVs.glsl";
const std::string GlslBoundsFsPath = "${MODULES}/toyvolume/shaders/boundsFs.glsl";
}
namespace openspace {
ToyVolumeRaycaster::ToyVolumeRaycaster(glm::vec4 color)
: _boundingBox(glm::vec3(1.0))
, _color(color) {}
ToyVolumeRaycaster::~ToyVolumeRaycaster() {}
void ToyVolumeRaycaster::initialize() {
_boundingBox.initialize();
}
void ToyVolumeRaycaster::deinitialize() {
}
void ToyVolumeRaycaster::renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) {
program.setUniform("modelTransform", _modelTransform);
program.setUniform("viewProjection", data.camera.viewProjectionMatrix());
Renderable::setPscUniforms(program, data.camera, data.position);
// Cull back face
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Render bounding geometry
_boundingBox.render();
}
void ToyVolumeRaycaster::renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) {
// Uniforms
program.setUniform("modelTransform", _modelTransform);
program.setUniform("viewProjection", data.camera.viewProjectionMatrix());
Renderable::setPscUniforms(program, data.camera, data.position);
// Cull front face
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
// Render bounding geometry
_boundingBox.render();
// Restore defaults
glCullFace(GL_BACK);
}
void ToyVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) {
std::string colorUniformName = "color" + std::to_string(data.id);
std::string timeUniformName = "time" + std::to_string(data.id);
std::string stepSizeUniformName = "maxStepSize" + std::to_string(data.id);
program.setUniform(colorUniformName, _color);
program.setUniform(stepSizeUniformName, _stepSize);
program.setUniform(timeUniformName, static_cast<float>(std::fmod(_time, 3600.0)));
}
void ToyVolumeRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) {
// For example: release texture units
}
std::string ToyVolumeRaycaster::getBoundsVsPath() const {
return GlslBoundsVsPath;
}
std::string ToyVolumeRaycaster::getBoundsFsPath() const {
return GlslBoundsFsPath;
}
std::string ToyVolumeRaycaster::getRaycastPath() const {
return GlslRaycastPath;
}
std::string ToyVolumeRaycaster::getHelperPath() const {
return ""; // no helper file
}
void ToyVolumeRaycaster::setColor(glm::vec4 color) {
_color = color;
}
void ToyVolumeRaycaster::setModelTransform(glm::mat4 transform) {
_modelTransform = transform;
}
void ToyVolumeRaycaster::setTime(double time) {
_time = time;
}
void ToyVolumeRaycaster::setStepSize(float stepSize) {
_stepSize = stepSize;
}
}

View File

@@ -0,0 +1,80 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 __TOYVOLUMERAYCASTER_H__
#define __TOYVOLUMERAYCASTER_H__
#include <ghoul/glm.h>
#include <string>
#include <vector>
#include <openspace/rendering/volumeraycaster.h>
#include <openspace/util/boxgeometry.h>
#include <openspace/util/blockplaneintersectiongeometry.h>
namespace ghoul {
namespace opengl {
class Texture;
class ProgramObject;
}
}
namespace openspace {
class RenderData;
class RaycastData;
class ToyVolumeRaycaster : public VolumeRaycaster {
public:
ToyVolumeRaycaster(glm::vec4 color);
virtual ~ToyVolumeRaycaster();
void initialize();
void deinitialize();
void renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override;
void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override;
void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override;
void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override;
std::string getBoundsVsPath() const override;
std::string getBoundsFsPath() const override;
std::string getRaycastPath() const override;
std::string getHelperPath() const override;
void setColor(glm::vec4 color);
void setModelTransform(glm::mat4 transform);
void setTime(double time);
void setStepSize(float time);
private:
BoxGeometry _boundingBox;
glm::vec4 _color;
glm::mat4 _modelTransform;
float _stepSize;
double _time;
}; // ToyVolumeRaycaster
} // openspace
#endif // __TOYVOLUMERAYCASTER_H__

View File

@@ -0,0 +1,40 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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. *
****************************************************************************************/
in vec3 vPosition;
in vec4 worldPosition;
#include "PowerScaling/powerScaling_fs.hglsl"
#include "fragment.glsl"
Fragment getFragment() {
vec4 fragColor = vec4(vPosition+0.5, 1.0);
vec4 position = worldPosition;
float depth = pscDepth(position);
Fragment frag;
frag.color = fragColor;
frag.depth = depth;
return frag;
}

View File

@@ -0,0 +1,47 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2016 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec4 vertPosition;
uniform mat4 viewProjection;
uniform mat4 modelTransform;
out vec3 vPosition;
out vec4 worldPosition;
#include "PowerScaling/powerScaling_vs.hglsl"
void main() {
vPosition = vertPosition.xyz;
worldPosition = modelTransform*vertPosition;
vec4 position = pscTransform(worldPosition, mat4(1.0));
// project the position to view space
gl_Position = viewProjection * position;
gl_Position.z = 1.0;
}

View File

@@ -0,0 +1,58 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2016 *
* *
* 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. *
****************************************************************************************/
uniform vec4 color#{id};
uniform float time#{id};
uniform float maxStepSize#{id} = 0.02;
vec4 sample#{id}(vec3 samplePos, vec3 dir, vec4 foregroundColor, inout float maxStepSize) {
maxStepSize = maxStepSize#{id};
// Generate an arbitrary procedural volume.
// In real situations, the sample function would sample a
// 3D texture to retrieve the color contribution of a given point.
vec3 fromCenter = vec3(0.5, 0.5, 0.5) - samplePos;
vec4 c = color#{id};
float r = length(fromCenter);
c.a *= (1.0 - smoothstep(0.4, 0.45, r));
c.a *= (1.0 - smoothstep(0.35, 0.3, r));
c.a *= (1.0 - smoothstep(0.1, 0.2, abs(fromCenter.y)));
float theta = atan(fromCenter.x, fromCenter.z);
float angularRatio = (theta + 3.1415) / 6.283;
angularRatio = mod(angularRatio + time#{id}*0.01, 1.0);
c.a *= smoothstep(0.0, 0.2, clamp(angularRatio, 0.0, 1.0));
c.a *= smoothstep(1.0, 0.8, clamp(angularRatio, 0.0, 1.0));
return c;
}
float stepSize#{id}(vec3 samplePos, vec3 dir) {
return maxStepSize#{id};
}

View File

@@ -0,0 +1,44 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 <modules/toyvolume/toyvolumemodule.h>
#include <openspace/rendering/renderable.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/misc/assert.h>
#include <modules/toyvolume/rendering/renderabletoyvolume.h>
namespace openspace {
ToyVolumeModule::ToyVolumeModule() : OpenSpaceModule("ToyVolume") {}
void ToyVolumeModule::internalInitialize() {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "No renderable factory existed");
fRenderable->registerClass<RenderableToyVolume>("RenderableToyVolume");
}
} // namespace openspace

View File

@@ -0,0 +1,40 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 __TOYVOLUMEMODULE_H__
#define __TOYVOLUMEMODULE_H__
#include <openspace/util/openspacemodule.h>
namespace openspace {
class ToyVolumeModule : public OpenSpaceModule {
public:
ToyVolumeModule();
void internalInitialize() override;
};
} // namespace openspace
#endif // __TOYVOLUMEMODULE_H__

View File

@@ -88,4 +88,82 @@ vec4 z_normalization(vec4 v_in) {
return v_out;
}
/**
* Compute the length of a vector.
* Supporting huge vectors, where the square of any of the components is too large to represent as a float.
*/
float safeLength(vec4 v) {
float m = max(max(max(abs(v.x), abs(v.y)), abs(v.z)), abs(v.w));
if (m > 0.0) {
return length(v / m) * m;
} else {
return 0;
}
}
float safeLength(vec3 v) {
float m = max(max(abs(v.x), abs(v.y)), abs(v.z));
if (m > 0.0) {
return length(v / m) * m;
} else {
return 0;
}
}
float safeLength(vec2 v) {
float m = max(abs(v.x), abs(v.y));
if (m > 0.0) {
return length(v / m) * m;
} else {
return 0;
}
}
/**
* Normalize a vector
* Supporting huge vectors, where the square of any of the components is too large to represent as a float.
*/
vec3 safeNormalize(vec3 v) {
float m = max(max(abs(v.x), abs(v.y)), abs(v.z));
return normalize(v / m);
}
/**
* Convert a psc vector to a float
*/
vec3 pscToLinear(vec4 position) {
return pow(k, position.w) * position.xyz;
}
/**
* Convert a psc scalar to a float
*/
float pscToLinear(vec2 position) {
return pow(k, position.y) * position.x;
}
/**
* Convert a positive floating point distance [0, 10^27]
* (size of observable universe)
* to a float in the range [-1, 1], suitable for depth buffer storage.
* Note: This needs to be a monotonic function, so that the value can
* still be used for depth comparison.
*/
float normalizeFloat(float input) {
if (input > 1.0) {
return input / pow(10, 27);
} else {
return input - 1.0;
}
}
float denormalizeFloat(float input) {
if (input < 0.0) {
return input + 1.0;
} else {
return input * pow(10, 27);
}
}
#endif

View File

@@ -47,11 +47,15 @@ vec4 psc_normlization(vec4 invec) {
}
}
float pscDepth(vec4 position) {
// For now: simply convert power scaled coordinates to a linear scale.
// TODO: get rid of power scaled coordinates and use scale graph instead.
return (position.w + log(abs(position.z) + 1/pow(k, position.w))/log(k)) / 27.0;
// return (position.w + log(abs(position.z) + 1/pow(k, position.w))/log(k)) / 27.0;
return safeLength(pscToLinear(position));
}
#endif

View File

@@ -41,7 +41,7 @@ struct ABufferFragment {
// -------DEPTH-------
// depth 32 bits
// -------DATA--------
// type 8 bits 0: geometry, >0: volume, <0: reserved
// type 8 bits (signed char) 0: geometry, >0: volume entry, <0: volume exit
// msaa 8 bits
// reserved 16 bits
// ----COMPOSITION----
@@ -104,13 +104,22 @@ float _depth_(ABufferFragment frag) {
* Type
*/
void _type_(inout ABufferFragment frag, int type) {
uint val = uint(type);
uint val;
if (type < 0) {
val = uint(-type) + 128;
} else {
val = type;
}
bitinsert(frag.data, val, mask_type, shift_type);
}
int _type_(ABufferFragment frag) {
uint val = bitextract(frag.data, mask_type, shift_type);
return int(val);
if (val > 127) {
return 128 - int(val);
} else {
return int(val);
}
}
/**

View File

@@ -25,16 +25,15 @@
#ifndef _ABUFFERRESOURCES_GLSL_
#define _ABUFFERRESOURCES_GLSL_
#include "abufferfragment.glsl"
#define MAX_LAYERS #{rendererData.maxLayers}
#include "abufferfragment.glsl"
ABufferFragment fragments[MAX_LAYERS];
layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture;
layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture;
layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer;
ABufferFragment fragments[MAX_LAYERS];
uint indices[MAX_LAYERS];
const uint NULL_POINTER = 0;
void storeFragment(uint index, ABufferFragment aBufferFrag) {
@@ -50,17 +49,15 @@ ABufferFragment loadFragment(uint index) {
/**
* Load fragments into the #fragments array.
* Also set #indices to the used indices.
*/
uint loadFragments() {
uint currentIndex = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x;
int nFrags = 0;
while (currentIndex != NULL_POINTER && nFrags < MAX_LAYERS) {
ABufferFragment frag = loadFragment(currentIndex);
indices[nFrags] = currentIndex;
fragments[nFrags] = frag;
nFrags++;
currentIndex = _next_(frag);
nFrags++;
}
return nFrags;
}

View File

@@ -0,0 +1,60 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
#include "fragment.glsl"
#include <#{fragmentPath}>
#include "abufferfragment.glsl"
#include "abufferresources.glsl"
uniform bool _exit_;
out vec4 _out_color_;
void main() {
Fragment frag = getFragment();
int sampleMask = gl_SampleMaskIn[0];
uint newHead = atomicCounterIncrement(atomicCounterBuffer);
uint prevHead = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), newHead);
ABufferFragment aBufferFrag;
_color_(aBufferFrag, frag.color);
_depth_(aBufferFrag, frag.depth);
int fragmentType = #{fragmentType};
if (_exit_) {
fragmentType *= -1;
}
_type_(aBufferFrag, fragmentType);
_msaa_(aBufferFrag, gl_SampleMaskIn[0]);
_next_(aBufferFrag, prevHead);
storeFragment(newHead, aBufferFrag);
discard;
}

View File

@@ -0,0 +1,35 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* 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 _RAYCASTERDATA_GLSL_
#define _RAYCASTERDATA_GLSL_
struct RaycasterData {
vec3 position;
vec3 direction;
float scale;
float previousJitterDistance;
}
#endif

View File

@@ -35,6 +35,9 @@ void main() {
int sampleMask = gl_SampleMaskIn[0];
uint newHead = atomicCounterIncrement(atomicCounterBuffer);
if (newHead >= #{rendererData.maxTotalFragments}) {
discard; // ABuffer is full!
}
uint prevHead = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), newHead);
ABufferFragment aBufferFrag;

View File

@@ -27,32 +27,52 @@
#include "abufferfragment.glsl"
#include "abufferresources.glsl"
#include "fragment.glsl"
#include "PowerScaling/powerScalingMath.hglsl"
#include "blending.glsl"
#include "rand.glsl"
layout (location = 0) out vec4 finalColor;
uniform float blackoutFactor;
uniform int nAaSamples;
void sortFragments(uint nFrags) {
ABufferFragment tmp;
uint i, j;
// Insertion sort
for(i = 1; i < nFrags; ++i) {
tmp = fragments[i];
for(j = i; j > 0 && _depth_(tmp) < _depth_(fragments[j-1]); --j) {
fragments[j] = fragments[j-1];
}
fragments[j] = tmp;
}
}
#define RAYCASTING_ENABLED #{raycastingEnabled}
#define N_RAYCASTERS #{nRaycasters}
#define ALPHA_LIMIT 0.99
#define RAYCAST_MAX_STEPS 1000
#define INT_MAX 2147483647
vec4 blend(vec4 front, vec4 back) {
vec4 result;
result.a = front.a + (1.0 - front.a) * back.a;
result.rgb = ((front.rgb * front.a) + (back.rgb * back.a * (1.0 - front.a))) / result.a;
result = clamp(result, 0.0, 1.0);
return result;
/////////////////////////
#if RAYCASTING_ENABLED
#include "raycasterdata.glsl"
RaycasterData raycasterData[N_RAYCASTERS];
// Include all ray caster helpers
#for id, helperPath in helperPaths
#include <#{helperPath}>
#endfor
// Include all ray casters
#for id, raycaster in raycasters
#include <#{raycaster.raycastPath}>
#endfor
#endif
/////////////////////////
void sortFragments(uint nFrags) {
ABufferFragment tmp;
uint i, j;
// Insertion sort
for(i = 1; i < nFrags; ++i) {
tmp = fragments[i];
for(j = i; j > 0 && _depth_(tmp) < _depth_(fragments[j-1]); --j) {
fragments[j] = fragments[j-1];
}
fragments[j] = tmp;
}
}
uint countSamples(uint mask) {
@@ -66,39 +86,172 @@ uint countSamples(uint mask) {
+ ((mask >> 7) & 1);
}
uint reduceFragments(uint nFrags) {
uint outputIndex = 0;
for (uint inputIndex = 0; inputIndex < nFrags; inputIndex++, outputIndex++) {
ABufferFragment frag = fragments[inputIndex];
uint accumulatedMask = _msaa_(fragments[inputIndex]);
uint newMask = _msaa_(fragments[inputIndex]);
int type = _type_(fragments[inputIndex]);
// Accumulate sample mask
for (uint j = inputIndex + 1;
j < nFrags && ((newMask = _msaa_(fragments[j])) & accumulatedMask) == 0 && _type_(fragments[j]) == type;
j++) {
accumulatedMask |= newMask;
inputIndex = j;
}
uint nSamples = countSamples(accumulatedMask);
vec4 color = _color_(fragments[inputIndex]); // TODO: Possibly weigh all samples together?
// Adjust the alpha by the ratio of accumulated samples
float alpha = float(nSamples) / float(nAaSamples);
color.a *= alpha;
ABufferFragment outputFragment = fragments[inputIndex];
_color_(outputFragment, color);
fragments[outputIndex] = outputFragment;
}
// return number of outputted fragments
return outputIndex;
}
#if RAYCASTING_ENABLED
/**
* Iterate through list of sorted fragments,
* and retrieve raycasting position, direction, scale
*/
void retrieveRaycasterData(uint nFrags) {
float entryDepths[N_RAYCASTERS];
for (int i = 0; i < N_RAYCASTERS; i++) {
entryDepths[i] = -1;
}
for (int i = 0; i < nFrags; i++) {
int type = _type_(fragments[i]); // - 1;
vec4 color = _color_(fragments[i]);
float depth = _depth_(fragments[i]);
if (type > 0) { // enter raycaster
int raycasterId = type - 1;
if (entryDepths[raycasterId] < 0) { // first entry
raycasterData[raycasterId].position = color.rgb;
raycasterData[raycasterId].previousJitterDistance = 0;
entryDepths[raycasterId] = depth;
raycasterData[raycasterId].scale = -1;
}
} else if (type < 0) { // exit raycaster
int raycasterId = -type - 1;
vec3 localDirection = color.xyz - raycasterData[raycasterId].position;
raycasterData[raycasterId].direction = safeNormalize(localDirection);
raycasterData[raycasterId].scale = safeLength(localDirection) / (depth - entryDepths[raycasterId]);
}
}
}
/**
* Perform raycasting
*/
void raycast(float raycastDepth, uint raycasterMask, inout vec4 finalColor) {
float nextStepSize = raycastDepth;
float currentStepSize = 0.0;
float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0
#for index, raycaster in raycasters
if ((raycasterMask & #{raycaster.bitmask}) != 0) {
RaycasterData data = raycasterData[#{index}];
float maxStepSizeLocal = stepSize#{raycaster.id}(data.position, data.direction);
float maxStepSize = maxStepSizeLocal / data.scale;
nextStepSize = min(nextStepSize, maxStepSize);
}
#endfor
float currentDepth = 0.0;
for (int steps = 0; finalColor.a < ALPHA_LIMIT && steps < RAYCAST_MAX_STEPS; ++steps) {
bool exceededDepth = currentDepth + nextStepSize * jitterFactor > raycastDepth;
bool shortStepSize = nextStepSize < raycastDepth / 10000000000.0;
if (exceededDepth || shortStepSize) {
break;
}
currentStepSize = nextStepSize;
currentDepth += currentStepSize;
nextStepSize = raycastDepth - currentDepth;
#for index, raycaster in raycasters
if ((raycasterMask & #{raycaster.bitmask}) != 0) {
RaycasterData data = raycasterData[#{raycaster.id}];
float stepSizeLocal = currentStepSize * data.scale;
float jitteredStepSizeLocal = stepSizeLocal * jitterFactor;
vec3 jitteredPosition = data.position + data.direction*jitteredStepSizeLocal;
raycasterData[#{raycaster.id}].position += data.direction * stepSizeLocal;
float maxStepSizeLocal;
vec4 raycasterContribution = sample#{raycaster.id}(jitteredPosition, data.direction, finalColor, maxStepSizeLocal);
float sampleDistance = jitteredStepSizeLocal + data.previousJitterDistance;
blendStep(finalColor, raycasterContribution, sampleDistance);
raycasterData[#{raycaster.id}].previousJitterDistance = stepSizeLocal - jitteredStepSizeLocal;
float maxStepSize = maxStepSizeLocal/data.scale;
nextStepSize = min(nextStepSize, maxStepSize);
}
#endfor
}
}
#endif // RAYCASTING_ENABLED
void main() {
finalColor = vec4(0.0);
uint nFrags = loadFragments();
sortFragments(nFrags);
int realFrags = 0;
uint nOriginalFrags = loadFragments();
uint raycasterMask = 0;
sortFragments(nOriginalFrags);
uint nFrags = reduceFragments(nOriginalFrags);
#if RAYCASTING_ENABLED
retrieveRaycasterData(nFrags);
#endif
for (uint i = 0; i < nFrags; i++) {
ABufferFragment frag = fragments[i];
uint accumulatedMask = _msaa_(fragments[i]);
uint newMask = _msaa_(fragments[i]);
int type = _type_(frag);
vec4 color = vec4(0.0);
float totalAlpha = 0.0;
for (uint j = i + 1;
j < nFrags
&& ((newMask = _msaa_(fragments[j])) & accumulatedMask) == 0;
j++) {
accumulatedMask |= newMask;
i = j;
if (type == 0) { // geometry fragment
vec4 color = _color_(frag);
blend(finalColor, color);
}
uint nSamples = countSamples(accumulatedMask);
color = _color_(fragments[i]); // TODO: Possibly weigh all samples together?
color.a *= float(nSamples) / float(nAaSamples);
finalColor = blend(finalColor, color);
#if RAYCASTING_ENABLED
else if (type > 0) { // enter volume
int raycasterId = type - 1;
// only enter volume if a valid scale was detected
if (raycasterData[raycasterId].scale > 0) {
raycasterMask |= (1 << (raycasterId));
}
} else { // exit volume
int raycasterId = -type - 1;
raycasterMask &= INT_MAX - (1 << (raycasterId));
}
// Ray cast to next fragment
if (i + 1 < nFrags && raycasterMask != 0) {
float startDepth = _depth_(fragments[i]);
float endDepth = _depth_(fragments[i + 1]);
raycast(endDepth - startDepth, raycasterMask, finalColor);
}
#endif
}
finalColor.a *= blackoutFactor;
// finalColor is expressed with premultiplied alpha
finalColor.rgb *= blackoutFactor;
// Render everything on a black background
finalColor.a = 1.0;
}

50
shaders/blending.glsl Normal file
View File

@@ -0,0 +1,50 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2016 *
* *
* 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 _BLENDING_GLSL_
#define _BLENDING_GLSL_
/**
* Blend in src behind dst
* dst is premultiplied
* src is expressed in straight RGBA
*/
void blend(inout vec4 dst, vec4 src) {
dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb;
dst.a = dst.a + (1.0 - dst.a) * src.a;
}
/**
* Blend in src behind dst
* dst is premultiplied
* src is expressed in straight RGBA
* stepSize = 0: alpha becomes 0
* stepSize = 1: alpha becomes src.a
*/
void blendStep(inout vec4 dst, vec4 src, float stepSize) {
src.a = 1.0 - pow(1.0 - src.a, stepSize);
blend(dst, src);
}
#endif

View File

@@ -0,0 +1,37 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScalingMath.hglsl"
#include <#{fragmentPath}>
out vec4 _out_color_;
void main() {
Fragment f = getFragment();
_out_color_ = f.color;
gl_FragDepth = normalizeFloat(f.depth);
}

View File

@@ -0,0 +1,151 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2016 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
uniform sampler2D exitColorTexture;
uniform sampler2D exitDepthTexture;
uniform sampler2DMS mainDepthTexture;
#include "blending.glsl"
#include "rand.glsl"
#include "PowerScaling/powerScalingMath.hglsl"
#include <#{fragmentPath}>
#for id, helperPath in helperPaths
#include <#{helperPath}>
#endfor
#include <#{raycastPath}>
out vec4 finalColor;
#define ALPHA_LIMIT 0.99
#define RAYCAST_MAX_STEPS 1000
#define MAX_AA_SAMPLES 8
uniform int nAaSamples;
void main() {
vec2 texCoord = vec2(gl_FragCoord.x / #{rendererData.windowWidth},
gl_FragCoord.y / #{rendererData.windowHeight});
vec4 exitColorTexture = texture(exitColorTexture, texCoord);
if (exitColorTexture.a < 1.0) {
discard;
}
// fetch exit point from texture
vec3 exitPos = exitColorTexture.rgb;
float exitDepth = denormalizeFloat(texture(exitDepthTexture, texCoord).x);
float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0
// fetch entry point from rendered fragment
Fragment f = getFragment();
vec3 entryPos = f.color.xyz;
float entryDepth = f.depth;
vec3 position = entryPos;
vec3 diff = exitPos - entryPos;
vec3 direction = normalize(diff);
float raycastDepth = length(diff);
float raycastDepths[MAX_AA_SAMPLES];
int i, j;
float tmp;
for (i = 0; i < nAaSamples; i++) {
float geoDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), i).x);
float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.0, 1.0);
raycastDepths[i] = geoRatio * raycastDepth;
}
for(i = 1; i < nAaSamples; ++i) {
tmp = raycastDepths[i];
for(j = i; j > 0 && tmp < raycastDepths[j - 1]; --j) {
raycastDepths[j] = raycastDepths[j-1];
}
raycastDepths[j] = tmp;
}
finalColor = vec4(0.0);
float currentDepth = 0.0;
// todo: shorten depth if geometry is intersecting!
float nextStepSize = stepSize#{id}(position, direction);
float currentStepSize;
float previousJitterDistance = 0.0;
int steps = 0;
float aaOpacity = 1.0;
int sampleIndex = 0;
float opacityDecay = 1.0 / nAaSamples;
for (steps = 0; finalColor.a < ALPHA_LIMIT && steps < RAYCAST_MAX_STEPS; ++steps) {
while (sampleIndex < nAaSamples && currentDepth + nextStepSize * jitterFactor > raycastDepths[sampleIndex]) {
sampleIndex++;
aaOpacity -= opacityDecay;
}
bool shortStepSize = nextStepSize < raycastDepth / 10000000000.0;
if (sampleIndex >= nAaSamples || shortStepSize) {
break;
}
currentStepSize = nextStepSize;
currentDepth += currentStepSize;
float jitteredStepSize = currentStepSize * jitterFactor;
vec3 jitteredPosition = position + direction*jitteredStepSize;
position += direction * currentStepSize;
vec4 raycasterContribution = sample#{id}(jitteredPosition, direction, finalColor, nextStepSize);
float sampleDistance = aaOpacity * (jitteredStepSize + previousJitterDistance);
blendStep(finalColor, raycasterContribution, sampleDistance);
previousJitterDistance = currentStepSize - jitteredStepSize;
float maxStepSize = raycastDepths[nAaSamples - 1] - currentDepth;
nextStepSize = min(nextStepSize, maxStepSize);
}
finalColor.rgb /= finalColor.a;
gl_FragDepth = normalizeFloat(entryDepth);
}

View File

@@ -0,0 +1,33 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 <#{fragmentPath}>
out vec4 _out_color_;
void main() {
Fragment f = getFragment();
_out_color_ = f.color;
gl_FragDepth = normalizeFloat(f.depth);
}

View File

@@ -0,0 +1,45 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScalingMath.hglsl"
layout (location = 0) out vec4 finalColor;
uniform float blackoutFactor;
uniform int nAaSamples;
uniform sampler2DMS mainColorTexture;
void main() {
vec4 color = vec4(0.0);
for (int i = 0; i < nAaSamples; i++) {
color += texelFetch(mainColorTexture, ivec2(gl_FragCoord), i);
}
color /= nAaSamples;
color.rgb *= blackoutFactor;
finalColor = vec4(color.rgb, 1.0);
}

View File

@@ -0,0 +1,33 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
in vec4 position;
out vec2 texCoord;
void main() {
gl_Position = position;
texCoord = 0.5 + position.xy / 2.0;
}

35
shaders/rand.glsl Normal file
View File

@@ -0,0 +1,35 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2016 *
* *
* 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 _RAND_GLSL_
#define _RAND_GLSL_
/**
* Return a random number between 0 and 1, based on a vec2
*/
float rand(vec2 co){
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
#endif

View File

@@ -1,9 +0,0 @@
#include <#{fragmentPath}>
out vec4 _out_color_;
void main() {
Fragment f = getFragment();
_out_color_ = f.color;
gl_FragDepth = f.depth;
}

View File

@@ -60,6 +60,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/query/query.cpp
${OPENSPACE_BASE_DIR}/src/rendering/abufferrenderer.cpp
${OPENSPACE_BASE_DIR}/src/rendering/framebufferrenderer.cpp
${OPENSPACE_BASE_DIR}/src/rendering/raycastermanager.cpp
${OPENSPACE_BASE_DIR}/src/rendering/renderable.cpp
${OPENSPACE_BASE_DIR}/src/rendering/renderengine.cpp
${OPENSPACE_BASE_DIR}/src/rendering/renderengine_lua.inl
@@ -129,11 +130,14 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/query/query.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/abufferrenderer.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/framebufferrenderer.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/raycasterlistener.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/raycastermanager.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderable.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderer.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderengine.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/volume.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/screenspacerenderable.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/volumeraycaster.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/ephemeris.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/scene.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenegraph.h

View File

@@ -39,8 +39,8 @@ namespace properties {
[](lua_State* state, bool& success) -> __TYPE__ { \
__TYPE__ result; \
int number = 1; \
for (glm::length_t i = 0; i < __TYPE__::rows; ++i) { \
for (glm::length_t j = 0; j < __TYPE__::cols; ++j) { \
for (glm::length_t i = 0; i < ghoul::glm_rows<__TYPE__>::value; ++i) { \
for (glm::length_t j = 0; j < ghoul::glm_cols<__TYPE__>::value; ++j) { \
lua_getfield(state, -1, std::to_string(number).c_str()); \
if (lua_isnumber(state, -1) != 1) { \
success = false; \
@@ -61,8 +61,8 @@ namespace properties {
[](lua_State* state, __TYPE__ value) -> bool { \
lua_newtable(state); \
int number = 1; \
for (glm::length_t i = 0; i < __TYPE__::rows; ++i) { \
for (glm::length_t j = 0; j < __TYPE__::cols; ++j) { \
for (glm::length_t i = 0; i < ghoul::glm_rows<__TYPE__>::value; ++i) { \
for (glm::length_t j = 0; j < ghoul::glm_cols<__TYPE__>::value; ++j) { \
lua_pushnumber(state, static_cast<lua_Number>(value[i][j])); \
lua_setfield(state, -2, std::to_string(number).c_str()); \
++number; \
@@ -75,13 +75,15 @@ namespace properties {
[](std::string value, bool& success) -> __TYPE__ { \
__TYPE__ result; \
std::vector<std::string> tokens = ghoul::tokenizeString(value, ','); \
if (tokens.size() != (__TYPE__::rows * __TYPE__::cols)) { \
if (tokens.size() != \
(ghoul::glm_rows<__TYPE__>::value * ghoul::glm_cols<__TYPE__>::value)) \
{ \
success = false; \
return result; \
} \
int number = 0; \
for (glm::length_t i = 0; i < __TYPE__::rows; ++i) { \
for (glm::length_t j = 0; j < __TYPE__::cols; ++j) { \
for (glm::length_t i = 0; i < ghoul::glm_rows<__TYPE__>::value; ++i) { \
for (glm::length_t j = 0; j < ghoul::glm_cols<__TYPE__>::value; ++j) { \
std::stringstream s(tokens[number]); \
__TYPE__::value_type v; \
s >> v; \
@@ -102,8 +104,8 @@ namespace properties {
#define DEFAULT_TO_STRING_LAMBDA(__TYPE__) \
[](std::string& outValue, __TYPE__ inValue) -> bool { \
outValue = ""; \
for (glm::length_t i = 0; i < __TYPE__::rows; ++i) { \
for (glm::length_t j = 0; j < __TYPE__::cols; ++j) { \
for (glm::length_t i = 0; i < ghoul::glm_rows<__TYPE__>::value; ++i) { \
for (glm::length_t j = 0; j < ghoul::glm_cols<__TYPE__>::value; ++j) { \
outValue += std::to_string(inValue[i][j]) + ","; \
} \
outValue.pop_back(); \

View File

@@ -39,7 +39,7 @@ namespace properties {
[](lua_State * state, bool& success) -> __TYPE__ { \
__TYPE__ result; \
lua_pushnil(state); \
for (glm::length_t i = 0; i < __TYPE__::components; ++i) { \
for (glm::length_t i = 0; i < ghoul::glm_components<__TYPE__>::value; ++i) { \
int success = lua_next(state, -2); \
if (success != 1) { \
success = false; \
@@ -61,7 +61,7 @@ namespace properties {
[](lua_State * state, __TYPE__ value) -> bool { \
lua_newtable(state); \
int number = 1; \
for (glm::length_t i = 0; i < __TYPE__::components; ++i) { \
for (glm::length_t i = 0; i < ghoul::glm_components<__TYPE__>::value; ++i) { \
lua_pushnumber(state, static_cast<lua_Number>(value[i])); \
lua_setfield(state, -2, std::to_string(number).c_str()); \
++number; \
@@ -77,7 +77,7 @@ namespace properties {
success = false; \
return result; \
} \
for (glm::length_t i = 0; i < __TYPE__::components; ++i) { \
for (glm::length_t i = 0; i < ghoul::glm_components<__TYPE__>::value; ++i) { \
std::stringstream s(tokens[i]); \
__TYPE__::value_type v; \
s >> v; \
@@ -95,7 +95,7 @@ namespace properties {
#define DEFAULT_TO_STRING_LAMBDA(__TYPE__) \
[](std::string& outValue, __TYPE__ inValue) -> bool { \
outValue = "{"; \
for (glm::length_t i = 0; i < __TYPE__::components; ++i) \
for (glm::length_t i = 0; i < ghoul::glm_components<__TYPE__>::value; ++i) \
outValue += std::to_string(inValue[i]) + ","; \
outValue.pop_back(); \
outValue += "}"; \

View File

@@ -23,31 +23,44 @@
****************************************************************************************/
#include <openspace/rendering/abufferrenderer.h>
#include <openspace/rendering/raycastermanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/wrapper/windowwrapper.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/volumeraycaster.h>
#include <openspace/scene/scene.h>
#include <openspace/util/camera.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/misc/exception.h>
#include <string>
#include <iterator>
namespace {
const std::string _loggerCat = "ABufferRenderer";
const std::string BoundsFragmentShaderPath = "${SHADERS}/abuffer/boundsabuffer.frag";
const std::string RenderFragmentShaderPath = "${SHADERS}/abuffer/renderabuffer.frag";
const int MaxRaycasters = 32;
const int MaxLayers = 16;
const int MaxAverageLayers = 8;
}
namespace openspace {
ABufferRenderer::ABufferRenderer()
ABufferRenderer::ABufferRenderer()
: _camera(nullptr)
, _scene(nullptr)
, _resolution(glm::ivec2(0))
, _dirtyResolution(true)
, _dirtyRaycastData(true)
, _dirtyRendererData(true)
, _dirtyResolveDictionary(true)
, _resolveProgram(nullptr) { }
ABufferRenderer::~ABufferRenderer() {}
@@ -85,23 +98,27 @@ void ABufferRenderer::initialize() {
glGenBuffers(1, &_fragmentBuffer);
glGenTextures(1, &_fragmentTexture);
if (_dirtyResolution) {
updateResolution();
}
updateRendererData();
ghoul::Dictionary dict = createResolveDictionary();
_resolveProgram = ghoul::opengl::ProgramObject::Build("ABuffer Resolve",
"${SHADERS}/abuffer/resolveabuffer.vert",
"${SHADERS}/abuffer/resolveabuffer.frag",
dict);
_nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples();
if (_nAaSamples > 8) {
LERROR("ABuffer does not support more than 8 MSAA samples.");
LERROR("ABuffer renderer does not support more than 8 MSAA samples.");
_nAaSamples = 8;
}
updateResolution();
updateRendererData();
updateRaycastData();
updateResolveDictionary();
try {
_resolveProgram = ghoul::opengl::ProgramObject::Build("ABuffer Resolve",
"${SHADERS}/abuffer/resolveabuffer.vert",
"${SHADERS}/abuffer/resolveabuffer.frag",
_resolveDictionary);
} catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
OsEng.renderEngine().raycasterManager().addListener(*this);
}
void ABufferRenderer::deinitialize() {
@@ -115,65 +132,134 @@ void ABufferRenderer::deinitialize() {
glDeleteBuffers(1, &_vertexPositionBuffer);
glDeleteVertexArrays(1, &_screenQuad);
OsEng.renderEngine().raycasterManager().removeListener(*this);
}
void ABufferRenderer::raycastersChanged(VolumeRaycaster& raycaster, bool attached) {
(void) raycaster;
(void) attached;
_dirtyRaycastData = true;
}
void ABufferRenderer::update() {
bool dirtyRendererData = false;
bool dirtyResolveDictionary = false;
// Make sure that the fragment buffer has the correct resoliution
// according to the output render buffer size
if (_dirtyResolution) {
updateResolution();
}
if (dirtyRendererData) {
dirtyResolveDictionary = true;
// Make sure that the renderengine gets the correct render data
// to feed into all render programs.
// This will trigger a recompilation of all the shader programs
// involved in rendering geometries.
if (_dirtyRendererData) {
updateRendererData();
}
// TODO: Collect volumes from scene graph.
// Diff against cache, update cache.
// possibly mark resolve dictionary as dirty
if (dirtyResolveDictionary) {
ghoul::Dictionary dict = createResolveDictionary();
_resolveProgram->setDictionary(dict);
// Make sure that all raycaster data is up to date.
if (_dirtyRaycastData) {
updateRaycastData();
}
if (_resolveProgram->isDirty()) {
_resolveProgram->rebuildFromFile();
// Make sure that the resolve dictionary is up to date.
// The resolve dictionary contains information for all
// ray casters, including shader include paths.
if (_dirtyResolveDictionary) {
updateResolveDictionary();
_resolveProgram->setDictionary(_resolveDictionary);
}
// If the resolve dictionary changed (or a file changed on disk)
// then rebuild the resolve program.
if (_resolveProgram->isDirty()) {
try {
_resolveProgram->rebuildFromFile();
} catch (ghoul::RuntimeError& error) {
LERROR(error.message);
}
}
for (auto &program : _boundsPrograms) {
if (program.second->isDirty()) {
try {
program.second->rebuildFromFile();
} catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
}
}
}
void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) {
if (_scene == nullptr) return;
if (_camera == nullptr) return;
// Reset
clear();
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
clear();
// Step 1: Render geometries to the fragment buffer
// Bind head-pointer image for read-write
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer);
// Bind head-pointer image for read-write
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer);
glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
_scene->render({ *_camera, psc(), doPerformanceMeasurements });
// Step 2: Render volumes to the fragment buffer
//TODO: Implement this
// Render the scene to the fragment buffer. Collect renderer tasks (active raycasters)
RenderData data{ *_camera, psc(), doPerformanceMeasurements };
RendererTasks tasks;
_scene->render(data, tasks);
// Step 2: Perform raycasting tasks requested by the scene
for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) {
VolumeRaycaster* raycaster = raycasterTask.raycaster;
ghoul::opengl::ProgramObject* program = _boundsPrograms[raycaster].get();
if (program) {
program->activate();
program->setUniform("_exit_", false);
raycaster->renderEntryPoints(raycasterTask.renderData, *program);
program->setUniform("_exit_", true);
raycaster->renderExitPoints(raycasterTask.renderData, *program);
program->deactivate();
}
else {
LWARNING("Raycaster is not attached when trying to perform raycaster task");
}
}
// Step 3: Resolve the buffer
_resolveProgram->activate();
// 3a: Perform the pre-raycast step for all raycaster tasks.
for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) {
VolumeRaycaster* raycaster = raycasterTask.raycaster;
auto raycastData = _raycastData.find(raycaster);
if (raycastData != _raycastData.end()) {
raycaster->preRaycast(raycastData->second, *_resolveProgram.get());
}
}
// 3b: Set "global" uniforms, and start the resolve pass.
_resolveProgram->setUniform("blackoutFactor", blackoutFactor);
_resolveProgram->setUniform("nAaSamples", _nAaSamples);
// todo: pre-ray-cast for each volume
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
// todo: post-ray-cast for each volume
// 3c: Perform the post-raycast step for all raycaster tasks.
for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) {
VolumeRaycaster* raycaster = raycasterTask.raycaster;
auto raycastData = _raycastData.find(raycaster);
if (raycastData != _raycastData.end()) {
raycaster->postRaycast(raycastData->second, *_resolveProgram.get());
}
}
_resolveProgram->deactivate();
}
@@ -223,7 +309,7 @@ void ABufferRenderer::updateResolution() {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer);
glBufferData(GL_TEXTURE_BUFFER, MaxLayers*totalPixels*sizeof(GLuint) * 4, NULL, GL_DYNAMIC_COPY);
glBufferData(GL_TEXTURE_BUFFER, MaxAverageLayers*totalPixels*sizeof(GLuint) * 4, NULL, GL_DYNAMIC_COPY);
glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer);
@@ -233,27 +319,125 @@ void ABufferRenderer::updateResolution() {
_dirtyResolution = false;
}
ghoul::Dictionary ABufferRenderer::createResolveDictionary() {
void ABufferRenderer::updateResolveDictionary() {
ghoul::Dictionary dict;
ghoul::Dictionary raycastersDict;
for (const auto &raycastPair : _raycastData) {
ghoul::Dictionary innerDict;
int id = raycastPair.second.id;
std::string namespaceName = raycastPair.second.namespaceName;
std::string raycastPath = raycastPair.first->getRaycastPath();
innerDict.setValue("id", id);
innerDict.setValue("namespace", namespaceName);
innerDict.setValue("bitmask", 1 << id);
innerDict.setValue("raycastPath", raycastPath);
raycastersDict.setValue(std::to_string(id), innerDict);
}
dict.setValue("raycasters", raycastersDict);
ghoul::Dictionary helperPathsDict;
for (int i = 0; i < _helperPaths.size(); i++) {
helperPathsDict.setValue(std::to_string(i), _helperPaths[i]);
}
dict.setValue("helperPaths", helperPathsDict);
dict.setValue("rendererData", _rendererData);
// TODO: Add volume data to dictionary
// such as id, bitmask, path to raycaster frag shader, helpers, nVolumes...
return dict;
dict.setValue("raycastingEnabled", _raycastData.size() > 0);
dict.setValue("nRaycasters", static_cast<unsigned long long>(_raycastData.size()));
_resolveDictionary = dict;
_dirtyResolveDictionary = false;
}
void ABufferRenderer::updateRaycastData() {
_raycastData.clear();
_boundsPrograms.clear();
_helperPaths.clear();
const std::vector<VolumeRaycaster*>& raycasters = OsEng.renderEngine().raycasterManager().raycasters();
std::map<std::string, int> namespaceIndices;
int nextId = 0; // raycaster ids are positive integers starting at 0. (for raycasters, fragment type is id+1)
int nextNamespaceIndex = 0;
for (auto &raycaster : raycasters) {
if (nextId > MaxRaycasters) {
int nIgnored = MaxRaycasters - raycasters.size();
LWARNING("ABufferRenderer does not support more than 32 raycasters. Ignoring " << nIgnored << " raycasters");
break;
}
RaycastData data;
data.id = nextId++;
std::string helperPath = raycaster->getHelperPath();
// Each new helper path generates a new namespace,
// to avoid glsl name collisions between raycaster implementaitons.
// Assign a new namespace or find an already created index.
if (helperPath == "") {
data.namespaceName = "NAMESPACE_" + std::to_string(nextNamespaceIndex++);
} else {
auto iter = namespaceIndices.find(helperPath);
if (iter == namespaceIndices.end()) {
int namespaceIndex = nextNamespaceIndex++;
data.namespaceName = std::to_string(namespaceIndex);
namespaceIndices[helperPath] = namespaceIndex;
_helperPaths.push_back(helperPath);
}
else {
data.namespaceName = "NAMESPACE_" + std::to_string(iter->second);
}
}
_raycastData[raycaster] = data;
std::string vsPath = raycaster->getBoundsVsPath();
std::string fsPath = raycaster->getBoundsFsPath();
ghoul::Dictionary dict;
// set path to the current renderer's main fragment shader
dict.setValue("rendererData", _rendererData);
// parameterize the main fragment shader program with specific contents.
// fsPath should point to a shader file defining a Fragment getFragment() function
// instead of a void main() setting glFragColor, glFragDepth, etc.
dict.setValue("fragmentPath", fsPath);
dict.setValue("fragmentType", data.id + 1);
try {
_boundsPrograms[raycaster] = ghoul::opengl::ProgramObject::Build("Volume " + std::to_string(data.id) + " bounds", vsPath, BoundsFragmentShaderPath, dict);
}
catch (ghoul::RuntimeError& error) {
LERROR(error.message);
}
}
_dirtyRaycastData = false;
_dirtyResolveDictionary = true;
}
void ABufferRenderer::updateRendererData() {
ghoul::Dictionary dict;
dict.setValue("windowWidth", OsEng.windowWrapper().currentWindowResolution().x);
dict.setValue("windowHeight", OsEng.windowWrapper().currentWindowResolution().y);
dict.setValue("windowWidth", _resolution.x);
dict.setValue("windowHeight", _resolution.y);
dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath));
dict.setValue("maxLayers", MaxLayers);
dict.setValue("fragmentRendererPath", std::string("${SHADERS}/abuffer/renderabuffer.frag"));
dict.setValue("maxTotalFragments", MaxLayers * _resolution.x * _resolution.y);
_rendererData = dict;
OsEng.renderEngine().setRendererData(dict);
_dirtyRendererData = false;
}
}

View File

@@ -30,74 +30,378 @@
#include <openspace/scene/scene.h>
#include <openspace/util/camera.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/volumeraycaster.h>
#include <openspace/rendering/raycastermanager.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/opengl/textureunit.h>
#include <vector>
#include <ghoul/opengl/programobject.h>
namespace {
const std::string _loggerCat = "FramebufferRenderer";
const std::string FragmentRendererPath = "${SHADERS}/renderframebuffer.frag";
const std::string ExitFragmentShaderPath = "${SHADERS}/framebuffer/exitframebuffer.frag";
const std::string RaycastFragmentShaderPath = "${SHADERS}/framebuffer/raycastframebuffer.frag";
const std::string RenderFragmentShaderPath = "${SHADERS}/framebuffer/renderframebuffer.frag";
}
namespace openspace {
FramebufferRenderer::FramebufferRenderer()
: _camera(nullptr)
, _scene(nullptr)
, _resolution(glm::vec2(0)) {
}
FramebufferRenderer::FramebufferRenderer()
: _camera(nullptr)
, _scene(nullptr)
, _resolution(glm::vec2(0)) {
}
FramebufferRenderer::~FramebufferRenderer() {}
void FramebufferRenderer::initialize() {
LINFO("Initializing FramebufferRenderer");
FramebufferRenderer::~FramebufferRenderer() {
}
const GLfloat size = 1.0f;
const GLfloat vertex_data[] = {
// x y s t
-size, -size, 0.0f, 1.0f,
size, size, 0.0f, 1.0f,
-size, size, 0.0f, 1.0f,
-size, -size, 0.0f, 1.0f,
size, -size, 0.0f, 1.0f,
size, size, 0.0f, 1.0f
};
glGenVertexArrays(1, &_screenQuad);
glBindVertexArray(_screenQuad);
void FramebufferRenderer::initialize() {
LINFO("Initializing FramebufferRenderer");
updateRendererData();
glGenBuffers(1, &_vertexPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast<void*>(0));
glEnableVertexAttribArray(0);
GLint defaultFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo);
// Main framebuffer
glGenTextures(1, &_mainColorTexture);
glGenTextures(1, &_mainDepthTexture);
glGenFramebuffers(1, &_mainFramebuffer);
// Exit framebuffer
glGenTextures(1, &_exitColorTexture);
glGenTextures(1, &_exitDepthTexture);
glGenFramebuffers(1, &_exitFramebuffer);
updateResolution();
updateRendererData();
updateRaycastData();
glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _exitColorTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _exitDepthTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
LERROR("Main framebuffer is not complete");
}
void FramebufferRenderer::deinitialize() {
LINFO("Deinitializing FramebufferRenderer");
}
void FramebufferRenderer::update() {
// no need to update anything.
}
void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) {
if (_scene == nullptr) return;
if (_camera == nullptr) return;
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
_scene->render({ *_camera, psc(), doPerformanceMeasurements });;
glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo);
try {
_resolveProgram = ghoul::opengl::ProgramObject::Build("Framebuffer Resolve",
"${SHADERS}/framebuffer/resolveframebuffer.vert",
"${SHADERS}/framebuffer/resolveframebuffer.frag");
} catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
void FramebufferRenderer::setScene(Scene* scene) {
_scene = scene;
OsEng.renderEngine().raycasterManager().addListener(*this);
_nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples();
if (_nAaSamples > 8) {
LERROR("Framebuffer renderer does not support more than 8 MSAA samples.");
_nAaSamples = 8;
}
}
void FramebufferRenderer::deinitialize() {
LINFO("Deinitializing FramebufferRenderer");
glDeleteFramebuffers(1, &_mainFramebuffer);
glDeleteFramebuffers(1, &_exitFramebuffer);
glDeleteTextures(1, &_mainColorTexture);
glDeleteTextures(1, &_mainDepthTexture);
glDeleteTextures(1, &_exitColorTexture);
glDeleteTextures(1, &_exitDepthTexture);
glDeleteBuffers(1, &_vertexPositionBuffer);
glDeleteVertexArrays(1, &_screenQuad);
OsEng.renderEngine().raycasterManager().removeListener(*this);
}
void FramebufferRenderer::raycastersChanged(VolumeRaycaster& raycaster, bool attached) {
(void) raycaster;
(void) attached;
_dirtyRaycastData = true;
}
void FramebufferRenderer::update() {
if (_dirtyResolution) {
updateResolution();
}
void FramebufferRenderer::setCamera(Camera* camera) {
_camera = camera;
if (_dirtyRaycastData) {
updateRaycastData();
}
void FramebufferRenderer::setResolution(glm::ivec2 res) {
_resolution = res;
// If the resolve dictionary changed (or a file changed on disk)
// then rebuild the resolve program.
if (_resolveProgram->isDirty()) {
try {
_resolveProgram->rebuildFromFile();
} catch (ghoul::RuntimeError& error) {
LERROR(error.message);
}
}
void FramebufferRenderer::updateRendererData() {
for (auto &program : _exitPrograms) {
if (program.second->isDirty()) {
try {
program.second->rebuildFromFile();
} catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
}
}
for (auto &program : _raycastPrograms) {
if (program.second->isDirty()) {
try {
program.second->rebuildFromFile();
} catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
}
}
}
void FramebufferRenderer::updateResolution() {
int nSamples = OsEng.windowWrapper().currentNumberOfAaSamples();
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture);
glTexImage2DMultisample(
GL_TEXTURE_2D_MULTISAMPLE,
nSamples,
GL_RGBA,
GLsizei(_resolution.x),
GLsizei(_resolution.y),
true);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture);
glTexImage2DMultisample(
GL_TEXTURE_2D_MULTISAMPLE,
nSamples,
GL_DEPTH_COMPONENT32F,
GLsizei(_resolution.x),
GLsizei(_resolution.y),
true);
glBindTexture(GL_TEXTURE_2D, _exitColorTexture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
GLsizei(_resolution.x),
GLsizei(_resolution.y),
0,
GL_RGBA,
GL_BYTE,
nullptr);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, _exitDepthTexture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_DEPTH_COMPONENT32F,
GLsizei(_resolution.x),
GLsizei(_resolution.y),
0,
GL_DEPTH_COMPONENT,
GL_FLOAT,
nullptr);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void FramebufferRenderer::updateRaycastData() {
_raycastData.clear();
_exitPrograms.clear();
_raycastPrograms.clear();
const std::vector<VolumeRaycaster*>& raycasters = OsEng.renderEngine().raycasterManager().raycasters();
int nextId = 0;
for (auto &raycaster : raycasters) {
RaycastData data;
data.id = nextId++;
data.namespaceName = "HELPER";
std::string vsPath = raycaster->getBoundsVsPath();
std::string fsPath = raycaster->getBoundsFsPath();
ghoul::Dictionary dict;
dict.setValue("fragmentRendererPath", FragmentRendererPath);
dict.setValue("windowWidth", OsEng.windowWrapper().currentWindowResolution().x);
dict.setValue("windowHeight", OsEng.windowWrapper().currentWindowResolution().y);
dict.setValue("rendererData", _rendererData);
dict.setValue("fragmentPath", fsPath);
dict.setValue("id", data.id);
std::string helperPath = raycaster->getHelperPath();
ghoul::Dictionary helpersDict;
if (helperPath != "") {
helpersDict.setValue("0", helperPath);
}
dict.setValue("helperPaths", helpersDict);
dict.setValue("raycastPath", raycaster->getRaycastPath());
_raycastData[raycaster] = data;
OsEng.renderEngine().setRendererData(dict);
try {
_exitPrograms[raycaster] = ghoul::opengl::ProgramObject::Build("Volume " + std::to_string(data.id) + " exit", vsPath, ExitFragmentShaderPath, dict);
}
catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
try {
_raycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build("Volume " + std::to_string(data.id) + " raycast", vsPath, RaycastFragmentShaderPath, dict);
} catch (ghoul::RuntimeError e) {
LERROR(e.message);
}
}
_dirtyRaycastData = false;
}
void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (_scene == nullptr) return;
if (_camera == nullptr) return;
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
RenderData data = { *_camera, psc(), doPerformanceMeasurements };
RendererTasks tasks;
// Capture standard fbo
GLint defaultFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo);
glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// bind new fbo A with color and depth buffer.
_scene->render(data, tasks);
for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) {
VolumeRaycaster* raycaster = raycasterTask.raycaster;
glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ghoul::opengl::ProgramObject* exitProgram = _exitPrograms[raycaster].get();
if (exitProgram) {
exitProgram->activate();
raycaster->renderExitPoints(raycasterTask.renderData, *exitProgram);
exitProgram->deactivate();
}
glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer);
ghoul::opengl::ProgramObject* raycastProgram = _raycastPrograms[raycaster].get();
if (raycastProgram) {
raycastProgram->activate();
raycaster->preRaycast(_raycastData[raycaster], *raycastProgram);
ghoul::opengl::TextureUnit exitColorTextureUnit;
exitColorTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D, _exitColorTexture);
raycastProgram->setUniform("exitColorTexture", exitColorTextureUnit);
ghoul::opengl::TextureUnit exitDepthTextureUnit;
exitDepthTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D, _exitDepthTexture);
raycastProgram->setUniform("exitDepthTexture", exitDepthTextureUnit);
ghoul::opengl::TextureUnit mainDepthTextureUnit;
mainDepthTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture);
raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit);
raycastProgram->setUniform("nAaSamples", _nAaSamples);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
raycaster->renderEntryPoints(raycasterTask.renderData, *raycastProgram);
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
raycaster->postRaycast(_raycastData[raycaster], *raycastProgram);
raycastProgram->deactivate();
} else {
LWARNING("Raycaster is not attached when trying to perform raycaster task");
}
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo);
_resolveProgram->activate();
ghoul::opengl::TextureUnit mainColorTextureUnit;
mainColorTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture);
_resolveProgram->setUniform("mainColorTexture", mainColorTextureUnit);
_resolveProgram->setUniform("blackoutFactor", blackoutFactor);
_resolveProgram->setUniform("nAaSamples", _nAaSamples);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
_resolveProgram->deactivate();
}
void FramebufferRenderer::setScene(Scene* scene) {
_scene = scene;
}
void FramebufferRenderer::setCamera(Camera* camera) {
_camera = camera;
}
void FramebufferRenderer::setResolution(glm::ivec2 res) {
_resolution = res;
}
void FramebufferRenderer::updateRendererData() {
ghoul::Dictionary dict;
dict.setValue("fragmentRendererPath", RenderFragmentShaderPath);
dict.setValue("windowWidth", _resolution.x);
dict.setValue("windowHeight", _resolution.y);
_rendererData = dict;
OsEng.renderEngine().setRendererData(dict);
}
}

View File

@@ -0,0 +1,83 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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/raycastermanager.h>
#include <openspace/rendering/raycasterlistener.h>
#include <algorithm>
namespace {
const std::string _loggerCat = "RaycasterManager";
}
namespace openspace {
RaycasterManager::RaycasterManager() {}
RaycasterManager::~RaycasterManager() {}
void RaycasterManager::attachRaycaster(VolumeRaycaster& raycaster) {
if (!isAttached(raycaster)) {
_raycasters.push_back(&raycaster);
}
for (auto &listener : _listeners) {
listener->raycastersChanged(raycaster, true);
}
}
bool RaycasterManager::isAttached(VolumeRaycaster& raycaster) {
auto it = std::find(_raycasters.begin(), _raycasters.end(), &raycaster);
return it != _raycasters.end();
}
void RaycasterManager::detachRaycaster(VolumeRaycaster& raycaster) {
auto it = std::find(_raycasters.begin(), _raycasters.end(), &raycaster);
if (it != _raycasters.end()) {
_raycasters.erase(it);
for (auto &listener : _listeners) {
listener->raycastersChanged(raycaster, false);
}
}
}
void RaycasterManager::addListener(RaycasterListener& listener) {
auto it = std::find(_listeners.begin(), _listeners.end(), &listener);
if (it == _listeners.end()) {
_listeners.push_back(&listener);
}
}
void RaycasterManager::removeListener(RaycasterListener& listener) {
auto it = std::find(_listeners.begin(), _listeners.end(), &listener);
if (it != _listeners.end()) {
_listeners.erase(it);
}
}
const std::vector<VolumeRaycaster*>& RaycasterManager::raycasters() {
return _raycasters;
}
}

View File

@@ -111,15 +111,25 @@ void Renderable::update(const UpdateData&)
{
}
void Renderable::render(const RenderData& data, RendererTasks& tasks)
{
(void) tasks;
render(data);
}
void Renderable::render(const RenderData& data)
{
}
void Renderable::setPscUniforms(
ghoul::opengl::ProgramObject* program,
const Camera* camera,
ghoul::opengl::ProgramObject& program,
const Camera& camera,
const PowerScaledCoordinate& position)
{
program->setUniform("campos", camera->position().vec4());
program->setUniform("objpos", position.vec4());
program->setUniform("camrot", camera->viewRotationMatrix());
program->setUniform("scaling", camera->scaling());
program.setUniform("campos", camera.position().vec4());
program.setUniform("objpos", position.vec4());
program.setUniform("camrot", camera.viewRotationMatrix());
program.setUniform("scaling", camera.scaling());
}
bool Renderable::isVisible() const {
@@ -166,8 +176,10 @@ bool Renderable::isEnabled() const {
return _enabled;
}
std::vector<Volume*> Renderable::volumesToRender(const RenderData& data) const {
return std::vector<Volume*>();
void Renderable::onEnabledChange(std::function<void(bool)> callback) {
_enabled.onChange([=] () {
callback(isEnabled());
});
}
} // namespace openspace

View File

@@ -31,6 +31,7 @@
#include <openspace/rendering/renderer.h>
#include <openspace/rendering/abufferrenderer.h>
#include <openspace/rendering/framebufferrenderer.h>
#include <openspace/rendering/raycastermanager.h>
#include <modules/base/rendering/screenspaceimage.h>
#include <modules/base/rendering/screenspaceframebuffer.h>
@@ -57,6 +58,7 @@
#include <openspace/engine/wrapper/windowwrapper.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/io/texture/texturewriter.h>
#ifdef GHOUL_USE_DEVIL
@@ -135,6 +137,7 @@ RenderEngine::~RenderEngine() {
delete _mainCamera;
delete _performanceMemory;
delete _raycasterManager;
if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData))
ghoul::SharedMemory::remove(PerformanceMeasurementSharedData);
@@ -182,6 +185,8 @@ bool RenderEngine::initialize() {
}
}
_raycasterManager = new RaycasterManager();
LINFO("Seting renderer from string: " << renderingMethod);
setRendererFromString(renderingMethod);
@@ -441,6 +446,10 @@ Scene* RenderEngine::scene() {
return _sceneGraph;
}
RaycasterManager& RenderEngine::raycasterManager() {
return *_raycasterManager;
}
void RenderEngine::setSceneGraph(Scene* sceneGraph) {
_sceneGraph = sceneGraph;
}

View File

@@ -35,7 +35,7 @@ ScreenSpaceRenderable::ScreenSpaceRenderable()
, _alpha("alpha", "Alpha" , 1, 0, 1)
, _quad(0)
, _vertexPositionBuffer(0)
,_rendererPath("${SHADERS}/renderframebuffer.frag")
,_rendererPath("${SHADERS}/framebuffer/renderframebuffer.frag")
,_vertexPath("${MODULE_BASE}/shaders/screnspace_vs.glsl")
,_fragmentPath("${MODULE_BASE}/shaders/screnspace_fs.glsl")
,_texture(nullptr)

View File

@@ -131,19 +131,10 @@ void Scene::evaluate(Camera* camera) {
//_root->evaluate(camera);
}
void Scene::render(const RenderData& data) {
for (SceneGraphNode* node : _graph.nodes())
node->render(data);
}
std::vector<std::pair<Volume*, RenderData>> Scene::volumesToRender(const RenderData& data) const {
std::vector<std::pair<Volume*, RenderData>> volumes;
for (const SceneGraphNode* node : _graph.nodes()) {
std::vector<std::pair<Volume*, RenderData>> newVolumes = node->volumesToRender(data);
std::copy(newVolumes.begin(), newVolumes.end(), std::back_inserter(volumes));
void Scene::render(const RenderData& data, RendererTasks& tasks) {
for (SceneGraphNode* node : _graph.nodes()) {
node->render(data, tasks);
}
return volumes;
}
void Scene::scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath) {

View File

@@ -242,7 +242,7 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) {
// child->evaluate(camera, psc());
}
void SceneGraphNode::render(const RenderData& data) {
void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
const psc thisPosition = worldPosition();
RenderData newData = {data.camera, thisPosition, data.doPerformanceMeasurement};
@@ -253,14 +253,14 @@ void SceneGraphNode::render(const RenderData& data) {
glFinish();
auto start = std::chrono::high_resolution_clock::now();
_renderable->render(newData);
_renderable->render(newData, tasks);
glFinish();
auto end = std::chrono::high_resolution_clock::now();
_performanceRecord.renderTime = (end - start).count();
}
else
_renderable->render(newData);
_renderable->render(newData, tasks);
}
// evaluate all the children, tail-recursive function(?)
@@ -269,18 +269,6 @@ void SceneGraphNode::render(const RenderData& data) {
// child->render(newData);
}
std::vector<std::pair<Volume*, RenderData>> SceneGraphNode::volumesToRender(const RenderData& data) const {
const psc thisPosition = worldPosition();
RenderData newData = {data.camera, thisPosition, data.doPerformanceMeasurement};
std::vector<std::pair<Volume*, RenderData>> toRender;
if (_renderableVisible && _renderable->isVisible() && _renderable->isReady() && _renderable->isEnabled()) {
std::vector<Volume*> volumes = _renderable->volumesToRender(newData);
for (Volume* v : volumes) {
toRender.push_back(std::make_pair(v, newData));
}
}
return toRender;
}
// not used anymore @AA
//void SceneGraphNode::addNode(SceneGraphNode* child)

View File

@@ -111,19 +111,19 @@ void BlockPlaneIntersectionGeometry::updateVertices() {
std::vector< std::pair<int, float> > angles(nIntersections-1);
glm::vec3 vector1 = glm::normalize(intersections[1] - intersections[0]);
angles[0] = std::pair<int, float>(1, 0.0);
angles[0] = std::pair<int, float>(1, 0.0f);
for (int i = 2; i < nIntersections; i++) {
glm::vec3 vectorI = glm::normalize(intersections[i] - intersections[0]);
float sinA = glm::dot(glm::cross(vector1, vectorI), _normal);
float cosA = glm::dot(vector1, vectorI);
angles[i-1] = std::pair<int, float>(i, glm::sign(sinA) * (1.0 - cosA));
angles[i - 1] = std::pair<int, float>(i, static_cast<float>(glm::sign(sinA) * (1.0 - cosA)));
}
// Sort the vectors by angle in the plane
std::sort(angles.begin(), angles.end(),
[](const std::pair<int, float>& a, const std::pair<int, float>& b) -> bool {
return a.second > b.second;
return a.second < b.second;
}
);
@@ -138,6 +138,17 @@ void BlockPlaneIntersectionGeometry::updateVertices() {
_vertices.push_back(intersections[j].z);
//_vertices.push_back(_w);
}
// First VAO setup
glBindVertexArray(_vaoId);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferId);
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(GLfloat), _vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
glBindVertexArray(0);
}
bool BlockPlaneIntersectionGeometry::initialize() {
@@ -154,23 +165,14 @@ bool BlockPlaneIntersectionGeometry::initialize() {
}
updateVertices();
// First VAO setup
glBindVertexArray(_vaoId);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferId);
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(GLfloat), _vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
glBindVertexArray(0);
return true;
}
void BlockPlaneIntersectionGeometry::render() {
glBindVertexArray(_vaoId); // select first VAO
glDrawArrays(GL_TRIANGLES, 0, 6*6);
glBindVertexArray(0);
glBindVertexArray(_vaoId);
//glDisable(GL_CULL_FACE);
glDrawArrays(GL_TRIANGLE_FAN, 0, _vertices.size() / 3);
//glEnable(GL_CULL_FACE);
}
}

View File

@@ -45,53 +45,53 @@ BoxGeometry::~BoxGeometry() {
bool BoxGeometry::initialize() {
// Initialize and upload to graphics card
// Initialize and upload to GPU
float x = _size.x * 0.5;
float y = _size.y * 0.5;
float z = _size.z * 0.5;
const GLfloat vertices[] = {
-x, y, z,
x, y, z,
-x, y, z,
-x, -y, z,
x, -y, z,
x, y, z,
-x, -y, z, // blue corner
x, y, z, // white corner
-x, y, z, // cyan corner
-x, -y, z, // blue corner
x, -y, z, // magenta corner
x, y, z, // white corner
-x, -y, -z,
x, y, -z,
-x, y, -z,
-x, -y, -z,
x, -y, -z,
x, y, -z,
-x, -y, -z, // black corner
-x, y, -z, // green
x, y, -z, // yellow corner
-x, -y, -z, // black
x, y, -z, // yellow
x, -y, -z, // red
x, -y, -z,
x, y, z,
x, -y, z,
x, -y, -z,
x, y, -z,
x, y, z,
x, -y, -z, // red
x, y, z, // yellow
x, -y, z, // magenta
x, -y, -z, // red
x, y, -z, // yellow
x, y, z, // white
-x, -y, -z,
-x, y, z,
-x, -y, z,
-x, -y, -z,
-x, y, -z,
-x, y, z,
-x, y, -z,
x, y, z,
-x, y, z,
-x, y, -z,
x, y, -z,
x, y, z,
-x, -y, -z,
x, -y, z,
-x, -y, z,
-x, -y, -z,
x, -y, -z,
x, -y, z
-x, -y, -z, // black
-x, -y, z, // blue
-x, y, z, // cyan
-x, -y, -z, // black
-x, y, z, // cyan
-x, y, -z, // green
x, y, z, // white
-x, y, -z, // green
-x, y, z, // cyan
-x, y, -z, // green
x, y, z, // white
x, y, -z, // yellow
-x, -y, -z, // black
x, -y, z, // magenta
-x, -y, z, // blue
-x, -y, -z, // black
x, -y, -z, // red
x, -y, z // magenta
};
if (_vaoId == 0)
@@ -113,7 +113,7 @@ bool BoxGeometry::initialize() {
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, 0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
glBindVertexArray(0);
return true;

View File

@@ -32,7 +32,7 @@
#include <glm/gtc/type_ptr.hpp>
#include <algorithm>
#include <format.h>
#include <cppformat/format.h>
namespace {
const std::string _loggerCat = "SpiceManager";

View File

@@ -23,7 +23,7 @@
#########################################################################################
include (${OPENSPACE_CMAKE_EXT_DIR}/module_common.cmake)
include (${GHOUL_BASE_DIR}/ext/handle_external_library.cmake)
include (${GHOUL_BASE_DIR}/support/cmake/handle_external_library.cmake)
# Creates a new project and a library for the module with name <module_name>. The name of
# the library is returned in <output_library_name> for outside configuration

View File

@@ -126,7 +126,6 @@ function (add_external_dependencies)
target_compile_definitions(libOpenSpace PUBLIC ${GHOUL_DEFINITIONS})
set_property(TARGET Lua PROPERTY FOLDER "External")
set_property(TARGET lz4 PROPERTY FOLDER "External")
set_property(TARGET tinyobjloader PROPERTY FOLDER "External")
# SGCT
find_package(SGCT REQUIRED)