Merge master into issue/1669 to fix build conflict

This commit is contained in:
GPayne
2021-07-30 13:13:14 -06:00
79 changed files with 1562 additions and 3314 deletions

View File

@@ -132,8 +132,6 @@ if (MSVC)
set(GHOUL_OPTIMIZATION_ENABLE_OTHER_OPTIMIZATIONS ${OPENSPACE_OPTIMIZATION_ENABLE_OTHER_OPTIMIZATIONS} CACHE BOOL "" FORCE)
endif ()
option(OPENSPACE_WITH_ABUFFER_RENDERER "Compile ABuffer Renderer" OFF)
if (UNIX)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -stdlib=libc++")

View File

@@ -115,6 +115,7 @@ PropertiesDialog QListWidget {
*/
AssetsDialog QTreeView {
min-width: 40em;
min-height: 40em;
}
/*

View File

@@ -312,8 +312,24 @@ void LauncherWindow::setBackgroundImage(const std::string& syncPath) {
std::mt19937 g(rd());
std::shuffle(files.begin(), files.end(), g);
// We know there has to be at least one folder, so it's fine to just pick the first
std::string image = files.front();
_backgroundImage->setPixmap(QPixmap(QString::fromStdString(image)));
while (!files.empty()) {
std::string p = files.front();
if (std::filesystem::path(p).extension() == ".png") {
// If the top path starts with the png extension, we have found our candidate
break;
}
else {
// There shouldn't be any non-png images in here, but you never know. So we
// just remove non-image files here
files.erase(files.begin());
}
}
// There better be at least one file left, but just in in case
if (!files.empty()) {
std::string image = files.front();
_backgroundImage->setPixmap(QPixmap(QString::fromStdString(image)));
}
}
void LauncherWindow::populateProfilesList(std::string preset) {

View File

@@ -129,10 +129,7 @@ AssetsDialog::AssetsDialog(openspace::Profile& profile, const std::string& asset
{
setWindowTitle("Assets");
_assetTreeModel.importModelData(assetBasePath, userAssetBasePath);
createWidgets();
}
void AssetsDialog::createWidgets() {
QBoxLayout* layout = new QVBoxLayout(this);
{
QLabel* heading = new QLabel("Select assets from /data/assets");
@@ -173,18 +170,19 @@ void AssetsDialog::createWidgets() {
nRows,
_assetTreeModel.index(-1, 0)
);
layout->addWidget(_assetTree);
layout->addWidget(_assetTree, 4);
}
{
QWidget* box = new QWidget;
QBoxLayout* boxLayout = new QVBoxLayout(box);
QLabel* summaryHeading = new QLabel("Selection summary");
summaryHeading->setObjectName("heading");
layout->addWidget(summaryHeading);
}
{
boxLayout->addWidget(summaryHeading);
_summary = new QTextEdit;
_summary->setReadOnly(true);
_summary->setText(createTextSummary());
layout->addWidget(_summary);
boxLayout->addWidget(_summary);
layout->addWidget(box, 1);
}
layout->addWidget(new Line);

View File

@@ -20,7 +20,7 @@ local Gaia = {
XAxis = { 1.0, 0.0, 0.0 },
XAxisOrthogonal = true,
YAxis = "Sun",
YAxisInverted = true
YAxisInvert = true
},
Scale = {
Type = "StaticScale",

View File

@@ -11,7 +11,7 @@ local trail = asset.syncedResource({
local GaiaTrail = {
Identifier = "GaiaTrail",
Parent = earthTransforms.EarthBarycenter.Identifier,
Parent = earthTransforms.EarthCenter.Identifier,
Renderable = {
Type = "RenderableTrailTrajectory",
Translation = {
@@ -36,7 +36,7 @@ local GaiaTrail = {
local GaiaTrailEclip = {
Identifier = "GaiaTrail_Eclip",
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
Parent = sunTransforms.SunCenter.Identifier,
Renderable = {
Type = "RenderableTrailTrajectory",
Enabled = false,

View File

@@ -11,7 +11,7 @@ local trail = asset.syncedResource({
local GaiaPosition = {
Identifier = "GaiaPosition",
Parent = earthTransforms.EarthBarycenter.Identifier,
Parent = earthTransforms.EarthCenter.Identifier,
Transform = {
Translation = {
Type = "HorizonsTranslation",

View File

@@ -42,7 +42,6 @@ local Atmosphere = {
G = 0.85
},
Debug = {
-- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....)
PreCalculatedTextureScale = 1.0,
SaveCalculatedTextures = false
}

View File

@@ -42,7 +42,6 @@ local Atmosphere = {
G = 0.85
},
Debug = {
-- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....)
PreCalculatedTextureScale = 1.0,
SaveCalculatedTextures = false
}

View File

@@ -20,6 +20,24 @@ local SolarSystemBarycenter = {
}
}
local SunCenter = {
Identifier = "SunCenter",
Parent = SolarSystemBarycenter.Identifier,
Transform = {
Translation = {
Type = "SpiceTranslation",
Target = "SUN",
Observer = "SSB"
}
},
GUI = {
Name = "SUN Center",
Path = "/Solar System/Sun",
Description = [[Spice frame for the Sun]],
Hidden = true
}
}
-- Spice frame for the Sun
local SunIAU = {
Identifier = "SunIAU",
@@ -67,7 +85,7 @@ local SunECLIPJ2000 = {
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { SolarSystemBarycenter, SunIAU, SunECLIPJ2000 })
assetHelper.registerSceneGraphNodesAndExport(asset, { SolarSystemBarycenter, SunCenter, SunIAU, SunECLIPJ2000 })
asset.meta = {

View File

@@ -67,7 +67,7 @@ local addCartesianAxes = function (specification)
Parent = parent,
Transform = {
Scale = {
Type = "StaticScale",
Type = "NonUniformStaticScale",
Scale = scale
},
Translation = {

View File

@@ -98,18 +98,17 @@ struct Configuration {
bool usePerProfileCache = false;
bool isRenderingOnMasterDisabled = false;
glm::dvec3 globalRotation = glm::dvec3(0.0);
glm::dvec3 screenSpaceRotation = glm::dvec3(0.0);
glm::dvec3 masterRotation = glm::dvec3(0.0);
glm::vec3 globalRotation = glm::vec3(0.0);
glm::vec3 screenSpaceRotation = glm::vec3(0.0);
glm::vec3 masterRotation = glm::vec3(0.0);
bool isConsoleDisabled = false;
bool bypassLauncher = false;
std::map<std::string, ghoul::Dictionary> moduleConfigurations;
std::string renderingMethod = "Framebuffer";
struct OpenGLDebugContext {
bool isActive = false;
bool printStacktrace = false;
bool isSynchronous = true;
struct IdentifierFilter {
std::string type;

View File

@@ -1,183 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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 __OPENSPACE_CORE___ABUFFERRENDERER___H__
#define __OPENSPACE_CORE___ABUFFERRENDERER___H__
#ifdef OPENSPACE_WITH_ABUFFER_RENDERER
#include <openspace/rendering/renderer.h>
#include <openspace/rendering/raycasterlistener.h>
#include <ghoul/glm.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl {
class ProgramObject;
class Texture;
} // namespace ghoul::opengl
namespace openspace {
struct RaycasterTask;
class RenderableVolume;
class Camera;
class Scene;
struct RaycastData;
class ABufferRenderer : public Renderer, public RaycasterListener {
public:
virtual ~ABufferRenderer() = default;
void initialize() override;
void deinitialize() override;
void setResolution(glm::ivec2 res) override;
void setNAaSamples(int nAaSamples) override;
void setBlurrinessLevel(int level) override;
void setHDRExposure(float hdrExposure) override;
void setGamma(float gamma) override;
void setMaxWhite(float maxWhite) override;
void setToneMapOperator(int tmOp) override;
void setBloomThreMin(float minV) override;
void setBloomThreMax(float maxV) override;
void setBloomOrigFactor(float origFactor) override;
void setBloomNewFactor(float newFactor) override;
void setKey(float key) override;
void setYwhite(float white) override;
void setTmoSaturation(float sat) override;
void setHue(float hue) override;
void setValue(float value) override;
void setSaturation(float sat) override;
void setLightness(float lightness) override;
void setColorSpace(unsigned int colorspace) override;
void enableBloom(bool enable) override;
void enableHistogram(bool enable) override;
int nAaSamples() const override;
const std::vector<double>& mSSAPattern() const override;
using Renderer::preRaycast;
void preRaycast(const RaycasterTask& raycasterTask);
using Renderer::postRaycast;
void postRaycast(const RaycasterTask& raycasterTask);
void update() override;
void render(Scene* scene, Camera* camera, float blackoutFactor) override;
/**
* Update render data
* Responsible for calling renderEngine::setRenderData
*/
virtual void updateRendererData() override;
virtual void raycastersChanged(VolumeRaycaster& raycaster,
IsAttached attached) override;
private:
void clear();
void updateResolution();
void updateRaycastData();
void updateResolveDictionary();
void updateMSAASamplingPattern();
void saveTextureToMemory(GLenum color_buffer_attachment, int width, int height,
std::vector<double> & memory) const;
glm::ivec2 _resolution = glm::ivec2(0);
bool _dirtyResolution = true;
bool _dirtyRendererData = true;
bool _dirtyRaycastData = true;
bool _dirtyResolveDictionary = true;
std::unique_ptr<ghoul::opengl::ProgramObject> _resolveProgram = nullptr;
/**
* When a volume is attached or detached from the scene graph,
* the resolve program needs to be recompiled.
* 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::map<VolumeRaycaster*, RaycastData> _raycastData;
std::map<
VolumeRaycaster*, std::unique_ptr<ghoul::opengl::ProgramObject>
> _boundsPrograms;
std::vector<std::string> _helperPaths;
ghoul::Dictionary _resolveDictionary;
GLuint _mainColorTexture;
GLuint _mainDepthTexture;
GLuint _mainFramebuffer;
GLuint _screenQuad;
GLuint _anchorPointerTexture;
GLuint _anchorPointerTextureInitializer;
GLuint _atomicCounterBuffer;
GLuint _fragmentBuffer;
GLuint _fragmentTexture;
GLuint _vertexPositionBuffer;
int _nAaSamples;
int _blurrinessLevel = 1;
float _hdrExposure = 0.4f;
float _hdrBackground = 2.8f;
float _gamma = 2.2f;
float _maxWhite = 1.f;
float _blackoutFactor;
bool _bloomEnabled = false;
float _bloomThresholdMin = 0.0;
float _bloomThresholdMax = 1.0;
float _bloomOrigFactor = 1.0;
float _bloomNewFactor = 1.0;
int _toneMapOperator = 0;
bool _histogramEnabled = false;
int _numberOfBins = 1024; // JCC TODO: Add a parameter control for this.
float _tmoKey = 0.18f;
float _tmoYwhite = 1e6f;
float _tmoSaturation = 1.0f;
float _hue = 1.f;
float _saturation = 1.f;
float _value = 1.f;
float _lightness = 1.f;
unsigned int _colorSpace = 1;
std::vector<double> _mSAAPattern;
ghoul::Dictionary _rendererData;
};
} // namespace openspace
#endif // OPENSPACE_WITH_ABUFFER_RENDERER
#endif // __OPENSPACE_CORE___ABUFFERRENDERER___H__

View File

@@ -51,8 +51,6 @@ public:
const DeferredcastData& /*deferredData*/,
ghoul::opengl::ProgramObject& /*program*/) {};
virtual std::filesystem::path deferredcastPath() const = 0;
virtual std::filesystem::path deferredcastVSPath() const = 0;
virtual std::filesystem::path deferredcastFSPath() const = 0;

View File

@@ -25,8 +25,6 @@
#ifndef __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__
#define __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__
#include <openspace/rendering/renderer.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/raycasterlistener.h>
#include <openspace/rendering/deferredcasterlistener.h>
@@ -56,14 +54,14 @@ struct RaycasterTask;
class Scene;
struct UpdateStructures;
class FramebufferRenderer : public Renderer, public RaycasterListener,
class FramebufferRenderer : public RaycasterListener,
public DeferredcasterListener
{
public:
virtual ~FramebufferRenderer() = default;
void initialize() override;
void deinitialize() override;
void initialize();
void deinitialize();
void updateResolution();
void updateRaycastData();
@@ -72,33 +70,33 @@ public:
void updateFXAA();
void updateDownscaledVolume();
void setResolution(glm::ivec2 res) override;
void setHDRExposure(float hdrExposure) override;
void setGamma(float gamma) override;
void setHue(float hue) override;
void setValue(float value) override;
void setSaturation(float sat) override;
void setResolution(glm::ivec2 res);
void setHDRExposure(float hdrExposure);
void setGamma(float gamma);
void setHue(float hue);
void setValue(float value);
void setSaturation(float sat);
void enableFXAA(bool enable) override;
void setDisableHDR(bool disable) override;
void enableFXAA(bool enable);
void setDisableHDR(bool disable);
void update() override;
void update();
void performRaycasterTasks(const std::vector<RaycasterTask>& tasks,
const glm::ivec4& viewport);
void performDeferredTasks(const std::vector<DeferredcasterTask>& tasks,
const glm::ivec4& viewport);
void render(Scene* scene, Camera* camera, float blackoutFactor) override;
void render(Scene* scene, Camera* camera, float blackoutFactor);
/**
* Update render data
* Responsible for calling renderEngine::setRenderData
*/
virtual void updateRendererData() override;
virtual void updateRendererData();
virtual void raycastersChanged(VolumeRaycaster& raycaster,
RaycasterListener::IsAttached attached) override;
RaycasterListener::IsAttached attached);
virtual void deferredcastersChanged(Deferredcaster& deferredcaster,
DeferredcasterListener::IsAttached isAttached) override;
DeferredcasterListener::IsAttached isAttached);
private:
using RaycasterProgObjMap = std::map<

View File

@@ -33,6 +33,7 @@
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/rendering/framebufferrenderer.h>
#include <chrono>
#include <filesystem>
@@ -54,7 +55,6 @@ namespace scripting { struct LuaLibrary; }
class Camera;
class RaycasterManager;
class DeferredcasterManager;
class Renderer;
class Scene;
class SceneManager;
class ScreenLog;
@@ -63,12 +63,6 @@ struct ShutdownInformation;
class RenderEngine : public properties::PropertyOwner {
public:
enum class RendererImplementation {
Framebuffer = 0,
ABuffer,
Invalid
};
RenderEngine();
~RenderEngine();
@@ -80,9 +74,6 @@ public:
Scene* scene();
void updateScene();
const Renderer& renderer() const;
RendererImplementation rendererImplementation() const;
ghoul::opengl::OpenGLStateCache& openglStateCache();
void updateShaderPrograms();
@@ -120,24 +111,11 @@ public:
void removeRenderProgram(ghoul::opengl::ProgramObject* program);
/**
* Set raycasting uniforms on the program object, and setup raycasting.
*/
void preRaycast(ghoul::opengl::ProgramObject& programObject);
/**
* Tear down raycasting for the specified program object.
*/
void postRaycast(ghoul::opengl::ProgramObject& programObject);
/**
* Set the camera to use for rendering
*/
void setCamera(Camera* camera);
void setRendererFromString(const std::string& renderingMethod);
/**
* Lets the renderer update the data to be brought into the rendererer programs
* as a 'rendererData' variable in the dictionary.
@@ -176,9 +154,6 @@ public:
uint64_t frameNumber() const;
private:
void setRenderer(std::unique_ptr<Renderer> renderer);
RendererImplementation rendererFromString(const std::string& renderingMethod) const;
void renderScreenLog();
void renderVersionInformation();
void renderCameraInformation();
@@ -188,8 +163,7 @@ private:
Camera* _camera = nullptr;
Scene* _scene = nullptr;
std::unique_ptr<Renderer> _renderer;
RendererImplementation _rendererImplementation = RendererImplementation::Invalid;
FramebufferRenderer _renderer;
ghoul::Dictionary _rendererData;
ghoul::Dictionary _resolveData;
ScreenLog* _log = nullptr;

View File

@@ -1,83 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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 __OPENSPACE_CORE___RENDERER___H__
#define __OPENSPACE_CORE___RENDERER___H__
#include <ghoul/glm.h>
#include <vector>
namespace ghoul { class Dictionary; }
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl {
class ProgramObject;
class Texture;
} // namespace ghoul::opengl
namespace openspace {
class RenderableVolume;
class Camera;
class Scene;
class Renderer {
public:
virtual ~Renderer() = default;
virtual void initialize() = 0;
virtual void deinitialize() = 0;
virtual void setResolution(glm::ivec2 res) = 0;
virtual void setHDRExposure(float hdrExposure) = 0;
virtual void setGamma(float gamma) = 0;
virtual void setHue(float hue) = 0;
virtual void setValue(float value) = 0;
virtual void setSaturation(float sat) = 0;
virtual void enableFXAA(bool enable) = 0;
virtual void setDisableHDR(bool disable) = 0;
/**
* Set raycasting uniforms on the program object, and setup raycasting.
*/
virtual void preRaycast(ghoul::opengl::ProgramObject& /*programObject*/) {};
/**
* Tear down raycasting for the specified program object.
*/
virtual void postRaycast(ghoul::opengl::ProgramObject& /*programObject*/) {};
virtual void update() = 0;
virtual void render(Scene* scene, Camera* camera, float blackoutFactor) = 0;
/**
* Update render data
* Responsible for calling renderEngine::setRenderData
*/
virtual void updateRendererData() = 0;
};
} // openspace
#endif // __OPENSPACE_CORE___RENDERER___H__

View File

@@ -36,7 +36,7 @@ template<typename P>
void ConcurrentJobManager<P>::enqueueJob(std::shared_ptr<Job<P>> job) {
threadPool.enqueue([this, job]() {
job->execute();
std::lock_guard<std::mutex> lock(_finishedJobsMutex);
std::lock_guard lock(_finishedJobsMutex);
_finishedJobs.push(job);
});
}
@@ -50,7 +50,7 @@ template<typename P>
std::shared_ptr<Job<P>> ConcurrentJobManager<P>::popFinishedJob() {
ghoul_assert(!_finishedJobs.empty(), "There is no finished job to pop!");
std::lock_guard<std::mutex> lock(_finishedJobsMutex);
std::lock_guard lock(_finishedJobsMutex);
return _finishedJobs.pop();
}

File diff suppressed because it is too large Load Diff

View File

@@ -57,16 +57,17 @@ struct ShadowRenderingStruct {
class AtmosphereDeferredcaster : public Deferredcaster {
public:
AtmosphereDeferredcaster(float textureScale,
std::vector<ShadowConfiguration> shadowConfigArray, bool saveCalculatedTextures);
virtual ~AtmosphereDeferredcaster() = default;
void initialize();
void deinitialize();
void preRaycast(const RenderData& renderData, const DeferredcastData& deferredData,
void preRaycast(const RenderData& data, const DeferredcastData& deferredData,
ghoul::opengl::ProgramObject& program) override;
void postRaycast(const RenderData& renderData, const DeferredcastData& deferredData,
void postRaycast(const RenderData& data, const DeferredcastData& deferredData,
ghoul::opengl::ProgramObject& program) override;
std::filesystem::path deferredcastPath() const override;
std::filesystem::path deferredcastVSPath() const override;
std::filesystem::path deferredcastFSPath() const override;
std::filesystem::path helperPath() const override;
@@ -75,82 +76,64 @@ public:
void update(const UpdateData&) override;
void preCalculateAtmosphereParam();
void calculateAtmosphereParameters();
void setModelTransform(glm::dmat4 transform);
void setTime(double time);
void setAtmosphereRadius(float atmRadius);
void setPlanetRadius(float planetRadius);
void setPlanetAverageGroundReflectance(float averageGReflectance);
void setPlanetGroundRadianceEmission(float groundRadianceEmission);
void setRayleighHeightScale(float rayleighHeightScale);
void enableOzone(bool enable);
void setOzoneHeightScale(float ozoneHeightScale);
void setMieHeightScale(float mieHeightScale);
void setMiePhaseConstant(float miePhaseConstant);
void setSunRadianceIntensity(float sunRadiance);
void setRayleighScatteringCoefficients(glm::vec3 rayScattCoeff);
void setOzoneExtinctionCoefficients(glm::vec3 ozoneExtCoeff);
void setMieScatteringCoefficients(glm::vec3 mieScattCoeff);
void setMieExtinctionCoefficients(glm::vec3 mieExtCoeff);
void setEllipsoidRadii(glm::dvec3 radii);
void setShadowConfigArray(std::vector<ShadowConfiguration> shadowConfigArray);
void setHardShadows(bool enabled);
void enableSunFollowing(bool enable);
void setPrecalculationTextureScale(float preCalculatedTexturesScale);
void enablePrecalculationTexturesSaving();
void setParameters(float atmosphereRadius, float planetRadius,
float averageGroundReflectance, float groundRadianceEmission,
float rayleighHeightScale, bool enableOzone, float ozoneHeightScale,
float mieHeightScale, float miePhaseConstant, float sunRadiance,
glm::vec3 rayScatteringCoefficients, glm::vec3 ozoneExtinctionCoefficients,
glm::vec3 mieScatteringCoefficients, glm::vec3 mieExtinctionCoefficients,
bool sunFollowing);
void setHardShadows(bool enabled);
private:
void loadComputationPrograms();
void unloadComputationPrograms();
void createComputationTextures();
void deleteComputationTextures();
void deleteUnusedComputationTextures();
void executeCalculations(GLuint quadCalcVAO, GLenum drawBuffers[1],
GLsizei vertexSize);
void step3DTexture(ghoul::opengl::ProgramObject& shaderProg, int layer,
bool doCalculation);
void loadAtmosphereDataIntoShaderProgram(ghoul::opengl::ProgramObject& shaderProg);
void step3DTexture(ghoul::opengl::ProgramObject& prg, int layer);
void calculateTransmittance();
GLuint calculateDeltaE();
std::pair<GLuint, GLuint> calculateDeltaS();
void calculateIrradiance();
void calculateInscattering(GLuint deltaSRayleigh, GLuint deltaSMie);
void calculateDeltaJ(int scatteringOrder,
ghoul::opengl::ProgramObject& program, GLuint deltaJ, GLuint deltaE,
GLuint deltaSRayleigh, GLuint deltaSMie);
void calculateDeltaE(int scatteringOrder,
ghoul::opengl::ProgramObject& program, GLuint deltaE, GLuint deltaSRayleigh,
GLuint deltaSMie);
void calculateDeltaS(int scatteringOrder,
ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh, GLuint deltaJ);
void calculateIrradiance(int scatteringOrder,
ghoul::opengl::ProgramObject& program, GLuint deltaE);
void calculateInscattering(int scatteringOrder,
ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh);
std::unique_ptr<ghoul::opengl::ProgramObject> _transmittanceProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _irradianceProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _irradianceSupTermsProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _irradianceFinalProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _inScatteringProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _inScatteringSupTermsProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _deltaEProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _deltaSProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _deltaSSupTermsProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _deltaJProgramObject;
UniformCache(cullAtmosphere, Rg, Rt, groundRadianceEmission, HR, betaRayleigh, HM,
betaMieExtinction, mieG, sunRadiance, ozoneLayerEnabled, HO, betaOzoneExtinction,
SAMPLES_R, SAMPLES_MU, SAMPLES_MU_S, SAMPLES_NU, inverseModelTransformMatrix,
modelTransformMatrix, projectionToModelTransformMatrix,
viewToWorldMatrix, camPosObj, sunDirectionObj, hardShadows,
transmittanceTexture, irradianceTexture, inscatterTexture) _uniformCache;
GLuint _transmittanceTableTexture = 0;
GLuint _irradianceTableTexture = 0;
GLuint _inScatteringTableTexture = 0;
GLuint _deltaETableTexture = 0;
GLuint _deltaSRayleighTableTexture = 0;
GLuint _deltaSMieTableTexture = 0;
GLuint _deltaJTableTexture = 0;
modelTransformMatrix, projectionToModelTransform, viewToWorldMatrix,
camPosObj, sunDirectionObj, hardShadows, transmittanceTexture, irradianceTexture,
inscatterTexture) _uniformCache;
ghoul::opengl::TextureUnit _transmittanceTableTextureUnit;
ghoul::opengl::TextureUnit _irradianceTableTextureUnit;
ghoul::opengl::TextureUnit _inScatteringTableTextureUnit;
GLuint _transmittanceTableTexture = 0;
GLuint _irradianceTableTexture = 0;
GLuint _inScatteringTableTexture = 0;
// Atmosphere Data
bool _atmosphereCalculated = false;
bool _ozoneEnabled = false;
bool _sunFollowingCameraEnabled = false;
float _atmosphereRadius = 0.f;
float _atmospherePlanetRadius = 0.f;
float _planetAverageGroundReflectance = 0.f;
float _planetGroundRadianceEmission = 0.f;
float _averageGroundReflectance = 0.f;
float _groundRadianceEmission = 0.f;
float _rayleighHeightScale = 0.f;
float _ozoneHeightScale = 0.f;
float _mieHeightScale = 0.f;
@@ -161,34 +144,33 @@ private:
glm::vec3 _ozoneExtinctionCoeff = glm::vec3(0.f);
glm::vec3 _mieScatteringCoeff = glm::vec3(0.f);
glm::vec3 _mieExtinctionCoeff = glm::vec3(0.f);
glm::dvec3 _ellipsoidRadii = glm::dvec3(0.0);
// Atmosphere Textures Dimmensions
glm::ivec2 _transmittanceTableSize = glm::ivec2(256, 64);
glm::ivec2 _irradianceTableSize = glm::ivec2(64, 16);
glm::ivec2 _deltaETableSize = glm::ivec2(64, 16);
int _r_samples = 32;
int _mu_samples = 128;
int _mu_s_samples = 32;
int _nu_samples = 8;
const glm::ivec2 _transmittanceTableSize;
const glm::ivec2 _irradianceTableSize;
const glm::ivec2 _deltaETableSize;
const int _muSSamples;
const int _nuSamples;
const int _muSamples;
const int _rSamples;
const glm::ivec3 _textureSize;
glm::dmat4 _modelTransform;
double _time = 0.0;
// Eclipse Shadows
std::vector<ShadowConfiguration> _shadowConfArray;
std::vector<ShadowRenderingStruct> _shadowDataArrayCache;
bool _hardShadowsEnabled = false;
// Atmosphere Debugging
bool _saveCalculationTextures = false;
const bool _saveCalculationTextures = false;
std::vector<ShadowRenderingStruct> _shadowDataArrayCache;
// Assuming < 1000 shadow casters, the longest uniform name that we are getting is
// shadowDataArray[999].casterPositionVec
// which needs to fit into the uniform buffer
char _uniformNameBuffer[40];
};
} // openspace
} // namespace openspace
#endif // __OPENSPACE_MODULE_ATMOSPHERE___ATMOSPHEREDEFERREDCASTER___H__

View File

@@ -244,7 +244,7 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
MieScatteringCoeffInfo,
glm::vec3(0.004f), glm::vec3(0.00001f), glm::vec3(1.f)
)
, _mieScatteringExtinctionPropCoefficient(
, _mieScatteringExtinctionPropCoeff(
MieScatteringExtinctionPropCoeffInfo,
0.9f, 0.01f, 1.f
)
@@ -328,16 +328,15 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
_miePhaseConstant.onChange(updateWithCalculation);
addProperty(_miePhaseConstant);
_mieScatteringExtinctionPropCoefficient =
_mieScatteringExtinctionPropCoeff =
_mieScattExtPropCoefProp != 1.f ? _mieScattExtPropCoefProp :
_mieScatteringCoeff.value().x / _mieExtinctionCoeff.x;
_mieScatteringExtinctionPropCoefficient.onChange(updateWithCalculation);
addProperty(_mieScatteringExtinctionPropCoefficient);
_mieScatteringExtinctionPropCoeff.onChange(updateWithCalculation);
addProperty(_mieScatteringExtinctionPropCoeff);
if (p.debug.has_value()) {
_preCalculatedTexturesScale =
p.debug->preCalculatedTextureScale.value_or(_preCalculatedTexturesScale);
_textureScale = p.debug->preCalculatedTextureScale.value_or(_textureScale);
_saveCalculationsToTexture =
p.debug->saveCalculatedTextures.value_or(_saveCalculationsToTexture);
@@ -364,15 +363,13 @@ void RenderableAtmosphere::deinitializeGL() {
}
void RenderableAtmosphere::initializeGL() {
_deferredcaster = std::make_unique<AtmosphereDeferredcaster>();
_deferredcaster = std::make_unique<AtmosphereDeferredcaster>(
_textureScale,
_shadowEnabled ? std::move(_shadowConfArray) : std::vector<ShadowConfiguration>(),
_saveCalculationsToTexture
);
_shadowConfArray.clear();
updateAtmosphereParameters();
if (_shadowEnabled) {
_deferredcaster->setShadowConfigArray(_shadowConfArray);
// We no longer need it
_shadowConfArray.clear();
}
_deferredcaster->initialize();
global::deferredcasterManager->attachDeferredcaster(*_deferredcaster);
@@ -382,13 +379,11 @@ bool RenderableAtmosphere::isReady() const {
return true;
}
glm::dmat4 RenderableAtmosphere::computeModelTransformMatrix(
const TransformData& transformData)
{
glm::dmat4 RenderableAtmosphere::computeModelTransformMatrix(const TransformData& data) {
// scale the planet to appropriate size since the planet is a unit sphere
return glm::translate(glm::dmat4(1.0), transformData.translation) *
glm::dmat4(transformData.rotation) *
glm::scale(glm::dmat4(1.0), glm::dvec3(transformData.scale));
return glm::translate(glm::dmat4(1.0), data.translation) *
glm::dmat4(data.rotation) *
glm::scale(glm::dmat4(1.0), glm::dvec3(data.scale));
}
void RenderableAtmosphere::render(const RenderData& data, RendererTasks& renderTask) {
@@ -404,11 +399,10 @@ void RenderableAtmosphere::update(const UpdateData& data) {
_deferredCasterNeedsUpdate = false;
}
if (_deferredCasterNeedsCalculation) {
_deferredcaster->preCalculateAtmosphereParam();
_deferredcaster->calculateAtmosphereParameters();
_deferredCasterNeedsCalculation = false;
}
_deferredcaster->setTime(data.time.j2000Seconds());
glm::dmat4 modelTransform = computeModelTransformMatrix(data.modelTransform);
_deferredcaster->setModelTransform(modelTransform);
_deferredcaster->update(data);
@@ -416,34 +410,26 @@ void RenderableAtmosphere::update(const UpdateData& data) {
void RenderableAtmosphere::updateAtmosphereParameters() {
_mieExtinctionCoeff =
_mieScatteringCoeff.value() / _mieScatteringExtinctionPropCoefficient.value();
_mieScatteringCoeff.value() / _mieScatteringExtinctionPropCoeff.value();
_deferredcaster->setAtmosphereRadius(_planetRadius + _atmosphereHeight);
_deferredcaster->setPlanetRadius(_planetRadius);
_deferredcaster->setPlanetAverageGroundReflectance(_groundAverageReflectance);
_deferredcaster->setPlanetGroundRadianceEmission(_groundRadianceEmission);
_deferredcaster->setRayleighHeightScale(_rayleighHeightScale);
_deferredcaster->enableOzone(_ozoneEnabled);
_deferredcaster->setOzoneHeightScale(_ozoneHeightScale);
_deferredcaster->setMieHeightScale(_mieHeightScale);
_deferredcaster->setMiePhaseConstant(_miePhaseConstant);
_deferredcaster->setSunRadianceIntensity(_sunIntensity);
_deferredcaster->setRayleighScatteringCoefficients(_rayleighScatteringCoeff);
_deferredcaster->setOzoneExtinctionCoefficients(_ozoneCoeff);
_deferredcaster->setMieScatteringCoefficients(_mieScatteringCoeff);
_deferredcaster->setMieExtinctionCoefficients(_mieExtinctionCoeff);
_deferredcaster->enableSunFollowing(_sunFollowingCameraEnabled);
// TODO: Fix the ellipsoid nature of the renderable globe (JCC)
//_deferredcaster->setEllipsoidRadii(_ellipsoid.radii());
_deferredcaster->setPrecalculationTextureScale(_preCalculatedTexturesScale);
if (_saveCalculationsToTexture) {
_deferredcaster->enablePrecalculationTexturesSaving();
}
if (_shadowEnabled) {
_deferredcaster->setHardShadows(_hardShadowsEnabled);
}
_deferredcaster->setParameters(
_planetRadius + _atmosphereHeight,
_planetRadius,
_groundAverageReflectance,
_groundRadianceEmission,
_rayleighHeightScale,
_ozoneEnabled,
_ozoneHeightScale,
_mieHeightScale,
_miePhaseConstant,
_sunIntensity,
_rayleighScatteringCoeff,
_ozoneCoeff,
_mieScatteringCoeff,
_mieExtinctionCoeff,
_sunFollowingCameraEnabled
);
_deferredcaster->setHardShadows(_hardShadowsEnabled);
}
} // namespace openspace

View File

@@ -72,7 +72,7 @@ public:
static documentation::Documentation Documentation();
private:
glm::dmat4 computeModelTransformMatrix(const openspace::TransformData& transformData);
glm::dmat4 computeModelTransformMatrix(const openspace::TransformData& data);
void updateAtmosphereParameters();
properties::FloatProperty _atmosphereHeight;
@@ -85,7 +85,7 @@ private:
properties::Vec3Property _ozoneCoeff;
properties::FloatProperty _mieHeightScale;
properties::Vec3Property _mieScatteringCoeff;
properties::FloatProperty _mieScatteringExtinctionPropCoefficient;
properties::FloatProperty _mieScatteringExtinctionPropCoeff;
properties::FloatProperty _miePhaseConstant;
properties::FloatProperty _sunIntensity;
properties::BoolProperty _sunFollowingCameraEnabled;
@@ -98,7 +98,7 @@ private:
// Atmosphere Debug
bool _saveCalculationsToTexture = false;
float _preCalculatedTexturesScale = 1.f;
float _textureScale = 1.f;
std::unique_ptr<AtmosphereDeferredcaster> _deferredcaster;

View File

@@ -54,85 +54,11 @@
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Atmosphere Rendering Parameters
uniform float Rg;
uniform float Rt;
uniform float AverageGroundReflectance;
uniform float groundRadianceEmission;
uniform float HR;
uniform vec3 betaRayleigh;
uniform float HO;
uniform vec3 betaOzoneExtinction;
uniform float HM;
uniform vec3 betaMieScattering;
uniform vec3 betaMieExtinction;
uniform float mieG;
uniform float sunRadiance;
uniform bool ozoneLayerEnabled;
uniform ivec2 TRANSMITTANCE;
uniform ivec2 SKY;
uniform ivec2 OTHER_TEXTURES;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
const int INSCATTER_INTEGRAL_SAMPLES = 50;
const float M_PI = 3.141592657;
const float ATM_EPSILON = 1.0;
// Integration steps
const int TRANSMITTANCE_STEPS = 500;
const int INSCATTER_INTEGRAL_SAMPLES = 50;
const int IRRADIANCE_INTEGRAL_SAMPLES = 32;
const int INSCATTER_SPHERICAL_INTEGRAL_SAMPLES = 16;
const float M_PI = 3.141592657;
const float M_2PI = 2.0 * M_PI;
uniform sampler2D transmittanceTexture;
float Rg2 = Rg * Rg;
float Rt2 = Rt * Rt;
float H = sqrt(Rt2 - Rg2);
float H2 = Rt2 - Rg2;
float invSamplesMu = 1.0 / float(SAMPLES_MU);
float invSamplesR = 1.0 / float(SAMPLES_R);
float invSamplesMuS = 1.0 / float(SAMPLES_MU_S);
float invSamplesNu = 1.0 / float(SAMPLES_NU);
float RtMinusRg = float(Rt - Rg);
float invRtMinusRg = 1.0 / RtMinusRg;
float opticalDepth(float localH, float r, float mu, float d) {
float invH = 1.0 / localH;
float a = sqrt(0.5 * invH * r);
vec2 a01 = a * vec2(mu, mu + d / r);
vec2 a01s = sign(a01);
vec2 a01sq = a01 * a01;
float x = a01s.y > a01s.x ? exp(a01sq.x) : 0.0;
vec2 y = a01s / (2.3193 * abs(a01) + sqrt(1.52 * a01sq + 4.0)) * vec2(1.0, exp(-d * invH * (d / (2.0 * r) + mu)));
return sqrt(M_2PI * H * r) * exp((Rg-r)*invH) * (x + dot(y, vec2(1.0, -1.0)));
}
vec3 analyticTransmittance(float r, float mu, float d) {
vec3 ozone = vec3(0.0);
if (ozoneLayerEnabled) {
ozone = betaOzoneExtinction * (0.0000006) * opticalDepth(HO, r, mu, d);
}
return exp(-betaRayleigh * opticalDepth(HR, r, mu, d) - ozone -
betaMieExtinction * opticalDepth(HM, r, mu, d));
}
vec3 irradiance(sampler2D sampler, float r, float muSun) {
float u_r = (r - Rg) * invRtMinusRg;
float u_muSun = (muSun + 0.2) / 1.2;
return texture(sampler, vec2(u_muSun, u_r)).rgb;
}
//================================================//
//=============== General Functions ==============//
//================================================//
// In the following shaders r (altitude) is the length of vector/position x in the
// atmosphere (or on the top of it when considering an observer in space), where the light
// is coming from the opposite direction of the view direction, here the vector v or
@@ -142,7 +68,7 @@ vec3 irradiance(sampler2D sampler, float r, float muSun) {
// or top of atmosphere
// r := || vec(x) || e [0, Rt]
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
float rayDistance(float r, float mu) {
float rayDistance(float r, float mu, float Rt, float Rg) {
// The light ray starting at the observer in/on the atmosphere can have to possible end
// points: the top of the atmosphere or the planet ground. So the shortest path is the
// one we are looking for, otherwise we may be passing through the ground
@@ -151,9 +77,8 @@ float rayDistance(float r, float mu) {
float atmRadiusEps2 = (Rt + ATM_EPSILON) * (Rt + ATM_EPSILON);
float mu2 = mu * mu;
float r2 = r * r;
float rg2 = Rg * Rg;
float rayDistanceAtmosphere = -r * mu + sqrt(r2 * (mu2 - 1.0) + atmRadiusEps2);
float delta = r2 * (mu2 - 1.0) + rg2;
float delta = r2 * (mu2 - 1.0) + Rg*Rg;
// Ray may be hitting ground
if (delta >= 0.0) {
@@ -173,19 +98,23 @@ float rayDistance(float r, float mu) {
// nu := cosone of the angle between vec(s) and vec(v)
// dhdH := it is a vec4. dhdH.x stores the dminT := Rt - r, dhdH.y stores the dH value
// (see paper), dhdH.z stores dminG := r - Rg and dhdH.w stores dh (see paper)
void unmappingMuMuSunNu(float r, vec4 dhdH, out float mu, out float muSun, out float nu) {
void unmappingMuMuSunNu(float r, vec4 dhdH, int SAMPLES_MU, float Rg, float Rt,
int SAMPLES_MU_S, int SAMPLES_NU,
out float mu, out float muSun, out float nu)
{
// Window coordinates of pixel (uncentering also)
vec2 fragment = gl_FragCoord.xy - vec2(0.5);
// Pre-calculations
float r2 = r * r;
float Rg2 = Rg * Rg;
float halfSAMPLE_MU = float(SAMPLES_MU) / 2.0;
// If the (vec(x) dot vec(v))/r is negative, i.e., the light ray has great probability
// to touch the ground, we obtain mu considering the geometry of the ground
if (fragment.y < halfSAMPLE_MU) {
float ud = 1.0 - (fragment.y / (halfSAMPLE_MU - 1.0));
float d = min(max(dhdH.z, ud * dhdH.w), dhdH.w * 0.999);
float d = min(max(dhdH.z, ud * dhdH.w), dhdH.w * 0.999);
// cosine law: Rg^2 = r^2 + d^2 - 2rdcos(pi-theta) where cosine(theta) = mu
mu = (Rg2 - r2 - d * d) / (2.0 * r * d);
// We can't handle a ray inside the planet, i.e., when r ~ Rg, so we check against it.
@@ -199,12 +128,12 @@ void unmappingMuMuSunNu(float r, vec4 dhdH, out float mu, out float muSun, out f
float d = (fragment.y - halfSAMPLE_MU) / (halfSAMPLE_MU - 1.0);
d = min(max(dhdH.x, d * dhdH.y), dhdH.y * 0.999);
// cosine law: Rt^2 = r^2 + d^2 - 2rdcos(pi-theta) where cosine(theta) = mu
mu = (Rt2 - r2 - d * d) / (2.0 * r * d);
mu = (Rt*Rt - r2 - d * d) / (2.0 * r * d);
}
float modValueMuSun = mod(fragment.x, float(SAMPLES_MU_S)) / (float(SAMPLES_MU_S) - 1.0);
// The following mapping is different from the paper. See Colliene for an details.
muSun = tan((2.0 * modValueMuSun - 1.0 + 0.26) * 1.1f) / tan(1.26 * 1.1);
// The following mapping is different from the paper. See Collienne for an details.
muSun = tan((2.0 * modValueMuSun - 1.0 + 0.26) * 1.1) / tan(1.26 * 1.1);
nu = -1.0 + floor(fragment.x / float(SAMPLES_MU_S)) / (float(SAMPLES_NU) - 1.0) * 2.0;
}
@@ -213,14 +142,14 @@ void unmappingMuMuSunNu(float r, vec4 dhdH, out float mu, out float muSun, out f
// hits the ground or the top of atmosphere.
// r := height of starting point vect(x)
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
vec3 transmittance(float r, float mu) {
vec3 transmittance(sampler2D tex, float r, float mu, float Rg, float Rt) {
// Given the position x (here the altitude r) and the view angle v
// (here the cosine(v)= mu), we map this
float u_r = sqrt((r - Rg) * invRtMinusRg);
// See Colliene to understand the mapping
float u_r = sqrt((r - Rg) / (Rt - Rg));
// See Collienne to understand the mapping
float u_mu = atan((mu + 0.15) / 1.15 * tan(1.5)) / 1.5;
return texture(transmittanceTexture, vec2(u_mu, u_r)).rgb;
return texture(tex, vec2(u_mu, u_r)).rgb;
}
// Given a position r and direction mu, calculates de transmittance along the ray with
@@ -228,13 +157,13 @@ vec3 transmittance(float r, float mu) {
// T(a,b) = TableT(a,v)/TableT(b, v)
// r := height of starting point vect(x)
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
vec3 transmittance(float r, float mu, float d) {
vec3 transmittance(sampler2D tex, float r, float mu, float d, float Rg, float Rt) {
// Here we use the transmittance property: T(x,v) = T(x,d)*T(d,v) to, given a distance
// d, calculates that transmittance along that distance starting in x (height r):
// T(x,d) = T(x,v)/T(d,v).
//
// From cosine law: c^2 = a^2 + b^2 - 2*a*b*cos(ab)
float ri = sqrt(d * d + r * r + 2.0 * r * d * mu);
float ri = sqrt(d * d + r * r + 2.0 * r * d * mu);
// mu_i = (vec(d) dot vec(v)) / r_i
// = ((vec(x) + vec(d-x)) dot vec(v))/ r_i
// = (r*mu + d) / r_i
@@ -246,19 +175,21 @@ vec3 transmittance(float r, float mu, float d) {
// x --> x0, then x0-->x.
// Also, let's use the property: T(a,c) = T(a,b)*T(b,c)
// Because T(a,c) and T(b,c) are already in the table T, T(a,b) = T(a,c)/T(b,c).
vec3 res;
if (mu > 0.0) {
return min(transmittance(r, mu) / transmittance(ri, mui), 1.0);
res = transmittance(tex, r, mu, Rg, Rt) / transmittance(tex, ri, mui, Rg, Rt);
}
else {
return min(transmittance(ri, -mui) / transmittance(r, -mu), 1.0);
res = transmittance(tex, ri, -mui, Rg, Rt) / transmittance(tex, r, -mu, Rg, Rt);
}
return min(res, 1.0);
}
// Calculates Rayleigh phase function given the scattering cosine angle mu
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
float rayleighPhaseFunction(float mu) {
//return (3.0f / (16.0f * M_PI)) * (1.0f + mu * mu);
return 0.0596831036 * (1.0 + mu * mu);
// return (3.0 / (16.0 * M_PI)) * (1.0 + mu * mu);
return 0.0596831036 * (1.0 + mu * mu);
}
// Calculates Mie phase function given the scattering cosine angle mu
@@ -277,38 +208,30 @@ float miePhaseFunction(float mu, float mieG) {
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v))
// nu := cosine of the angle between vec(s) and vec(v)
vec4 texture4D(sampler3D table, float r, float mu, float muSun, float nu) {
vec4 texture4D(sampler3D table, float r, float mu, float muSun, float nu, float Rg,
int samplesMu, float Rt, int samplesR, int samplesMuS,
int samplesNu)
{
float r2 = r * r;
float Rg2 = Rg * Rg;
float Rt2 = Rt * Rt;
float rho = sqrt(r2 - Rg2);
float rmu = r * mu;
float delta = rmu * rmu - r2 + Rg2;
vec4 cst = rmu < 0.0 && delta > 0.0 ?
vec4(1.0, 0.0, 0.0, 0.5 - 0.5 * invSamplesMu) :
vec4(-1.0, H2, H, 0.5 + 0.5 * invSamplesMu);
vec4(1.0, 0.0, 0.0, 0.5 - 0.5 / float(samplesMu)) :
vec4(-1.0, Rt2 - Rg2, sqrt(Rt2 - Rg2), 0.5 + 0.5 / float(samplesMu));
float u_r = 0.5 * invSamplesR + rho / H * (1.0 - invSamplesR);
float u_mu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5 - invSamplesMu);
float u_mu_s = 0.5 * invSamplesMuS +
(atan(max(muSun, -0.1975) * tan(1.386)) * 0.9090909090909090 + 0.74) * 0.5 * (1.0 - invSamplesMuS);
float lerp = (nu + 1.0) / 2.0 * (float(SAMPLES_NU) - 1.0);
float u_nu = floor(lerp);
lerp = lerp - u_nu;
float u_r = 0.5 / float(samplesR) + rho / sqrt(Rt2 - Rg2) * (1.0 - 1.0 / float(samplesR));
float u_mu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5 - 1.0 / samplesMu);
float u_mu_s = 0.5 / float(samplesMuS) +
(atan(max(muSun, -0.1975) * tan(1.386)) * 0.9090909090909090 + 0.74) * 0.5 * (1.0 - 1.0 / float(samplesMuS));
float t = (nu + 1.0) / 2.0 * (float(samplesNu) - 1.0);
float u_nu = floor(t);
t = t - u_nu;
return texture(
table, vec3((u_nu + u_mu_s) * invSamplesNu, u_mu, u_r)) * (1.0 - lerp) +
texture(table, vec3((u_nu + u_mu_s + 1.0) * invSamplesNu, u_mu, u_r)) * lerp;
}
// Given the irradiance texture table, the cosine of zenith sun vector and the height of
// the observer (ray's stating point x), calculates the mapping for u_r and u_muSun and
// returns the value in the LUT
// lut := OpenGL texture2D sampler (the irradiance texture deltaE)
// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v))
// r := height of starting point vect(x)
vec3 irradianceLUT(sampler2D lut, float muSun, float r) {
// See Bruneton paper and Coliene to understand the mapping
float u_muSun = (muSun + 0.2) / 1.2;
float u_r = (r - Rg) * invRtMinusRg;
return texture(lut, vec2(u_muSun, u_r)).rgb;
vec4 v1 = texture(table, vec3((u_nu + u_mu_s) / float(samplesNu), u_mu, u_r));
vec4 v2 = texture(table, vec3((u_nu + u_mu_s + 1.0) / float(samplesNu), u_mu, u_r));
return mix(v1, v2, t);
}

View File

@@ -64,27 +64,37 @@ out vec4 renderTarget;
uniform int cullAtmosphere;
uniform float Rg;
uniform float Rt;
uniform float groundRadianceEmission;
uniform float HR;
uniform vec3 betaRayleigh;
uniform float HO;
uniform vec3 betaOzoneExtinction;
uniform float HM;
uniform vec3 betaMieExtinction;
uniform float mieG;
uniform float sunRadiance;
uniform bool ozoneLayerEnabled;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform sampler2D transmittanceTexture;
uniform sampler2D irradianceTexture;
uniform sampler3D inscatterTexture;
uniform sampler2D mainPositionTexture;
uniform sampler2D mainNormalTexture;
uniform sampler2D mainColorTexture;
uniform dmat4 inverseModelTransformMatrix;
uniform dmat4 modelTransformMatrix;
uniform dmat4 viewToWorldMatrix;
uniform dmat4 projectionToModelTransformMatrix;
uniform vec4 viewport;
uniform vec2 resolution;
uniform dvec3 camPosObj;
uniform dvec3 sunDirectionObj;
uniform dvec3 sunWorld;
uniform dvec3 viewDirWorld;
uniform dvec3 sunModel;
/*******************************************************************************
***** ALL CALCULATIONS FOR ECLIPSE ARE IN METERS AND IN WORLD SPACE SYSTEM ****
*******************************************************************************/
@@ -92,8 +102,10 @@ uniform dvec3 sunModel;
const uint numberOfShadows = 1;
struct ShadowRenderingStruct {
double xu, xp;
double rs, rc;
double xu;
double xp;
double rs;
double rc;
dvec3 sourceCasterVec;
dvec3 casterPositionVec;
bool isShadowing;
@@ -113,15 +125,15 @@ float calcShadow(ShadowRenderingStruct shadowInfoArray[numberOfShadows], dvec3 p
}
dvec3 pc = shadowInfoArray[0].casterPositionVec - position;
dvec3 sc_norm = shadowInfoArray[0].sourceCasterVec;
dvec3 pc_proj = dot(pc, sc_norm) * sc_norm;
dvec3 d = pc - pc_proj;
dvec3 scNorm = shadowInfoArray[0].sourceCasterVec;
dvec3 pcProj = dot(pc, scNorm) * scNorm;
dvec3 d = pc - pcProj;
float length_d = float(length(d));
double length_pc_proj = length(pc_proj);
double lengthPcProj = length(pcProj);
float r_p_pi = float(shadowInfoArray[0].rc * (length_pc_proj + shadowInfoArray[0].xp) / shadowInfoArray[0].xp);
float r_u_pi = float(shadowInfoArray[0].rc * (shadowInfoArray[0].xu - length_pc_proj) / shadowInfoArray[0].xu);
float r_p_pi = float(shadowInfoArray[0].rc * (lengthPcProj + shadowInfoArray[0].xp) / shadowInfoArray[0].xp);
float r_u_pi = float(shadowInfoArray[0].rc * (shadowInfoArray[0].xu - lengthPcProj) / shadowInfoArray[0].xu);
if (length_d < r_u_pi) {
// umbra
@@ -142,6 +154,33 @@ float calcShadow(ShadowRenderingStruct shadowInfoArray[numberOfShadows], dvec3 p
}
}
float opticalDepth(float localH, float r, float mu, float d, float Rg) {
float invH = 1.0 / localH;
float a = sqrt(0.5 * invH * r);
vec2 a01 = a * vec2(mu, mu + d / r);
vec2 a01s = sign(a01);
vec2 a01sq = a01 * a01;
float x = a01s.y > a01s.x ? exp(a01sq.x) : 0.0;
vec2 y = a01s / (2.3193 * abs(a01) + sqrt(1.52 * a01sq + 4.0)) *
vec2(1.0, exp(-d * invH * (d / (2.0 * r) + mu)));
return sqrt(2.0 * M_PI * sqrt(Rt*Rt - Rg*Rg) * r) * exp((Rg-r)*invH) * (x + dot(y, vec2(1.0, -1.0)));
}
vec3 analyticTransmittance(float r, float mu, float d) {
vec3 ozone = vec3(0.0);
if (ozoneLayerEnabled) {
ozone = betaOzoneExtinction * 0.0000006 * opticalDepth(HO, r, mu, d, Rg);
}
return exp(-betaRayleigh * opticalDepth(HR, r, mu, d, Rg) - ozone -
betaMieExtinction * opticalDepth(HM, r, mu, d, Rg));
}
vec3 irradiance(sampler2D s, float r, float muSun) {
float u_r = (r - Rg) / (Rt - Rg);
float u_muSun = (muSun + 0.2) / 1.2;
return texture(s, vec2(u_muSun, u_r)).rgb;
}
//////////////////////////////////////////////////////////////////////////////////////////
// ALL CALCULATIONS FOR ATMOSPHERE ARE KM AND IN WORLD SPACE SYSTEM //
//////////////////////////////////////////////////////////////////////////////////////////
@@ -173,10 +212,11 @@ bool atmosphereIntersection(Ray ray, double atmRadius, out double offset,
double l2 = dot(l, l);
double r2 = atmRadius * atmRadius; // avoiding surface acne
offset = 0.0;
maxLength = 0.0;
// Ray origin (eye position) is behind sphere
if ((s < 0.0) && (l2 > r2)) {
offset = 0.0;
maxLength = 0.0;
return false;
}
@@ -184,13 +224,9 @@ bool atmosphereIntersection(Ray ray, double atmRadius, out double offset,
// Ray misses atmosphere
if (m2 > r2) {
offset = 0.0;
maxLength = 0.0;
return false;
}
// We already now the ray hits the atmosphere
// If q = 0.0, there is only one intersection
double q = sqrt(r2 - m2);
@@ -248,9 +284,9 @@ Ray calculateRayRenderableGlobe(vec2 st) {
* the reflectance R[L]
*/
vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 v, vec3 s,
float r, out float mu, out vec3 attenuation, vec3 fragPosObj,
out bool groundHit, double maxLength, double pixelDepth,
vec3 spaceColor, float sunIntensity)
float r, vec3 fragPosObj, double maxLength, double pixelDepth,
vec3 spaceColor, float sunIntensity,
out float mu, out vec3 attenuation, out bool groundHit)
{
const float INTERPOLATION_EPS = 0.004; // precision const from Brunetton
@@ -268,7 +304,11 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3
// I.e. the next line has the scattering light for the "infinite" ray passing through
// the atmosphere. If this ray hits something inside the atmosphere, we will subtract
// the attenuated scattering light from that path in the current path
vec4 inscatterRadiance = max(texture4D(inscatterTexture, r, mu, muSun, nu), 0.0);
vec4 inscatterRadiance = max(
texture4D(inscatterTexture, r, mu, muSun, nu, Rg, SAMPLES_MU, Rt, SAMPLES_R,
SAMPLES_MU_S, SAMPLES_NU),
0.0
);
// After removing the initial path from camera pos to top of atmosphere (for an
// observer in the space) we test if the light ray is hitting the atmosphere
@@ -286,13 +326,14 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3
// attenuation = analyticTransmittance(r, mu, t);
// JCC: change from analytical to LUT transmittance to avoid
// acme on planet surface when looking from far away. (11/02/2017)
attenuation = transmittance(r, mu, t);
attenuation = transmittance(transmittanceTexture, r, mu, t, Rg, Rt);
// Here we use the idea of S[L](a->b) = S[L](b->a), and get the S[L](x0, v, s)
// Then we calculate S[L] = S[L]|x - T(x, x0)*S[L]|x0
// The "infinite" ray hist something inside the atmosphere, so we need to remove
// the unsused contribution to the final radiance.
vec4 inscatterFromSurface = texture4D(inscatterTexture, r0, mu0, muSun0, nu);
vec4 inscatterFromSurface = texture4D(inscatterTexture, r0, mu0, muSun0, nu, Rg,
SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU);
inscatterRadiance = max(inscatterRadiance - attenuation.rgbr * inscatterFromSurface, 0.0);
// We set the irradianceFactor to 1.0 so the reflected irradiance will be considered
@@ -307,7 +348,7 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3
// cos(PI-thetaH) = dist/r
// cos(thetaH) = -dist/r
// muHorizon = -sqrt(r^2-Rg^2)/r = -sqrt(1-(Rg/r)^2)
float muHorizon = -sqrt(1.0 - Rg2 / r2);
float muHorizon = -sqrt(1.0 - Rg*Rg / r2);
// In order to avoid precision problems near horizon, we interpolate between two
// points: above and below horizon
@@ -318,10 +359,10 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3
// Above Horizon
mu = muHorizon - INTERPOLATION_EPS;
// r0 = sqrt(r * r + t * t + 2.0f * r * t * mu);
// r0 = sqrt(r * r + t * t + 2.0 * r * t * mu);
// From cosine law where t = distance between x and x0
// r0^2 = r^2 + t^2 - 2 * r * t * cos(PI-theta)
// r0 = sqrt(r2 + t2 + 2.0f * r * t * mu);
// r0 = sqrt(r2 + t2 + 2.0 * r * t * mu);
float halfCosineLaw1 = r2 + (t * t);
float halfCosineLaw2 = 2.0 * r * t;
r0 = sqrt(halfCosineLaw1 + halfCosineLaw2 * mu);
@@ -332,20 +373,24 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3
// mu0 = (r*mu + t) / r0
mu0 = (r * mu + t) * (1.0 / r0);
vec4 inScatterAboveX = texture4D(inscatterTexture, r, mu, muSun, nu);
vec4 inScatterAboveXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu);
vec4 inScatterAboveX = texture4D(inscatterTexture, r, mu, muSun, nu, Rg,
SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU);
vec4 inScatterAboveXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu, Rg,
SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU);
// Attention for the attenuation.r value applied to the S_Mie
vec4 inScatterAbove = max(inScatterAboveX - attenuation.rgbr * inScatterAboveXs, 0.0);
// Below Horizon
mu = muHorizon + INTERPOLATION_EPS;
//r0 = sqrt(r2 + t2 + 2.0f * r * t * mu);
//r0 = sqrt(r2 + t2 + 2.0 * r * t * mu);
r0 = sqrt(halfCosineLaw1 + halfCosineLaw2 * mu);
mu0 = (r * mu + t) * (1.0 / r0);
vec4 inScatterBelowX = texture4D(inscatterTexture, r, mu, muSun, nu);
vec4 inScatterBelowXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu);
vec4 inScatterBelowX = texture4D(inscatterTexture, r, mu, muSun, nu, Rg,
SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU);
vec4 inScatterBelowXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu, Rg,
SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU);
// Attention for the attenuation.r value applied to the S_Mie
vec4 inScatterBelow = max(inScatterBelowX - attenuation.rgbr * inScatterBelowXs, 0.0);
@@ -370,13 +415,7 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3
// Finally we add the Lsun (all calculations are done with no Lsun so we can change it
// on the fly with no precomputations)
vec3 finalScatteringRadiance = radiance * sunIntensity;
if (groundHit) {
return finalScatteringRadiance;
}
else {
return spaceColor + finalScatteringRadiance;
}
return groundHit ? finalScatteringRadiance : spaceColor + finalScatteringRadiance;
}
/*
@@ -401,8 +440,6 @@ vec3 groundColor(vec3 x, float t, vec3 v, vec3 s, vec3 attenuationXtoX0, vec3 gr
vec3 normal, float irradianceFactor, float waterReflectance,
float sunIntensity)
{
vec3 reflectedRadiance = vec3(0.0);
// First we obtain the ray's end point on the surface
float r0 = length(x + t * v);
@@ -415,7 +452,7 @@ vec3 groundColor(vec3 x, float t, vec3 v, vec3 s, vec3 attenuationXtoX0, vec3 gr
// Is direct Sun light arriving at x0? If not, there is no direct light from Sun (shadowed)
vec3 transmittanceL0 =
muSun < -sqrt(1.0 - (Rg2 / (r0 * r0))) ? vec3(0.0) : transmittance(r0, muSun);
muSun < -sqrt(1.0 - (Rg*Rg / (r0 * r0))) ? vec3(0.0) : transmittance(transmittanceTexture, r0, muSun, Rg, Rt);
// E[L*] at x0
vec3 irradianceReflected = irradiance(irradianceTexture, r0, muSun) * irradianceFactor;
@@ -433,16 +470,14 @@ vec3 groundColor(vec3 x, float t, vec3 v, vec3 s, vec3 attenuationXtoX0, vec3 gr
// Fresnell Schlick's approximation
float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0);
// Walter BRDF approximation
float waterBrdf = fresnel * pow(max(dot(h, normal), 0.0), 150.0);
float waterBrdf = max(fresnel * pow(max(dot(h, normal), 0.0), 150.0), 0.0);
// Adding Fresnell and Water BRDFs approximation to the final surface color
// after adding the sunRadiance and the attenuation of the Sun through atmosphere
groundRadiance += waterReflectance * max(waterBrdf, 0.0) * transmittanceL0 * sunIntensity;
groundRadiance += waterReflectance * waterBrdf * transmittanceL0 * sunIntensity;
}
// Finally, we attenuate the surface Radiance from the point x0 to the camera location
reflectedRadiance = attenuationXtoX0 * groundRadiance;
// Returns reflectedRadiance = 0.0 if the ray doesn't hit the ground.
vec3 reflectedRadiance = attenuationXtoX0 * groundRadiance;
return reflectedRadiance;
}
@@ -464,7 +499,7 @@ vec3 sunColor(vec3 v, vec3 s, float r, float mu, float irradianceFactor) {
// JCC: Change this function to a impostor texture with gaussian decay color weighted
// by the sunRadiance, transmittance and irradianceColor (11/03/2017)
// @TODO (abock, 2021-07-01) This value is hard-coded to our sun right now
// @TODO (abock, 2021-07-01) This value is hard-coded to our sun+earth right now
// Convert 0.3 degrees -> radians
const float SunAngularSize = (0.3 * M_PI / 180.0);
const float FuzzyFactor = 0.5; // How fuzzy should the edges be
@@ -474,7 +509,7 @@ vec3 sunColor(vec3 v, vec3 s, float r, float mu, float irradianceFactor) {
float t = (angle - p1) / (p2 - p1);
float scale = clamp(t, 0.0, 1.0);
return scale * transmittance(r, mu) * sunRadiance * (1.0 - irradianceFactor);
return scale * transmittance(transmittanceTexture, r, mu, Rg, Rt) * sunRadiance * (1.0 - irradianceFactor);
}
void main() {
@@ -588,24 +623,22 @@ void main() {
bool groundHit = false;
vec3 attenuation;
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v, s, r, mu,
attenuation, vec3(positionObjectsCoords), groundHit, maxLength, pixelDepth,
color, sunIntensityInscatter);
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v, s, r,
vec3(positionObjectsCoords), maxLength, pixelDepth, color, sunIntensityInscatter, mu,
attenuation, groundHit);
vec3 atmColor = vec3(0.0);
if (groundHit) {
float eclipseShadowPlanet = calcShadow(shadowDataArray, positionWorldCoords.xyz, true);
float sunIntensityGround = sunRadiance * eclipseShadowPlanet;
atmColor = groundColor(x, tF, v, s, attenuation, color, normal.xyz,
irradianceFactor, normal.w, sunIntensityGround);
atmColor = groundColor(x, tF, v, s, attenuation, color, normal.xyz, irradianceFactor,
normal.w, sunIntensityGround);
}
else {
// In order to get better performance, we are not tracing multiple rays per pixel
// when the ray doesn't intersect the ground
atmColor = sunColor(v, s, r, mu, irradianceFactor);
}
// Final Color of ATM plus terrain:
vec4 finalRadiance = vec4(inscatterColor + atmColor, 1.0);
renderTarget = finalRadiance;
renderTarget = vec4(inscatterColor + atmColor, 1.0);;
}

View File

@@ -24,8 +24,8 @@
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
layout(location = 0) in vec2 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
gl_Position = vec4(in_position, 0.0, 1.0);
}

View File

@@ -24,8 +24,6 @@
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTableColor;
void main() {

View File

@@ -28,19 +28,45 @@
out vec4 renderTarget;
uniform float Rg;
uniform float Rt;
uniform float AverageGroundReflectance;
uniform float HR;
uniform vec3 betaRayleigh;
uniform float HM;
uniform vec3 betaMieScattering;
uniform float mieG;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform sampler2D transmittanceTexture;
uniform float r;
uniform vec4 dhdH;
uniform sampler2D deltaETexture;
uniform sampler3D deltaSRTexture;
uniform sampler3D deltaSMTexture;
uniform int firstIteration;
uniform int firstIteraction;
const int INSCATTER_SPHERICAL_INTEGRAL_SAMPLES = 16;
// -- Spherical Coordinates Steps. phi e [0,2PI] and theta e [0, PI]
const float stepPhi = (2.0 * M_PI) / float(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES);
const float stepTheta = M_PI / float(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES);
// Given the irradiance texture table, the cosine of zenith sun vector and the height of
// the observer (ray's stating point x), calculates the mapping for u_r and u_muSun and
// returns the value in the LUT
// lut := OpenGL texture2D sampler (the irradiance texture deltaE)
// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v))
// r := height of starting point vect(x)
vec3 irradianceLUT(sampler2D lut, float muSun, float r) {
// See Bruneton paper and Coliene to understand the mapping
float u_muSun = (muSun + 0.2) / 1.2;
float u_r = (r - Rg) / (Rt - Rg);
return texture(lut, vec2(u_muSun, u_r)).rgb;
}
vec3 inscatter(float r, float mu, float muSun, float nu) {
// Be sure to not get a cosine or height out of bounds
r = clamp(r, Rg, Rt);
@@ -59,7 +85,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) {
float muSun2 = muSun * muSun;
float sinThetaSinSigma = sqrt(1.0 - mu2) * sqrt(1.0 - muSun2);
// cos(sigma + theta) = cos(theta)cos(sigma)-sin(theta)sin(sigma)
// cos(ni) = nu = mu * muSun - sqrt(1.0f - mu*mu)*sqrt(1.0 - muSun*muSun) // sin(theta) = sqrt(1.0 - mu*mu)
// cos(ni) = nu = mu * muSun - sqrt(1.0 - mu*mu)*sqrt(1.0 - muSun*muSun) // sin(theta) = sqrt(1.0 - mu*mu)
// Now we make sure the angle between vec(s) and vec(v) is in the right range:
nu = clamp(nu, muSun * mu - sinThetaSinSigma, muSun * mu + sinThetaSinSigma);
@@ -69,7 +95,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) {
// -cos(theta) = sqrt(r*r-Rg*Rg)/r
float Rg2 = Rg * Rg;
float r2 = r * r;
float cosHorizon = -sqrt(r2 - Rg2)/r;
float cosHorizon = -sqrt(r2 - Rg2) / r;
// Now we get vec(v) and vec(s) from mu, muSun and nu:
// Assuming:
@@ -97,6 +123,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) {
// In order to integrate over 4PI, we scan the sphere using the spherical coordinates
// previously defined
vec3 radianceJAcc = vec3(0.0);
for (int theta_i = 0; theta_i < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; theta_i++) {
float theta = (float(theta_i) + 0.5) * stepTheta;
float cosineTheta = cos(theta);
@@ -131,7 +158,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) {
// float muGround = (r2 - distanceToGround*distanceToGround - Rg2)/(2*distanceToGround*Rg);
// Access the Transmittance LUT in order to calculate the transmittance from the
// ground point Rg, thorugh the atmosphere, at a distance: distanceToGround
groundTransmittance = transmittance(Rg, muGround, distanceToGround);
groundTransmittance = transmittance(transmittanceTexture, Rg, muGround, distanceToGround, Rg, Rt);
}
for (int phi_i = 0; phi_i < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++phi_i) {
@@ -161,43 +188,48 @@ vec3 inscatter(float r, float mu, float muSun, float nu) {
// We calculate the Rayleigh and Mie phase function for the new scattering angle:
// cos(angle between vec(s) and vec(w)), ||s|| = ||w|| = 1
float nuSW = dot(s, w);
// The first iteraction is different from the others. In the first iteraction all
// The first iteration is different from the others. In the first iteration all
// the light InScattered is coming from the initial pre-computed single InScattered
// light. We stored these values in the deltaS textures (Ray and Mie), and in order
// to avoid problems with the high angle dependency in the phase functions, we don't
// include the phase functions on those tables (that's why we calculate them now).
if (firstIteraction == 1) {
if (firstIteration == 1) {
float phaseRaySW = rayleighPhaseFunction(nuSW);
float phaseMieSW = miePhaseFunction(nuSW, mieG);
// We can now access the values for the single InScattering in the textures deltaS textures.
vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nuSW).rgb;
vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nuSW).rgb;
vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nuSW, Rg, SAMPLES_MU,
Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb;
vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nuSW, Rg, SAMPLES_MU,
Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb;
// Initial InScattering including the phase functions
radianceJ1 += singleRay * phaseRaySW + singleMie * phaseMieSW;
}
else {
// On line 9 of the algorithm, the texture table deltaSR is updated, so when we
// are not in the first iteraction, we are getting the updated result of deltaSR
// are not in the first iteration, we are getting the updated result of deltaSR
// (not the single inscattered light but the accumulated (higher order)
// inscattered light.
// w.z is the cosine(theta) = mu for vec(w)
radianceJ1 += texture4D(deltaSRTexture, r, w.z, muSun, nuSW).rgb;
radianceJ1 += texture4D(deltaSRTexture, r, w.z, muSun, nuSW, Rg, SAMPLES_MU, Rt,
SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb;
}
// Finally, we add the atmospheric scale height (See: Radiation Transfer on the
// Atmosphere and Ocean from Thomas and Stamnes, pg 9-10.
return radianceJ1 * (betaRayleigh * exp(-(r - Rg) / HR) * phaseRayleighWV +
radianceJAcc += radianceJ1 * (betaRayleigh * exp(-(r - Rg) / HR) * phaseRayleighWV +
betaMieScattering * exp(-(r - Rg) / HM) * phaseMieWV) * dw;
}
}
return radianceJAcc;
}
void main() {
// InScattering Radiance to be calculated at different points in the ray path
// Unmapping the variables from texture texels coordinates to mapped coordinates
float mu, muSun, nu;
unmappingMuMuSunNu(r, dhdH, mu, muSun, nu);
unmappingMuMuSunNu(r, dhdH, SAMPLES_MU, Rg, Rt, SAMPLES_MU_S, SAMPLES_NU, mu, muSun, nu);
// Calculate the the light inScattered in direction
// -vec(v) for the point at height r (vec(y) following Bruneton and Neyret's paper

View File

@@ -28,6 +28,10 @@
out vec4 renderTarget;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform int layer;
uniform sampler3D deltaSRTexture;
uniform sampler3D deltaSMTexture;

View File

@@ -28,6 +28,10 @@
out vec4 renderTarget;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform int layer;
uniform sampler3D deltaSTexture;
@@ -35,10 +39,9 @@ void main() {
vec2 p = gl_FragCoord.xy - vec2(0.5);
float nu = -1.0 + floor(p.x / float(SAMPLES_MU_S)) / (float(SAMPLES_NU) - 1.0) * 2.0;
vec3 uvw = vec3(
gl_FragCoord.xy,
float(layer) + 0.5) / vec3(ivec3(SAMPLES_MU_S * SAMPLES_NU, SAMPLES_MU, SAMPLES_R)
);
vec3 uvw =
vec3(gl_FragCoord.xy, float(layer) + 0.5) /
vec3(ivec3(SAMPLES_MU_S * SAMPLES_NU, SAMPLES_MU, SAMPLES_R));
// See Bruneton and Neyret paper, "Angular Precision" paragraph to understanding why we
// are dividing the S[L*] by the Rayleigh phase function.

View File

@@ -29,6 +29,18 @@
layout(location = 0) out vec4 renderTarget1;
layout(location = 1) out vec4 renderTarget2;
uniform float Rg;
uniform float Rt;
uniform float HR;
uniform vec3 betaRayleigh;
uniform float HO;
uniform float HM;
uniform vec3 betaMieScattering;
uniform bool ozoneLayerEnabled;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform sampler2D transmittanceTexture;
uniform float r;
uniform vec4 dhdH;
@@ -60,7 +72,9 @@ void integrand(float r, float mu, float muSun, float nu, float y, out vec3 S_R,
if (muSun_i >= -sqrt(1.0 - Rg * Rg / (ri * ri))) {
// It's the transmittance from the point y (ri) to the top of atmosphere in direction
// of the sun (muSun_i) and the transmittance from the observer at x (r) to y (ri).
vec3 transmittanceY = transmittance(r, mu, y) * transmittance(ri, muSun_i);
vec3 transmittanceY =
transmittance(transmittanceTexture, r, mu, y, Rg, Rt) *
transmittance(transmittanceTexture, ri, muSun_i, Rg, Rt);
// exp(-h/H)*T(x,v)
if (ozoneLayerEnabled) {
S_R = (exp(-(ri - Rg) / HO) + exp(-(ri - Rg) / HR)) * transmittanceY;
@@ -83,7 +97,7 @@ void inscatter(float r, float mu, float muSun, float nu, out vec3 S_R, out vec3
S_R = vec3(0.0);
S_M = vec3(0.0);
float rayDist = rayDistance(r, mu);
float rayDist = rayDistance(r, mu, Rt, Rg);
float dy = rayDist / float(INSCATTER_INTEGRAL_SAMPLES);
vec3 S_Ri;
vec3 S_Mi;
@@ -103,13 +117,10 @@ void inscatter(float r, float mu, float muSun, float nu, out vec3 S_R, out vec3
}
void main() {
vec3 S_R; // First Order Rayleigh InScattering
vec3 S_M; // First Order Mie InScattering
// From the layer interpolation (see C++ code for layer to r) and the textures
// parameters (uv), we unmapping mu, muSun and nu.
float mu, muSun, nu;
unmappingMuMuSunNu(r, dhdH, mu, muSun, nu);
unmappingMuMuSunNu(r, dhdH, SAMPLES_MU, Rg, Rt, SAMPLES_MU_S, SAMPLES_NU, mu, muSun, nu);
// Here we calculate the single inScattered light. Because this is a single
// inscattering, the light that arrives at a point y in the path from the eye to the
@@ -122,6 +133,8 @@ void main() {
// S[L0] = P_R*S_R[L0] + P_M*S_M[L0]
// In order to save memory, we just store the red component of S_M[L0], and later we use
// the proportionality rule to calcule the other components.
vec3 S_R; // First Order Rayleigh InScattering
vec3 S_M; // First Order Mie InScattering
inscatter(r, mu, muSun, nu, S_R, S_M);
renderTarget1 = vec4(S_R, 1.0);
renderTarget2 = vec4(S_M, 1.0);

View File

@@ -28,6 +28,13 @@
out vec4 renderTarget;
uniform float Rg;
uniform float Rt;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform sampler2D transmittanceTexture;
uniform float r;
uniform vec4 dhdH;
uniform sampler3D deltaJTexture;
@@ -35,7 +42,7 @@ uniform sampler3D deltaJTexture;
// The integrand here is the f(y) of the trapezoidal rule:
vec3 integrand(float r, float mu, float muSun, float nu, float dist) {
// We can calculate r_i by the cosine law: r_i^2=dist^2 + r^2 - 2*r*dist*cos(PI-theta)
float r_i = sqrt(r * r + dist * dist + 2.0f * r * dist * mu);
float r_i = sqrt(r * r + dist * dist + 2.0 * r * dist * mu);
// r_i can be found using the dot product:
// vec(y_i) dot vec(dist) = cos(theta_i) * ||vec(y_i)|| * ||vec(dist)||
// But vec(y_i) = vec(x) + vec(dist), also: vec(x) dot vec(dist) = cos(theta) = mu
@@ -46,12 +53,15 @@ vec3 integrand(float r, float mu, float muSun, float nu, float dist) {
// But vec(y_i) = vec(x) + vec(dist), and vec(x) dot vec(s) = muSun, cos(sigma_i + theta_i) = nu
float muSun_i = (r * muSun + dist * nu) / r_i;
// The irradiance attenuated from point r until y (y-x = dist)
return transmittance(r, mu, dist) * texture4D(deltaJTexture, r_i, mu_i, muSun_i, nu).rgb;
return
transmittance(transmittanceTexture, r, mu, dist, Rg, Rt) *
texture4D(deltaJTexture, r_i, mu_i, muSun_i, nu, Rg, SAMPLES_MU, Rt, SAMPLES_R,
SAMPLES_MU_S, SAMPLES_NU).rgb;
}
vec3 inscatter(float r, float mu, float muSun, float nu) {
vec3 inScatteringRadiance = vec3(0.0);
float dy = rayDistance(r, mu) / float(INSCATTER_INTEGRAL_SAMPLES);
float dy = rayDistance(r, mu, Rt, Rg) / float(INSCATTER_INTEGRAL_SAMPLES);
vec3 inScatteringRadiance_i = integrand(r, mu, muSun, nu, 0.0);
// In order to solve the integral from equation (11) we use the trapezoidal rule:
@@ -71,7 +81,7 @@ void main() {
float muSun = 0.0;
float nu = 0.0;
// Unmapping the variables from texture texels coordinates to mapped coordinates
unmappingMuMuSunNu(r, dhdH, mu, muSun, nu);
unmappingMuMuSunNu(r, dhdH, SAMPLES_MU, Rg, Rt, SAMPLES_MU_S, SAMPLES_NU, mu, muSun, nu);
// Write to texture deltaSR
renderTarget = vec4(inscatter(r, mu, muSun, nu), 1.0);

View File

@@ -28,16 +28,24 @@
out vec4 renderTableColor;
void main() {
// See Bruneton and Colliene to understand the mapping
float muSun = -0.2 + (gl_FragCoord.x - 0.5) / (float(OTHER_TEXTURES.x) - 1.0) * 1.2;
float r = Rg + (gl_FragCoord.y - 0.5) / (float(OTHER_TEXTURES.y) ) * RtMinusRg;
uniform float Rg;
uniform float Rt;
uniform ivec2 OTHER_TEXTURES;
uniform sampler2D transmittanceTexture;
// We are calculating the Irradiance for L0, i.e., only the radiance coming from Sun
// direction is accounted:
void main() {
// See Bruneton and Collienne to understand the mapping
float muSun = -0.2 + (gl_FragCoord.x - 0.5) / (float(OTHER_TEXTURES.x) - 1.0) * 1.2;
float r = Rg + (gl_FragCoord.y - 0.5) / (float(OTHER_TEXTURES.y)) * (Rt - Rg);
// We are calculating the Irradiance for L0, i.e., only the radiance coming from the Sun
// direction is accounted for:
// E[L0](x,s) = L0*dot(w,n) or 0 (if v!=s or the sun is occluded).
// Because we consider the Planet as a perfect sphere and we are considering only single
// Because we consider the planet as a perfect sphere and we are considering only single
// scattering here, the dot product dot(w,n) is equal to dot(s,n) that is equal to
// dot(s, r/||r||) = muSun.
renderTableColor = vec4(transmittance(r, muSun) * max(muSun, 0.0), 0.0);
renderTableColor = vec4(
transmittance(transmittanceTexture, r, muSun, Rg, Rt) * max(muSun, 0.0),
0.0
);
}

View File

@@ -24,10 +24,9 @@
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTableColor;
uniform ivec2 OTHER_TEXTURES;
uniform sampler2D deltaETexture;
void main() {

View File

@@ -28,22 +28,32 @@
out vec4 renderTableColor;
uniform int firstIteraction;
uniform float Rg;
uniform float Rt;
uniform float mieG;
uniform ivec2 SKY;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
uniform int firstIteration;
uniform sampler3D deltaSRTexture;
uniform sampler3D deltaSMTexture;
const int IRRADIANCE_INTEGRAL_SAMPLES = 32;
// Spherical Coordinates Steps. phi e [0,2PI] and theta e [0, PI/2]
const float stepPhi = (2.0 * M_PI) / float(IRRADIANCE_INTEGRAL_SAMPLES);
const float stepTheta = M_PI / (2.0 * float(IRRADIANCE_INTEGRAL_SAMPLES));
void main() {
// See Bruneton and Colliene to understand the mapping.
// See Bruneton and Collienne to understand the mapping.
float muSun = -0.2 + (gl_FragCoord.x - 0.5) / (float(SKY.x) - 1.0) * 1.2;
float r = Rg + (gl_FragCoord.y - 0.5) / (float(SKY.y) - 1.0) * RtMinusRg;
float r = Rg + (gl_FragCoord.y - 0.5) / (float(SKY.y) - 1.0) * (Rt - Rg);
// We know that muSun = cos(sigma) = s.z/||s||
// But, ||s|| = 1, so s.z = muSun. Also,
// ||s|| = 1, so s.x = sin(sigma) = sqrt(1-muSun^2) and s.y = 0.0f
// ||s|| = 1, so s.x = sin(sigma) = sqrt(1-muSun^2) and s.y = 0.0
vec3 s = vec3(max(sqrt(1.0 - muSun * muSun), 0.0), 0.0, muSun);
// In order to solve the integral from equation (15) we use the trapezoidal rule:
@@ -60,30 +70,32 @@ void main() {
vec3 w = vec3(cos(phi) * sin(theta), sin(phi) * sin(theta), cos(theta));
float nu = dot(s, w);
// The first iteraction is different from the others, that's because in the first
// iteraction all the light arriving are coming from the initial pre-computed
// single scattered light. We stored these values in the deltaS textures (Ray and
// Mie), and in order to avoid problems with the high angle dependency in the phase
// functions, we don't include the phase functions on those tables (that's why we
// calculate them now)
if (firstIteraction == 1) {
// The first iteration is different from the others as in the first iteration all
// the light arriving is coming from the initial pre-computed single scattered
// light. We stored these values in the deltaS textures (Ray and Mie), and in order
// to avoid problems with the high angle dependency in the phase functions, we don't
// include the phase functions on those tables (that's why we calculate them now)
if (firstIteration == 1) {
float phaseRay = rayleighPhaseFunction(nu);
float phaseMie = miePhaseFunction(nu, mieG);
vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nu).rgb;
vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nu).rgb;
vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nu, Rg, SAMPLES_MU, Rt,
SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb;
vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nu, Rg, SAMPLES_MU, Rt,
SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb;
// w.z is the cosine(theta) = mu for vec(w) and also vec(w) dot vec(n(xo))
irradianceE += (singleRay * phaseRay + singleMie * phaseMie) * w.z * dw;
}
else {
// On line 10 of the algorithm, the texture table deltaE is updated, so when we
// are not in the first iteraction, we are getting the updated result of deltaE
// are not in the first iteration, we are getting the updated result of deltaE
// (not the single irradiance light but the accumulated (higher order) irradiance
// light. w.z is the cosine(theta) = mu for vec(w) and also vec(w) dot vec(n(xo))
irradianceE += texture4D(deltaSRTexture, r, w.z, muSun, nu).rgb * w.z * dw;
irradianceE += texture4D(deltaSRTexture, r, w.z, muSun, nu, Rg, SAMPLES_MU, Rt,
SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb * w.z * dw;
}
}
}
// Write the higher oder irradiance to texture deltaE
// Write the higher order irradiance to texture deltaE
renderTableColor = vec4(irradianceE, 0.0);
}

View File

@@ -28,6 +28,19 @@
out vec4 renderTableColor;
uniform float Rg;
uniform float Rt;
uniform float HR;
uniform vec3 betaRayleigh;
uniform float HO;
uniform vec3 betaOzoneExtinction;
uniform float HM;
uniform vec3 betaMieExtinction;
uniform bool ozoneLayerEnabled;
uniform ivec2 TRANSMITTANCE;
const int TRANSMITTANCE_STEPS = 500;
// Optical depth by integration, from ray starting at point vec(x), i.e, height r and
// angle mu (cosine of vec(v)) until top of atmosphere or planet's ground.
// r := height of starting point vect(x)
@@ -42,14 +55,14 @@ float opticalDepth(float r, float mu, float H) {
// direction and starting and ending points.
// cosine law for triangles: y_i^2 = a^2 + b^2 - 2abcos(alpha)
float cosZenithHorizon = -sqrt(1.0 - (Rg * Rg / r2));
float cosZenithHorizon = -sqrt(1.0 - ((Rg * Rg) / r2));
if (mu < cosZenithHorizon) {
return 1e9;
}
// Integrating using the Trapezoidal rule:
// Integral(f(y)dy)(from a to b) = ((b-a)/2n_steps)*(Sum(f(y_i+1)+f(y_i)))
float b_a = rayDistance(r, mu);
float b_a = rayDistance(r, mu, Rt, Rg);
float deltaStep = b_a / float(TRANSMITTANCE_STEPS);
// cosine law
float y_i = exp(-(r - Rg) / H);
@@ -72,11 +85,11 @@ void main() {
// In the paper u_r^2 = (r^2-Rg^2)/(Rt^2-Rg^2)
// So, extracting r from u_r in the above equation:
float r = Rg + (u_r * u_r) * RtMinusRg;
float r = Rg + (u_r * u_r) * (Rt - Rg);
// In the paper the Bruneton suggest mu = dot(v,x)/||x|| with ||v|| = 1.0
// Later he proposes u_mu = (1-exp(-3mu-0.6))/(1-exp(-3.6))
// But the below one is better. See Colliene.
// But the below one is better. See Collienne.
// One must remember that mu is defined from 0 to PI/2 + epsilon
float muSun = -0.15 + tan(1.5 * u_mu) / tan(1.5) * 1.15;

View File

@@ -118,14 +118,7 @@ void RenderableCartesianAxes::initializeGL() {
);
glGenVertexArrays(1, &_vaoId);
glGenBuffers(1, &_vBufferId);
glGenBuffers(1, &_iBufferId);
glBindVertexArray(_vaoId);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferId);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
std::vector<Vertex> vertices({
Vertex{0.f, 0.f, 0.f},
@@ -140,7 +133,7 @@ void RenderableCartesianAxes::initializeGL() {
0, 3
};
glBindVertexArray(_vaoId);
glGenBuffers(1, &_vBufferId);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferId);
glBufferData(
GL_ARRAY_BUFFER,
@@ -149,8 +142,10 @@ void RenderableCartesianAxes::initializeGL() {
GL_STATIC_DRAW
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
glGenBuffers(1, &_iBufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferId);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
@@ -158,6 +153,7 @@ void RenderableCartesianAxes::initializeGL() {
indices.data(),
GL_STATIC_DRAW
);
glBindVertexArray(0);
}
void RenderableCartesianAxes::deinitializeGL() {
@@ -201,9 +197,9 @@ void RenderableCartesianAxes::render(const RenderData& data, RendererTasks&){
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnablei(GL_BLEND, 0);
glEnable(GL_LINE_SMOOTH);
glLineWidth(3.0);
glBindVertexArray(_vaoId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferId);
glDrawElements(GL_LINES, NVertexIndices, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);

View File

@@ -224,21 +224,21 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _color(ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
, _size(SizeInfo, 8.f, 0.5f, 30.f)
, _fontSize(FontSizeInfo, 50.f, 1.f, 100.f)
, _size(SizeInfo, 8.f, 0.5f, 30.f)
, _minMaxSize(MinMaxSizeInfo, glm::ivec2(8, 20), glm::ivec2(0), glm::ivec2(100))
, _enableFadingEffect(EnableFadingEffectInfo, false)
, _text(TextInfo, "")
, _fadeDistances(FadeDistancesInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f))
, _enableFadingEffect(EnableFadingEffectInfo, false)
, _fadeWidths(FadeWidthsInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f))
, _orientationOption(
OrientationOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
, _fadeDistances(FadeDistancesInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f))
, _fadeUnitOption(
FadeUnitOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
, _orientationOption(
OrientationOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
{
const Parameters p = codegen::bake<Parameters>(dictionary);

View File

@@ -255,21 +255,7 @@ void RenderablePlane::render(const RenderData& data, RendererTasks&) {
_shader->setUniform("multiplyColor", _multiplyColor);
bool usingFramebufferRenderer = global::renderEngine->rendererImplementation() ==
RenderEngine::RendererImplementation::Framebuffer;
bool usingABufferRenderer = global::renderEngine->rendererImplementation() ==
RenderEngine::RendererImplementation::ABuffer;
if (usingABufferRenderer) {
_shader->setUniform(
"additiveBlending",
_blendMode == static_cast<int>(BlendMode::Additive)
);
}
bool additiveBlending =
(_blendMode == static_cast<int>(BlendMode::Additive)) && usingFramebufferRenderer;
bool additiveBlending = (_blendMode == static_cast<int>(BlendMode::Additive));
if (additiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);

View File

@@ -215,7 +215,10 @@ void RenderablePrism::updateVertexData() {
for (int i = 0; i < 2; ++i) {
float h = i * _length; // z value, 0 to _length
for (int j = 0, k = 0; j < _nShapeSegments && k < unitVertices.size(); ++j, k += 2) {
for (int j = 0, k = 0;
j < _nShapeSegments && k < static_cast<int>(unitVertices.size());
++j, k += 2)
{
float ux = unitVertices[k];
float uy = unitVertices[k + 1];
@@ -239,7 +242,10 @@ void RenderablePrism::updateVertexData() {
_vertexArray.push_back(_length);
}
else {
for (int j = 0, k = 0; j < _nLines && k < unitVerticesLines.size(); ++j, k += 2) {
for (int j = 0, k = 0;
j < _nLines && k < static_cast<int>(unitVerticesLines.size());
++j, k += 2)
{
float ux = unitVerticesLines[k];
float uy = unitVerticesLines[k + 1];

View File

@@ -398,24 +398,14 @@ void RenderableSphere::render(const RenderData& data, RendererTasks&) {
glDisable(GL_CULL_FACE);
}
bool usingFramebufferRenderer = global::renderEngine->rendererImplementation() ==
RenderEngine::RendererImplementation::Framebuffer;
bool usingABufferRenderer = global::renderEngine->rendererImplementation() ==
RenderEngine::RendererImplementation::ABuffer;
if (usingABufferRenderer && _useAdditiveBlending) {
_shader->setUniform("additiveBlending", true);
}
if (usingFramebufferRenderer && _useAdditiveBlending) {
if (_useAdditiveBlending) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(false);
}
_sphere->render();
if (usingFramebufferRenderer && _useAdditiveBlending) {
if (_useAdditiveBlending) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(true);
}

View File

@@ -430,14 +430,8 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) {
/*glm::ivec2 resolution = global::renderEngine.renderingResolution();
_programObject->setUniform(_uniformCache.resolution, resolution);*/
const bool usingFramebufferRenderer =
global::renderEngine->rendererImplementation() ==
RenderEngine::RendererImplementation::Framebuffer;
if (usingFramebufferRenderer) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
const bool renderLines = (_appearance.renderingModes == RenderingModeLines) ||
(_appearance.renderingModes == RenderingModeLinesPoints);
@@ -508,10 +502,8 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) {
glBindVertexArray(0);
if (usingFramebufferRenderer) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(true);
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(true);
_programObject->deactivate();
}

View File

@@ -33,17 +33,20 @@ uniform vec3 yColor;
uniform vec3 zColor;
Fragment getFragment() {
Fragment frag;
Fragment frag;
vec3 colorComponents = step(0.01, vs_positionModelSpace);
// We compare against a small value as the first vertex doesn't have a positional
// information (or rather it is 0) and we don't want to miss out on the color close to
// the origin
vec3 colorComponents = step(2e-32, vs_positionModelSpace);
frag.color.rgb = colorComponents.x * xColor +
colorComponents.y * yColor +
colorComponents.z * zColor;
frag.color.a = 1.0;
frag.color.rgb = colorComponents.x * xColor +
colorComponents.y * yColor +
colorComponents.z * zColor;
frag.color.a = 1.0;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionViewSpace;
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionViewSpace;
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}

View File

@@ -34,13 +34,13 @@ uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
void main() {
vec4 positionViewSpace = modelViewTransform * vec4(in_position, 1.0);
vec4 positionClipSpace = projectionTransform * positionViewSpace;
vec4 positionScreenSpace = positionClipSpace;
positionScreenSpace.z = 0.0;
vs_positionModelSpace = in_position;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_positionViewSpace = positionViewSpace;
vec4 positionViewSpace = modelViewTransform * vec4(in_position, 1.0);
vec4 positionClipSpace = projectionTransform * positionViewSpace;
vec4 positionScreenSpace = positionClipSpace;
positionScreenSpace.z = 0.0;
vs_positionModelSpace = in_position;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_positionViewSpace = positionViewSpace;
gl_Position = positionScreenSpace;
gl_Position = positionScreenSpace;
}

View File

@@ -515,7 +515,6 @@ bool RenderableDUMeshes::readSpeckFile() {
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
if (file.eof()) {
@@ -534,16 +533,9 @@ bool RenderableDUMeshes::readSpeckFile() {
std::size_t found = line.find("mesh");
if (found == std::string::npos) {
//if (line.substr(0, 4) != "mesh") {
// we read a line that doesn't belong to the header, so we have to jump back
// before the beginning of the current line
//file.seekg(position);
//break;
continue;
}
else {
//if (line.substr(0, 4) == "mesh") {
// mesh lines are structured as follows:
// mesh -t texnum -c colorindex -s style {
// where textnum is the index of the texture;

View File

@@ -1112,22 +1112,9 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&
bool additiveBlending = false;
if (_pColorABlendEnabled) {
const auto renderer = global::renderEngine->rendererImplementation();
const bool usingFBufferRenderer = renderer ==
RenderEngine::RendererImplementation::Framebuffer;
const bool usingABufferRenderer = renderer ==
RenderEngine::RendererImplementation::ABuffer;
if (usingABufferRenderer) {
_shaderProgram->setUniform("usingAdditiveBlending", _pColorABlendEnabled);
}
additiveBlending = usingFBufferRenderer;
if (additiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
additiveBlending = true;
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
glBindVertexArray(_vertexArrayObject);

View File

@@ -56,6 +56,12 @@ namespace {
"This value determines the size of the font that is used to render the date."
};
constexpr openspace::properties::Property::PropertyInfo DisplayFormatInfo = {
"DisplayFormat",
"Display Format",
"Choosing the format in which the camera location is displayed"
};
constexpr openspace::properties::Property::PropertyInfo SignificantDigitsInfo = {
"SignificantDigits",
"Significant Digits",
@@ -69,6 +75,14 @@ namespace {
// [[codegen::verbatim(FontSizeInfo.description)]]
std::optional<float> fontSize;
enum class DisplayFormat {
DecimalDegrees,
DegreeMinuteSeconds
};
// [[codegen::verbatim(DisplayFormatInfo.description)]]
std::optional<DisplayFormat> displayFormat;
// [[codegen::verbatim(SignificantDigitsInfo.description)]]
std::optional<int> significantDigits;
};
@@ -86,6 +100,7 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation(
: DashboardItem(dictionary)
, _fontName(FontNameInfo, KeyFontMono)
, _fontSize(FontSizeInfo, DefaultFontSize, 10.f, 144.f, 1.f)
, _displayFormat(DisplayFormatInfo)
, _significantDigits(SignificantDigitsInfo, 4, 1, 12)
, _font(global::fontManager->font(KeyFontMono, 10))
{
@@ -104,20 +119,54 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation(
addProperty(_fontSize);
auto updateFormatString = [this]() {
using namespace fmt::literals;
_formatString = fmt::format(
"Position: {{:03.{0}f}}{{}}, {{:03.{0}f}}{{}} Altitude: {{:03.{0}f}} {{}}",
_significantDigits.value()
);
switch (_displayFormat.value()) {
case static_cast<int>(DisplayFormat::DecimalDegrees):
_formatString = fmt::format(
"Position: {{:03.{0}f}}, {{:03.{0}f}} "
"Altitude: {{:03.{0}f}} {{}}",
_significantDigits.value()
);
break;
case static_cast<int>(DisplayFormat::DegreeMinuteSeconds):
_formatString = fmt::format(
"Position: {{}}d {{}}' {{:03.{0}f}}\" {{}}, "
"{{}}d {{}}' {{:03.{0}f}}\" {{}} "
"Altitude: {{:03.{0}f}} {{}}",
_significantDigits.value()
);
break;
}
};
_displayFormat.addOptions({
{ static_cast<int>(DisplayFormat::DecimalDegrees), "Decimal Degrees" },
{ static_cast<int>(DisplayFormat::DegreeMinuteSeconds), "Degree Minute Seconds" }
});
_displayFormat.onChange(updateFormatString);
addProperty(_displayFormat);
if (p.displayFormat.has_value()) {
switch (*p.displayFormat) {
case Parameters::DisplayFormat::DecimalDegrees:
_displayFormat = static_cast<int>(DisplayFormat::DecimalDegrees);
break;
case Parameters::DisplayFormat::DegreeMinuteSeconds:
_displayFormat = static_cast<int>(DisplayFormat::DegreeMinuteSeconds);
break;
}
}
else {
_displayFormat = static_cast<int>(DisplayFormat::DecimalDegrees);
}
_significantDigits = p.significantDigits.value_or(_significantDigits);
_significantDigits.onChange(updateFormatString);
addProperty(_significantDigits);
updateFormatString();
_font = global::fontManager->font(_fontName, _fontSize);
_buffer.resize(128);
updateFormatString();
}
void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
@@ -149,12 +198,6 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
double lat = glm::degrees(geo2.lat);
double lon = glm::degrees(geo2.lon);
bool isNorth = lat > 0.0;
lat = std::abs(lat);
bool isEast = lon > 0.0;
lon = std::abs(lon);
double altitude = glm::length(
cameraPositionModelSpace - posHandle.centerToReferenceSurface
);
@@ -168,13 +211,49 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
std::pair<double, std::string> dist = simplifyDistance(altitude);
std::fill(_buffer.begin(), _buffer.end(), char(0));
char* end = fmt::format_to(
_buffer.data(),
_formatString.c_str(),
lat, isNorth ? "N" : "S",
lon, isEast ? "E" : "W",
dist.first, dist.second
);
char* end = nullptr;
switch (_displayFormat.value()) {
case static_cast<int>(DisplayFormat::DecimalDegrees):
{
end = fmt::format_to(
_buffer.data(),
_formatString, lat, lon, dist.first, dist.second
);
break;
}
case static_cast<int>(DisplayFormat::DegreeMinuteSeconds):
{
const bool isNorth = lat > 0.0;
lat = std::abs(lat);
const bool isEast = lon > 0.0;
lon = std::abs(lon);
const double latDeg = std::trunc(lat);
const double latDegRemainder = lat - latDeg;
const double latMin = std::trunc(latDegRemainder * 60.f);
const double latMinRemainder = latDegRemainder * 60.f - latMin;
const double latSec = latMinRemainder * 60.f;
const double lonDeg = std::trunc(lon);
const double lonDegRemainder = lon - lonDeg;
const double lonMin = std::trunc(lonDegRemainder * 60.f);
const double lonMinRemainder = lonDegRemainder * 60.f - lonMin;
const double lonSec = lonMinRemainder * 60.f;
end = fmt::format_to(
_buffer.data(),
_formatString,
latDeg, latMin, latSec, isNorth ? "N" : "S",
lonDeg, lonMin, lonSec, isEast ? "E" : "W",
dist.first, dist.second
);
break;
}
}
std::string_view text = std::string_view(_buffer.data(), end - _buffer.data());
RenderFont(*_font, penPosition, text);

View File

@@ -27,6 +27,7 @@
#include <openspace/rendering/dashboarditem.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/intproperty.h>
@@ -49,9 +50,15 @@ public:
static documentation::Documentation Documentation();
private:
enum class DisplayFormat {
DecimalDegrees = 0,
DegreeMinuteSeconds
};
properties::StringProperty _fontName;
properties::FloatProperty _fontSize;
properties::OptionProperty _displayFormat;
properties::IntProperty _significantDigits;
std::shared_ptr<ghoul::fontrendering::Font> _font;

View File

@@ -203,8 +203,8 @@ GlobeLabelsComponent::GlobeLabelsComponent()
: properties::PropertyOwner({ "Labels" })
, _enabled(EnabledInfo, false)
, _fontSize(FontSizeInfo, 30.f, 1.f, 300.f)
, _minMaxSize(MinMaxSizeInfo, glm::ivec2(1, 1000), glm::ivec2(1), glm::ivec2(1000))
, _size(SizeInfo, 2.5, 0, 30)
, _minMaxSize(MinMaxSizeInfo, glm::ivec2(1, 1000), glm::ivec2(1), glm::ivec2(1000))
, _heightOffset(HeightOffsetInfo, 100.f, 0.f, 10000.f)
, _color(ColorInfo, glm::vec3(1.f, 1.f, 0.f), glm::vec3(0.f), glm::vec3(1.f))
, _opacity(OpacityInfo, 1.f, 0.f, 1.f)

View File

@@ -156,7 +156,7 @@ void LayerManager::reset(bool includeDisabled) {
for (std::unique_ptr<LayerGroup>& layerGroup : _layerGroups) {
for (Layer* layer : layerGroup->layers()) {
if (layer->enabled() || includeDisabled) {
if ((layer->enabled() || includeDisabled) && layer->tileProvider()) {
tileprovider::reset(*layer->tileProvider());
}
}

View File

@@ -228,9 +228,7 @@ Tile tile(TextTileProvider& t, const TileIndex& tileIndex) {
// Keep track of defaultFBO and viewport to be able to reset state when done
GLint defaultFBO;
//GLint viewport[4];
defaultFBO = global::renderEngine->openglStateCache().defaultFramebuffer();
//glGetIntegerv(GL_VIEWPORT, viewport);
// Render to texture
glBindFramebuffer(GL_FRAMEBUFFER, t.fbo);
@@ -252,7 +250,6 @@ Tile tile(TextTileProvider& t, const TileIndex& tileIndex) {
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
global::renderEngine->openglStateCache().resetViewportState();
//glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
tile = Tile{ texture, std::nullopt, Tile::Status::OK };
t.tileCache->put(key, t.initData.hashKey, tile);

View File

@@ -40,7 +40,10 @@ namespace {
constexpr const int8_t LabelCacheFileVersion = 10;
constexpr const int8_t ColorCacheFileVersion = 10;
constexpr bool startsWith(std::string_view lhs, std::string_view rhs) noexcept {
bool startsWith(std::string lhs, std::string_view rhs) noexcept {
for (size_t i = 0; i < lhs.size(); i++) {
lhs[i] = static_cast<char>(tolower(lhs[i]));
}
return (rhs.size() <= lhs.size()) && (lhs.substr(0, rhs.size()) == rhs);
}
@@ -50,7 +53,7 @@ namespace {
// 3. Remove all spaces from the new beginning
// 4. Remove all spaces from the end
while (!line.empty() && line[0] == ' ') {
while (!line.empty() && (line[0] == ' ' || line[0] == '\t')) {
line = line.substr(1);
}
@@ -58,11 +61,11 @@ namespace {
line = line.substr(1);
}
while (!line.empty() && line[0] == ' ') {
while (!line.empty() && (line[0] == ' ' || line[0] == '\t')) {
line = line.substr(1);
}
while (!line.empty() && line.back() == ' ') {
while (!line.empty() && (line.back() == ' ' || line.back() == '\t')) {
line = line.substr(0, line.size() - 1);
}
}

View File

@@ -101,8 +101,8 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary)
: _target(TargetInfo)
, _observer(ObserverInfo)
, _frame(FrameInfo, DefaultReferenceFrame)
, _cachedFrame(DefaultReferenceFrame)
, _fixedDate(FixedDateInfo)
, _cachedFrame(DefaultReferenceFrame)
{
const Parameters p = codegen::bake<Parameters>(dictionary);

View File

@@ -74,10 +74,10 @@ namespace {
struct [[codegen::Dictionary(DashboardItemInstruments)]] Parameters {
// [[codegen::verbatim(ActiveColorInfo.description)]]
std::optional<glm::dvec3> activeColor [[codegen::color()]];
std::optional<glm::vec3> activeColor [[codegen::color()]];
// [[codegen::verbatim(FlashColorInfo.description)]]
std::optional<glm::dvec3> flashColor [[codegen::color()]];
std::optional<glm::vec3> flashColor [[codegen::color()]];
};
#include "dashboarditeminstruments_codegen.cpp"
} // namespace
@@ -105,8 +105,10 @@ DashboardItemInstruments::DashboardItemInstruments(const ghoul::Dictionary& dict
const Parameters p = codegen::bake<Parameters>(dictionary);
_activeColor.setViewOption(properties::Property::ViewOptions::Color);
_activeColor = p.activeColor.value_or(_activeColor);
addProperty(_activeColor);
_activeFlash.setViewOption(properties::Property::ViewOptions::Color);
_activeFlash = p.flashColor.value_or(_activeFlash);
addProperty(_activeFlash);
}

View File

@@ -42,8 +42,7 @@ namespace {
namespace openspace {
LabelParser::LabelParser(std::string name, std::string fileName,
const ghoul::Dictionary& dictionary)
LabelParser::LabelParser(std::string fileName, const ghoul::Dictionary& dictionary)
: _fileName(std::move(fileName))
{
// get the different instrument types

View File

@@ -31,8 +31,7 @@ namespace openspace {
class LabelParser : public SequenceParser {
public:
LabelParser(std::string name, std::string fileName,
const ghoul::Dictionary& translationDictionary);
LabelParser(std::string fileName, const ghoul::Dictionary& translationDictionary);
bool create() override;

View File

@@ -253,21 +253,13 @@ void ProjectionComponent::initialize(const std::string& identifier,
break;
case Parameters::Type::ImageSequence:
parsers.push_back(
std::make_unique<LabelParser>(
identifier,
std::move(source),
translations
)
std::make_unique<LabelParser>(std::move(source), translations)
);
break;
case Parameters::Type::Hybrid:
// first read labels
parsers.push_back(
std::make_unique<LabelParser>(
identifier,
std::move(source),
translations
)
std::make_unique<LabelParser>(std::move(source), translations)
);
if (p.eventFile.has_value()) {
@@ -297,11 +289,7 @@ void ProjectionComponent::initialize(const std::string& identifier,
case Parameters::Type::ImageAndInstrumentTimes:
{
parsers.push_back(
std::make_unique<LabelParser>(
identifier,
std::move(source),
translations
)
std::make_unique<LabelParser>(std::move(source), translations)
);
if (!p.timesSequence.has_value()) {

View File

@@ -228,7 +228,7 @@ bool HttpSynchronization::trySyncFromUrl(std::string listUrl) {
return !_shouldCancel;
}
std::lock_guard<std::mutex> guard(sizeDataMutex);
std::lock_guard guard(sizeDataMutex);
sizeData[line] = { p.totalBytesKnown, p.totalBytes, p.downloadedBytes };

View File

@@ -192,7 +192,7 @@ void UrlSynchronization::start() {
&startedAllDownloads, &nDownloads](HttpRequest::Progress p)
{
if (p.totalBytesKnown) {
std::lock_guard<std::mutex> guard(fileSizeMutex);
std::lock_guard guard(fileSizeMutex);
fileSizes[url] = p.totalBytes;
if (!_nTotalBytesKnown && startedAllDownloads &&

View File

@@ -236,9 +236,9 @@ GlobalRotation = { 0.0, 0.0, 0.0 }
MasterRotation = { 0.0, 0.0, 0.0 }
ScreenSpaceRotation = { 0.0, 0.0, 0.0 }
RenderingMethod = "Framebuffer"
OpenGLDebugContext = {
Activate = true,
PrintStacktrace = false,
FilterIdentifier = {
{ Type = "Other", Source = "API", Identifier = 131185 },
-- API_ID_RECOMPILE_FRAGMENT_SHADER performance warning has been generated. Fragment shader recompiled due to state change

View File

@@ -108,7 +108,6 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/properties/vector/vec3property.cpp
${OPENSPACE_BASE_DIR}/src/properties/vector/vec4property.cpp
${OPENSPACE_BASE_DIR}/src/query/query.cpp
${OPENSPACE_BASE_DIR}/src/rendering/abufferrenderer.cpp
${OPENSPACE_BASE_DIR}/src/rendering/dashboard.cpp
${OPENSPACE_BASE_DIR}/src/rendering/dashboard_lua.inl
${OPENSPACE_BASE_DIR}/src/rendering/dashboarditem.cpp
@@ -284,7 +283,6 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/properties/vector/vec3property.h
${OPENSPACE_BASE_DIR}/include/openspace/properties/vector/vec4property.h
${OPENSPACE_BASE_DIR}/include/openspace/query/query.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/abufferrenderer.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboard.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboarditem.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboardtextitem.h
@@ -298,7 +296,6 @@ set(OPENSPACE_HEADER
${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/screenspacerenderable.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/texturecomponent.h
@@ -464,10 +461,6 @@ endif ()
set_openspace_compile_settings(openspace-core)
target_link_libraries(openspace-core PUBLIC Ghoul spice external-curl)
if (OPENSPACE_WITH_ABUFFER_RENDERER)
target_compile_definitions(openspace-core PUBLIC "OPENSPACE_WITH_ABUFFER_RENDERER")
endif ()
# Just in case, create the bin directory
add_custom_command(
TARGET openspace-core

View File

@@ -161,15 +161,6 @@ namespace {
// resolution ('framebuffer'). This value defaults to 'window'
std::optional<Scaling> onScreenTextScaling;
// List from RenderEngine::setRendererFromString
enum class RenderingMethod {
Framebuffer,
ABuffer
};
// The renderer that is use after startup. The renderer 'ABuffer' requires support
// for at least OpenGL 4.3
std::optional<RenderingMethod> renderingMethod;
// Toggles whether the master in a multi-application setup should be rendering or
// just managing the state of the network. This is desired in cases where the
// master computer does not have the resources to render a scene
@@ -178,16 +169,16 @@ namespace {
// Applies a global view rotation. Use this to rotate the position of the focus
// node away from the default location on the screen. This setting persists even
// when a new focus node is selected. Defined using roll, pitch, yaw in radians
std::optional<glm::dvec3> globalRotation;
std::optional<glm::vec3> globalRotation;
// Applies a view rotation for only the master node, defined using roll, pitch yaw
// in radians. This can be used to compensate the master view direction for tilted
// display systems in clustered immersive environments
std::optional<glm::dvec3> masterRotation;
std::optional<glm::vec3> masterRotation;
// Applies a global rotation for all screenspace renderables. Defined using roll,
// pitch, yaw in radians
std::optional<glm::dvec3> screenSpaceRotation;
std::optional<glm::vec3> screenSpaceRotation;
// If this value is set to 'true' the ingame console is disabled, locking the
// system down against random access
@@ -232,6 +223,11 @@ namespace {
// Determines whether the OpenGL context should be a debug context
bool activate;
// If this is set to 'true', everytime an OpenGL error is logged, the full
// stacktrace leading to the error is printed as well, making debugging under
// production situations much easier
std::optional<bool> printStacktrace;
// Determines whether the OpenGL debug callbacks are performed synchronously.
// If set to 'true' the callbacks are in the same thread as the context and in
// the scope of the OpenGL function that triggered the message. The default
@@ -415,18 +411,6 @@ void parseLuaState(Configuration& configuration) {
c.globalRotation = p.globalRotation.value_or(c.globalRotation);
c.masterRotation = p.masterRotation.value_or(c.masterRotation);
c.screenSpaceRotation = p.screenSpaceRotation.value_or(c.screenSpaceRotation);
if (p.renderingMethod.has_value()) {
switch (*p.renderingMethod) {
case Parameters::RenderingMethod::Framebuffer:
c.renderingMethod = "Framebuffer";
break;
case Parameters::RenderingMethod::ABuffer:
c.renderingMethod = "ABuffer";
break;
default:
throw ghoul::MissingCaseException();
}
}
c.isConsoleDisabled = p.disableInGameConsole.value_or(c.isConsoleDisabled);
if (p.logging.has_value()) {
if (p.logging->logLevel.has_value()) {
@@ -499,6 +483,9 @@ void parseLuaState(Configuration& configuration) {
if (p.openGLDebugContext.has_value()) {
const Parameters::OpenGLDebugContext& l = *p.openGLDebugContext;
c.openGLDebugContext.isActive = l.activate;
c.openGLDebugContext.printStacktrace = l.printStacktrace.value_or(
c.openGLDebugContext.printStacktrace
);
c.openGLDebugContext.isSynchronous = l.synchronous.value_or(
c.openGLDebugContext.isSynchronous
);

View File

@@ -74,6 +74,7 @@
#include <ghoul/logging/logmanager.h>
#include <ghoul/logging/visualstudiooutputlog.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/misc/stacktrace.h>
#include <ghoul/misc/stringconversion.h>
#include <ghoul/opengl/debugcontext.h>
#include <ghoul/opengl/shaderpreprocessor.h>
@@ -560,6 +561,15 @@ void OpenSpaceEngine::initializeGL() {
default:
throw ghoul::MissingCaseException();
}
if (global::configuration->openGLDebugContext.printStacktrace) {
std::string stackString = "Stacktrace\n";
std::vector<std::string> stack = ghoul::stackTrace();
for (size_t i = 0; i < stack.size(); i++) {
stackString += fmt::format("{}: {}\n", i, stack[i]);
}
LDEBUGC(category, stackString);
}
};
ghoul::opengl::debug::setDebugCallback(callback);
}

View File

@@ -197,6 +197,7 @@ void NavigationHandler::deinitialize() {
}
void NavigationHandler::setFocusNode(SceneGraphNode* node) {
ghoul_assert(node, "Focus node must not be nullptr");
_orbitalNavigator.setFocusNode(node);
_camera->setPositionVec3(anchorNode()->worldPosition());
}

View File

@@ -199,7 +199,7 @@ void ParallelPeer::sendAuthentication() {
}
void ParallelPeer::queueInMessage(const ParallelConnection::Message& message) {
std::lock_guard<std::mutex> unqlock(_receiveBufferMutex);
std::lock_guard unqlock(_receiveBufferMutex);
_receiveBuffer.push_back(message);
}
@@ -221,7 +221,7 @@ void ParallelPeer::handleMessage(const ParallelConnection::Message& message) {
}
void ParallelPeer::analyzeTimeDifference(double messageTimestamp) {
std::lock_guard<std::mutex> latencyLock(_latencyMutex);
std::lock_guard latencyLock(_latencyMutex);
const double timeDiff = global::windowDelegate->applicationTime() - messageTimestamp;
if (_latencyDiffs.empty()) {
@@ -235,7 +235,7 @@ void ParallelPeer::analyzeTimeDifference(double messageTimestamp) {
}
double ParallelPeer::convertTimestamp(double messageTimestamp) {
std::lock_guard<std::mutex> latencyLock(_latencyMutex);
std::lock_guard latencyLock(_latencyMutex);
return messageTimestamp + _initialTimeDiff + _bufferTime;
}
@@ -495,7 +495,7 @@ void ParallelPeer::sendScript(std::string script) {
void ParallelPeer::resetTimeOffset() {
global::navigationHandler->keyframeNavigator().clearKeyframes();
global::timeManager->clearKeyframes();
std::lock_guard<std::mutex> latencyLock(_latencyMutex);
std::lock_guard latencyLock(_latencyMutex);
_latencyDiffs.clear();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1067,7 +1067,6 @@ void FramebufferRenderer::updateDeferredcastData() {
std::filesystem::path vsPath = caster->deferredcastVSPath();
std::filesystem::path fsPath = caster->deferredcastFSPath();
std::filesystem::path deferredShaderPath = caster->deferredcastPath();
ghoul::Dictionary dict;
dict.setValue("rendererData", _rendererData);
@@ -1086,17 +1085,10 @@ void FramebufferRenderer::updateDeferredcastData() {
_deferredcastPrograms[caster] = ghoul::opengl::ProgramObject::Build(
"Deferred " + std::to_string(data.id) + " raycast",
vsPath,
deferredShaderPath,
fsPath,
dict
);
_deferredcastPrograms[caster]->setIgnoreSubroutineUniformLocationError(
ghoul::opengl::ProgramObject::IgnoreError::Yes
);
_deferredcastPrograms[caster]->setIgnoreUniformLocationError(
ghoul::opengl::ProgramObject::IgnoreError::Yes
);
caster->initializeCachedVariables(*_deferredcastPrograms[caster]);
}
catch (ghoul::RuntimeError& e) {
@@ -1262,7 +1254,7 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac
TracyGpuZone("Apply TMO")
GLDebugGroup group("Apply TMO");
applyTMO(blackoutFactor, glm::ivec4(viewport[0], viewport[1], viewport[2], viewport[3]));
applyTMO(blackoutFactor, viewport);
}
if (_enableFXAA) {

View File

@@ -283,7 +283,7 @@ void LoadingScreen::render() {
glm::vec2 messageLl = glm::vec2(0.f);
glm::vec2 messageUr = glm::vec2(0.f);
if (_showMessage) {
std::lock_guard<std::mutex> guard(_messageMutex);
std::lock_guard guard(_messageMutex);
const glm::vec2 bboxMessage = _messageFont->boundingBox(_message);
@@ -298,7 +298,7 @@ void LoadingScreen::render() {
}
if (_showNodeNames) {
std::lock_guard<std::mutex> guard(_itemsMutex);
std::lock_guard guard(_itemsMutex);
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
@@ -485,7 +485,7 @@ void LoadingScreen::render() {
}
void LoadingScreen::postMessage(std::string message) {
std::lock_guard<std::mutex> guard(_messageMutex);
std::lock_guard guard(_messageMutex);
_message = std::move(message);
}
@@ -535,7 +535,7 @@ void LoadingScreen::updateItem(const std::string& itemIdentifier,
// also would create any of the text information
return;
}
std::lock_guard<std::mutex> guard(_itemsMutex);
std::lock_guard guard(_itemsMutex);
auto it = std::find_if(
_items.begin(),

View File

@@ -27,12 +27,12 @@
#include <openspace/openspace.h>
#include <openspace/engine/configuration.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/mission/missionmanager.h>
#include <openspace/rendering/abufferrenderer.h>
#include <openspace/rendering/dashboard.h>
#include <openspace/rendering/deferredcastermanager.h>
#include <openspace/rendering/helper.h>
@@ -302,57 +302,27 @@ RenderEngine::RenderEngine()
addProperty(_showVersionInfo);
addProperty(_showCameraInfo);
_enableFXAA.onChange([this]() {
if (_renderer) {
_renderer->enableFXAA(_enableFXAA);
}
});
_enableFXAA.onChange([this]() { _renderer.enableFXAA(_enableFXAA); });
addProperty(_enableFXAA);
_disableHDRPipeline.onChange([this]() {
if (_renderer) {
_renderer->setDisableHDR(_disableHDRPipeline);
}
_renderer.setDisableHDR(_disableHDRPipeline);
});
addProperty(_disableHDRPipeline);
_hdrExposure.onChange([this]() {
if (_renderer) {
_renderer->setHDRExposure(_hdrExposure);
}
});
_hdrExposure.onChange([this]() { _renderer.setHDRExposure(_hdrExposure); });
addProperty(_hdrExposure);
_gamma.onChange([this]() {
if (_renderer) {
_renderer->setGamma(_gamma);
}
});
_gamma.onChange([this]() { _renderer.setGamma(_gamma); });
addProperty(_gamma);
_hue.onChange([this]() {
if (_renderer) {
const float h = _hue / 360.f;
_renderer->setHue(h);
}
});
_hue.onChange([this]() { _renderer.setHue(_hue / 360.f); });
addProperty(_hue);
_saturation.onChange([this]() {
if (_renderer) {
_renderer->setSaturation(_saturation);
}
});
_saturation.onChange([this]() { _renderer.setSaturation(_saturation); });
addProperty(_saturation);
_value.onChange([this]() {
if (_renderer) {
_renderer->setValue(_value);
}
});
_value.onChange([this]() { _renderer.setValue(_value); });
addProperty(_value);
addProperty(_globalBlackOutFactor);
@@ -414,39 +384,16 @@ RenderEngine::RenderEngine()
RenderEngine::~RenderEngine() {} // NOLINT
void RenderEngine::setRendererFromString(const std::string& renderingMethod) {
ZoneScoped
_rendererImplementation = rendererFromString(renderingMethod);
std::unique_ptr<Renderer> newRenderer = nullptr;
switch (_rendererImplementation) {
case RendererImplementation::Framebuffer:
newRenderer = std::make_unique<FramebufferRenderer>();
break;
case RendererImplementation::ABuffer:
#ifdef OPENSPACE_WITH_ABUFFER_RENDERER
newRenderer = std::make_unique<ABufferRenderer>();
#endif // OPENSPACE_WITH_ABUFFER_RENDERER
break;
case RendererImplementation::Invalid:
LFATAL(fmt::format("Rendering method '{}' not available", renderingMethod));
return;
}
setRenderer(std::move(newRenderer));
}
void RenderEngine::initialize() {
ZoneScoped
// We have to perform these initializations here as the OsEng has not been initialized
// in our constructor
_globalRotation = static_cast<glm::vec3>(global::configuration->globalRotation);
_screenSpaceRotation =
static_cast<glm::vec3>(global::configuration->screenSpaceRotation);
_masterRotation = static_cast<glm::vec3>(global::configuration->masterRotation);
_globalRotation = global::configuration->globalRotation;
_screenSpaceRotation = global::configuration->screenSpaceRotation;
_masterRotation = global::configuration->masterRotation;
_disableMasterRendering = global::configuration->isRenderingOnMasterDisabled;
_screenshotUseDate = global::configuration->shouldUseScreenshotDate;
#ifdef GHOUL_USE_DEVIL
ghoul::io::TextureReader::ref().addReader(
@@ -499,8 +446,6 @@ void RenderEngine::initialize() {
);
}
}
_screenshotUseDate = global::configuration->shouldUseScreenshotDate;
}
void RenderEngine::initializeGL() {
@@ -508,21 +453,10 @@ void RenderEngine::initializeGL() {
LTRACE("RenderEngine::initializeGL(begin)");
std::string renderingMethod = global::configuration->renderingMethod;
if (renderingMethod == "ABuffer") {
using Version = ghoul::systemcapabilities::Version;
// The default rendering method has a requirement of OpenGL 4.3, so if we are
// below that, we will fall back to frame buffer operation
if (OpenGLCap.openGLVersion() < Version{ 4,3,0 }) {
LINFO("Falling back to framebuffer implementation due to OpenGL limitations");
renderingMethod = "Framebuffer";
}
}
LINFO(fmt::format("Setting renderer from string: {}", renderingMethod));
setRendererFromString(renderingMethod);
_renderer.setResolution(renderingResolution());
_renderer.enableFXAA(_enableFXAA);
_renderer.setHDRExposure(_hdrExposure);
_renderer.initialize();
// set the close clip plane and the far clip plane to extreme values while in
// development
@@ -532,45 +466,15 @@ void RenderEngine::initializeGL() {
// initialized window
_horizFieldOfView = static_cast<float>(global::windowDelegate->getHorizFieldOfView());
configuration::Configuration::FontSizes fontSize = global::configuration->fontSize;
{
ZoneScopedN("Font: FrameInfo")
TracyGpuZone("Font: FrameInfo")
_fontFrameInfo = global::fontManager->font(
KeyFontMono,
global::configuration->fontSize.frameInfo
);
}
{
ZoneScopedN("Font: Shutdown")
TracyGpuZone("Font: Shutdown")
_fontShutdown = global::fontManager->font(
KeyFontMono,
global::configuration->fontSize.shutdown
);
}
{
ZoneScopedN("Font: CameraInfo")
TracyGpuZone("Font: CameraInfo")
_fontCameraInfo = global::fontManager->font(
KeyFontMono,
global::configuration->fontSize.cameraInfo
);
}
{
ZoneScopedN("Font: VersionInfo")
TracyGpuZone("Font: VersionInfo")
_fontVersionInfo = global::fontManager->font(
KeyFontMono,
global::configuration->fontSize.versionInfo
);
}
{
ZoneScopedN("Font: Log")
TracyGpuZone("Font: Log")
_fontLog = global::fontManager->font(
KeyFontLight,
global::configuration->fontSize.log
);
ZoneScopedN("Fonts")
TracyGpuZone("Fonts")
_fontFrameInfo = global::fontManager->font(KeyFontMono, fontSize.frameInfo);
_fontShutdown = global::fontManager->font(KeyFontMono, fontSize.shutdown);
_fontCameraInfo = global::fontManager->font(KeyFontMono, fontSize.cameraInfo);
_fontVersionInfo = global::fontManager->font(KeyFontMono, fontSize.versionInfo);
_fontLog = global::fontManager->font(KeyFontLight, fontSize.log);
}
{
@@ -588,7 +492,7 @@ void RenderEngine::initializeGL() {
void RenderEngine::deinitializeGL() {
ZoneScoped
_renderer = nullptr;
_renderer.deinitialize();
}
void RenderEngine::updateScene() {
@@ -633,7 +537,7 @@ void RenderEngine::updateRenderer() {
const bool windowResized = global::windowDelegate->windowHasResized();
if (windowResized) {
_renderer->setResolution(renderingResolution());
_renderer.setResolution(renderingResolution());
using FR = ghoul::fontrendering::FontRenderer;
FR::defaultRenderer().setFramebufferSize(fontResolution());
@@ -643,7 +547,7 @@ void RenderEngine::updateRenderer() {
static_cast<float>(global::windowDelegate->getHorizFieldOfView());
}
_renderer->update();
_renderer.update();
}
void RenderEngine::updateScreenSpaceRenderables() {
@@ -737,15 +641,23 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat
_lastFrameTime = now + std::chrono::microseconds(static_cast<int>(delta));
}
const bool masterEnabled = delegate.isMaster() ? !_disableMasterRendering : true;
if (masterEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) {
_renderer->render(
const bool renderingEnabled = delegate.isMaster() ? !_disableMasterRendering : true;
if (renderingEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) {
_renderer.render(
_scene,
_camera,
_globalBlackOutFactor
);
}
// The CEF webbrowser fix has to be called at least once per frame and we are doing
// that in the renderer::render method. So if we disable the rendering, that fix is
// no longer called as we lose access to the Web UI. Since we are calling the fix
// many times anyway, we can just add one call to it here and not lose much
if (global::callback::webBrowserPerformanceHotfix) {
(*global::callback::webBrowserPerformanceHotfix)();
}
if (_showFrameInformation) {
ZoneScopedN("Show Frame Information")
@@ -776,7 +688,7 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat
RenderFont(*_fontFrameInfo, penPosition, res);
}
if (masterEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) {
if (renderingEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) {
ZoneScopedN("Render Screenspace Renderable")
std::vector<ScreenSpaceRenderable*> ssrs;
@@ -968,14 +880,6 @@ void RenderEngine::setCamera(Camera* camera) {
_camera = camera;
}
const Renderer& RenderEngine::renderer() const {
return *_renderer;
}
RenderEngine::RendererImplementation RenderEngine::rendererImplementation() const {
return _rendererImplementation;
}
ghoul::opengl::OpenGLStateCache& RenderEngine::openglStateCache() {
if (_openglStateCache == nullptr) {
_openglStateCache = ghoul::opengl::OpenGLStateCache::instance();
@@ -1127,39 +1031,10 @@ unsigned int RenderEngine::latestScreenshotNumber() const {
return _latestScreenshotNumber;
}
void RenderEngine::preRaycast(ghoul::opengl::ProgramObject& programObject) {
_renderer->preRaycast(programObject);
}
void RenderEngine::postRaycast(ghoul::opengl::ProgramObject& programObject) {
_renderer->postRaycast(programObject);
}
void RenderEngine::setRenderer(std::unique_ptr<Renderer> renderer) {
ZoneScoped
if (_renderer) {
_renderer->deinitialize();
}
_renderer = std::move(renderer);
_renderer->setResolution(renderingResolution());
_renderer->enableFXAA(_enableFXAA);
_renderer->setHDRExposure(_hdrExposure);
_renderer->initialize();
}
scripting::LuaLibrary RenderEngine::luaLibrary() {
return {
"",
{
{
"setRenderer",
&luascriptfunctions::setRenderer,
{},
"string",
"Sets the renderer (ABuffer or FrameBuffer)"
},
{
"addScreenSpaceRenderable",
&luascriptfunctions::addScreenSpaceRenderable,
@@ -1266,24 +1141,6 @@ std::vector<ScreenSpaceRenderable*> RenderEngine::screenSpaceRenderables() const
return res;
}
RenderEngine::RendererImplementation RenderEngine::rendererFromString(
const std::string& renderingMethod) const
{
const std::map<std::string, RenderEngine::RendererImplementation> RenderingMethods = {
#ifdef OPENSPACE_WITH_ABUFFER_RENDERER
{ "ABuffer", RendererImplementation::ABuffer },
#endif // OPENSPACE_WITH_ABUFFER_RENDERER
{ "Framebuffer", RendererImplementation::Framebuffer }
};
if (RenderingMethods.find(renderingMethod) != RenderingMethods.end()) {
return RenderingMethods.at(renderingMethod);
}
else {
return RendererImplementation::Invalid;
}
}
void RenderEngine::renderCameraInformation() {
ZoneScoped

View File

@@ -26,30 +26,6 @@
namespace openspace::luascriptfunctions {
/**
* \ingroup LuaScripts
* setRenderer(string):
* Set renderer
*/
int setRenderer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setRenderer");
const int type = lua_type(L, -1);
if (type != LUA_TSTRING) {
return ghoul::lua::luaError(L, "Expected argument of type 'string'");
}
const std::string& renderer = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
global::renderEngine->setRendererFromString(renderer);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int addScreenSpaceRenderable(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addScreenSpaceRenderable");

View File

@@ -25,6 +25,7 @@
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/navigationhandler.h>
#include <ghoul/misc/defer.h>
#include <ghoul/misc/easing.h>
@@ -654,7 +655,12 @@ int addSceneGraphNode(lua_State* L) {
global::renderEngine->scene()->initializeNode(node);
}
catch (const documentation::SpecificationError& e) {
LERRORC("Scene", ghoul::to_string(e.result));
std::string cat =
d.hasValue<std::string>("Identifier") ?
d.value<std::string>("Identifier") :
"Scene";
LERRORC(cat, ghoul::to_string(e.result));
return ghoul::lua::luaError(
L,
fmt::format("Error loading scene graph node: {}", e.what())
@@ -698,6 +704,15 @@ int removeSceneGraphNode(lua_State* L) {
// Remove the node and all its children
std::function<void(SceneGraphNode*)> removeNode =
[&removeNode](SceneGraphNode* localNode) {
if (localNode == global::navigationHandler->anchorNode()) {
global::navigationHandler->setFocusNode(sceneGraph()->root());
}
if (localNode == global::navigationHandler->orbitalNavigator().aimNode()) {
global::navigationHandler->orbitalNavigator().setAimNode("");
}
std::vector<SceneGraphNode*> children = localNode->children();
ghoul::mm_unique_ptr<SceneGraphNode> n = localNode->parent()->detachChild(
@@ -847,6 +862,15 @@ int removeSceneGraphNodesFromRegex(lua_State* L) {
// Remove all marked nodes
std::function<void(SceneGraphNode*)> removeNode =
[&removeNode, &markedList](SceneGraphNode* localNode) {
if (localNode == global::navigationHandler->anchorNode()) {
global::navigationHandler->setFocusNode(sceneGraph()->root());
}
if (localNode == global::navigationHandler->orbitalNavigator().aimNode()) {
global::navigationHandler->orbitalNavigator().setAimNode("");
}
std::vector<SceneGraphNode*> children = localNode->children();
ghoul::mm_unique_ptr<SceneGraphNode> n = localNode->parent()->detachChild(

View File

@@ -66,7 +66,7 @@ void MultiThreadedSceneInitializer::initializeNode(SceneGraphNode* node) {
}
node->initialize();
std::lock_guard<std::mutex> g(_mutex);
std::lock_guard g(_mutex);
_initializedNodes.push_back(node);
_initializingNodes.erase(node);
@@ -94,19 +94,19 @@ void MultiThreadedSceneInitializer::initializeNode(SceneGraphNode* node) {
);
}
std::lock_guard<std::mutex> g(_mutex);
std::lock_guard g(_mutex);
_initializingNodes.insert(node);
_threadPool.enqueue(initFunction);
}
std::vector<SceneGraphNode*> MultiThreadedSceneInitializer::takeInitializedNodes() {
std::lock_guard<std::mutex> g(_mutex);
std::lock_guard g(_mutex);
std::vector<SceneGraphNode*> nodes = std::move(_initializedNodes);
return nodes;
}
bool MultiThreadedSceneInitializer::isInitializing() const {
std::lock_guard<std::mutex> g(_mutex);
std::lock_guard g(_mutex);
return !_initializingNodes.empty();
}

View File

@@ -423,6 +423,13 @@ void ScriptEngine::addBaseLibrary() {
"string",
"Checks whether the provided file exists."
},
{
"readFile",
&luascriptfunctions::readFile,
{},
"string",
"Reads a file from disk and return its contents"
},
{
"directoryExists",
&luascriptfunctions::directoryExists,
@@ -687,7 +694,7 @@ void ScriptEngine::preSync(bool isMaster) {
return;
}
std::lock_guard<std::mutex> guard(_slaveScriptsMutex);
std::lock_guard guard(_slaveScriptsMutex);
while (!_incomingScripts.empty()) {
QueueItem item = std::move(_incomingScripts.front());
_incomingScripts.pop();
@@ -721,7 +728,7 @@ void ScriptEngine::encode(SyncBuffer* syncBuffer) {
void ScriptEngine::decode(SyncBuffer* syncBuffer) {
ZoneScoped
std::lock_guard<std::mutex> guard(_slaveScriptsMutex);
std::lock_guard guard(_slaveScriptsMutex);
size_t nScripts;
syncBuffer->decode(nScripts);
@@ -750,7 +757,7 @@ void ScriptEngine::postSync(bool isMaster) {
}
}
else {
std::lock_guard<std::mutex> guard(_slaveScriptsMutex);
std::lock_guard guard(_slaveScriptsMutex);
while (!_slaveScriptQueue.empty()) {
try {
runScript(_slaveScriptQueue.front());

View File

@@ -30,37 +30,11 @@
namespace openspace::luascriptfunctions {
int printInternal(ghoul::logging::LogLevel level, lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::printInternal");
using ghoul::lua::luaTypeToString;
const int type = lua_type(L, 1);
switch (type) {
case LUA_TNONE:
case LUA_TLIGHTUSERDATA:
case LUA_TTABLE:
case LUA_TFUNCTION:
case LUA_TUSERDATA:
case LUA_TTHREAD:
log(
level,
"print",
fmt::format("Function parameter was of type '{}'", luaTypeToString(type))
);
break;
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
log(level, "print", std::to_string(ghoul::lua::value<bool>(L, 1)));
break;
case LUA_TNUMBER:
log(level, "print", std::to_string(ghoul::lua::value<double>(L, 1)));
break;
case LUA_TSTRING:
log(level, "print", ghoul::lua::value<std::string>(L, 1));
break;
const int nArguments = lua_gettop(L);
for (int i = 1; i <= nArguments; i++) {
log(level, "print", ghoul::lua::luaValueToString(L, i));
}
lua_pop(L, 1);
lua_pop(L, nArguments);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
@@ -197,6 +171,32 @@ int fileExists(lua_State* L) {
return 1;
}
/**
* \ingroup LuaScripts
* readFile(string):
* Reads a file from disk and return its contents
*/
int readFile(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::readFile");
const std::string& file = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
std::filesystem::path p = absPath(file);
if (!std::filesystem::is_regular_file(p)) {
return ghoul::lua::luaError(L, fmt::format("Could not open file {}", file));
}
std::ifstream f(p);
std::stringstream buffer;
buffer << f.rdbuf();
ghoul::lua::push(L, buffer.str());
return 1;
}
/**
* \ingroup LuaScripts
* directoryExists(string):

View File

@@ -42,14 +42,15 @@ Camera::Camera(const Camera& o)
{}
void Camera::setPositionVec3(glm::dvec3 pos) {
std::lock_guard<std::mutex> _lock(_mutex);
_position = std::move(pos);
_cachedCombinedViewMatrix.isDirty = true;
if (!glm::any(glm::isnan(pos))) {
std::lock_guard _lock(_mutex);
_position = std::move(pos);
_cachedCombinedViewMatrix.isDirty = true;
}
}
void Camera::setRotation(glm::dquat rotation) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_rotation = std::move(rotation);
_cachedViewDirection.isDirty = true;
_cachedLookupVector.isDirty = true;
@@ -58,14 +59,14 @@ void Camera::setRotation(glm::dquat rotation) {
}
void Camera::setScaling(float scaling) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_scaling = scaling;
_cachedViewScaleMatrix.isDirty = true;
_cachedCombinedViewMatrix.isDirty = true;
}
void Camera::setMaxFov(float fov) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_maxFov = fov;
_cachedSinMaxFov.isDirty = true;
}
@@ -75,7 +76,7 @@ void Camera::setParent(SceneGraphNode* parent) {
}
void Camera::rotate(glm::dquat rotation) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_rotation = std::move(rotation) * static_cast<glm::dquat>(_rotation);
_cachedViewDirection.isDirty = true;
@@ -224,20 +225,20 @@ Camera::SgctInternal::SgctInternal(const SgctInternal& o)
{}
void Camera::SgctInternal::setSceneMatrix(glm::mat4 sceneMatrix) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_sceneMatrix = std::move(sceneMatrix);
}
void Camera::SgctInternal::setViewMatrix(glm::mat4 viewMatrix) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_viewMatrix = std::move(viewMatrix);
_cachedViewProjectionMatrix.isDirty = true;
}
void Camera::SgctInternal::setProjectionMatrix(glm::mat4 projectionMatrix) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_projectionMatrix = std::move(projectionMatrix);
_cachedViewProjectionMatrix.isDirty = true;
@@ -257,7 +258,7 @@ const glm::mat4& Camera::SgctInternal::projectionMatrix() const {
const glm::mat4& Camera::SgctInternal::viewProjectionMatrix() const {
//if (_cachedViewProjectionMatrix.isDirty) {
std::lock_guard<std::mutex> _lock(_mutex);
std::lock_guard _lock(_mutex);
_cachedViewProjectionMatrix.datum = _projectionMatrix * _viewMatrix;
_cachedViewProjectionMatrix.isDirty = false;
//}

View File

@@ -32,9 +32,11 @@ namespace {
constexpr const char* _loggerCat = "Coordinateconversion";
// J2000 Galactic reference frame
constexpr double A0 = glm::radians(192.8595); // Equatorial coordinates of the Galactic north pole
// Equatorial coordinates of the Galactic north pole
constexpr double A0 = glm::radians(192.8595);
constexpr double D0 = glm::radians(27.1284);
constexpr double L0 = glm::radians(122.9320); // Galactic longitude of the equatorial north pole
// Galactic longitude of the equatorial north pole
constexpr double L0 = glm::radians(122.9320);
void parseString(const std::string& str, int& hoursOrDegrees, int& minutes,
double& seconds)

View File

@@ -245,7 +245,7 @@ AsyncHttpDownload::AsyncHttpDownload(AsyncHttpDownload&& d)
{}
void AsyncHttpDownload::start(HttpRequest::RequestOptions opt) {
std::lock_guard<std::mutex> guard(_stateChangeMutex);
std::lock_guard guard(_stateChangeMutex);
if (hasStarted()) {
return;
}
@@ -286,7 +286,7 @@ void AsyncHttpDownload::download(HttpRequest::RequestOptions opt) {
_httpRequest.onProgress([this](HttpRequest::Progress p) {
// Return a non-zero value to cancel download
// if onProgress returns false.
//std::lock_guard<std::mutex> guard(_mutex);
//std::lock_guard guard(_mutex);
const bool shouldContinue = callOnProgress(p);
if (!shouldContinue) {
return 1;

View File

@@ -41,7 +41,7 @@ SynchronizationWatcher::WatchHandle SynchronizationWatcher::watchSynchronization
[this, synchronization, watchHandle, cb = std::move(callback)]
(ResourceSynchronization::State state)
{
std::lock_guard<std::mutex> g(_mutex);
std::lock_guard g(_mutex);
_pendingNotifications.push_back({ synchronization, state, watchHandle, cb });
}
);

View File

@@ -315,19 +315,19 @@ TEST_CASE("Configuration: isRenderingOnMasterDisabled", "[configuration]") {
TEST_CASE("Configuration: globalRotation", "[configuration]") {
constexpr const char Extra[] = R"(GlobalRotation = { 1.0, 2.0, 3.0 })";
const Configuration c = loadConfiguration("globalRotation", Extra);
CHECK(c.globalRotation == glm::dvec3(1.0, 2.0, 3.0));
CHECK(c.globalRotation == glm::vec3(1.0, 2.0, 3.0));
}
TEST_CASE("Configuration: screenSpaceRotation", "[configuration]") {
constexpr const char Extra[] = R"(ScreenSpaceRotation = { 1.0, 2.0, 3.0 })";
const Configuration c = loadConfiguration("screenSpaceRotation", Extra);
CHECK(c.screenSpaceRotation == glm::dvec3(1.0, 2.0, 3.0));
CHECK(c.screenSpaceRotation == glm::vec3(1.0, 2.0, 3.0));
}
TEST_CASE("Configuration: masterRotation", "[configuration]") {
constexpr const char Extra[] = R"(MasterRotation = { 1.0, 2.0, 3.0 })";
const Configuration c = loadConfiguration("masterRotation", Extra);
CHECK(c.masterRotation == glm::dvec3(1.0, 2.0, 3.0));
CHECK(c.masterRotation == glm::vec3(1.0, 2.0, 3.0));
}
TEST_CASE("Configuration: isConsoleDisabled", "[configuration]") {
@@ -381,12 +381,6 @@ ModuleConfigurations = {
}
}
TEST_CASE("Configuration: renderingMethod", "[configuration]") {
constexpr const char Extra[] = R"(RenderingMethod = "ABuffer")";
const Configuration c = loadConfiguration("renderingMethod", Extra);
CHECK(c.renderingMethod == "ABuffer");
}
TEST_CASE("Configuration: openGLDebugContext", "[configuration]") {
Configuration defaultConf;
{
@@ -394,6 +388,7 @@ TEST_CASE("Configuration: openGLDebugContext", "[configuration]") {
constexpr const char Extra[] = R"(OpenGLDebugContext = { Activate = true })";
const Configuration c = loadConfiguration("openGLDebugContext1", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(c.openGLDebugContext.printStacktrace == false);
CHECK(
c.openGLDebugContext.isSynchronous ==
defaultConf.openGLDebugContext.isSynchronous
@@ -457,6 +452,7 @@ OpenGLDebugContext = { Activate = true, Synchronous = true }
constexpr const char Extra[] = R"(
OpenGLDebugContext = {
Activate = true,
PrintStacktrace = true,
FilterIdentifier = {
{ Identifier = 1, Source = "API", Type = "Error" },
{ Identifier = 2, Source = "Window System", Type = "Deprecated" },
@@ -473,6 +469,7 @@ OpenGLDebugContext = {
)";
const Configuration c = loadConfiguration("openGLDebugContext3", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(c.openGLDebugContext.printStacktrace == true);
CHECK(
c.openGLDebugContext.isSynchronous ==
defaultConf.openGLDebugContext.isSynchronous
@@ -521,6 +518,7 @@ OpenGLDebugContext = { Activate = true, FilterSeverity = { "High", "Medium" } }
)";
const Configuration c = loadConfiguration("openGLDebugContext4", Extra);
CHECK(c.openGLDebugContext.isActive == true);
CHECK(c.openGLDebugContext.printStacktrace == false);
CHECK(
c.openGLDebugContext.isSynchronous ==
defaultConf.openGLDebugContext.isSynchronous