Merge commit 'a9661f681e115ebed096f5d25343dc99aad0f33f' into feature/data-management

# Conflicts:
#	data/scene/default.scene
#	data/scene/digitaluniverse/abell/abell.mod
#	data/scene/digitaluniverse/backgroundradiation/backgroundradiation.mod
#	data/scene/digitaluniverse/constellations/constellations.mod
#	data/scene/digitaluniverse/grids/grids.mod
#	data/scene/digitaluniverse/quasars/quasars.mod
#	data/scene/digitaluniverse/sloandss/sloandss.mod
#	data/scene/digitaluniverse/tully/tully.data
#	data/scene/digitaluniverse/tully/tully.mod
#	data/scene/earth/earth.mod
#	data/scene/grids/grids.mod
#	data/scene/mars/mars.mod
#	data/scene/milkyway/digitaluniverse/digitaluniverse.mod
#	data/scene/moon/moon.mod
#	data/scene/satellites/tle/geo.txt
#	data/scene/satellites/tle/gps-ops.txt
#	data/scene/satellites/tle/stations.txt
#	modules/imgui/src/renderproperties.cpp
#	modules/sync/ext/libtorrent
#	openspace.cfg
#	src/rendering/renderengine.cpp
This commit is contained in:
Alexander Bock
2017-12-27 19:39:40 +01:00
162 changed files with 14060 additions and 569 deletions
+76
View File
@@ -0,0 +1,76 @@
#########################################################################################
# #
# OpenSpace #
# #
# Copyright (c) 2014-2017 #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
# software and associated documentation files (the "Software"), to deal in the Software #
# without restriction, including without limitation the rights to use, copy, modify, #
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the following #
# conditions: #
# #
# The above copyright notice and this permission notice shall be included in all copies #
# or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A #
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT #
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF #
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE #
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
#########################################################################################
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/atmospheredeferredcaster.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableatmosphere.h
)
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/atmospheredeferredcaster.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableatmosphere.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})
set(SHADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/shaders/atmosphere_common.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/atmosphere_deferred_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/atmosphere_deferred_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaE_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaE_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaJ_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaJ_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaJ_calc_gs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaS_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaS_calc_gs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaS_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaS_sup_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaS_sup_calc_gs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/deltaS_sup_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/inScattering_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/inScattering_calc_gs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/inScattering_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/inScattering_sup_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/inScattering_sup_calc_gs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/inScattering_sup_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/irradiance_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/irradiance_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/irradiance_final_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/irradiance_final_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/irradiance_sup_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/irradiance_sup_calc_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/transmittance_calc_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/transmittance_calc_fs.glsl
)
source_group("Shader Files" FILES ${SHADER_FILES})
create_new_module(
"Atmosphere"
atmosphere_module
STATIC
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
)
+45
View File
@@ -0,0 +1,45 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/atmosphere/atmospheremodule.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/misc/assert.h>
#include <openspace/rendering/renderable.h>
#include <modules/atmosphere/rendering/renderableatmosphere.h>
namespace openspace {
AtmosphereModule::AtmosphereModule() :
OpenSpaceModule("Atmosphere")
{}
void AtmosphereModule::internalInitialize() {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "No renderable factory existed");
fRenderable->registerClass<RenderableAtmosphere>("RenderableAtmosphere");
}
} // namespace openspace
+41
View File
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* 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_MODULE_ATMOSPHERE___ATMOSPHERE_MODULE___H__
#define __OPENSPACE_MODULE_ATMOSPHERE___ATMOSPHERE_MODULE___H__
#include <openspace/util/openspacemodule.h>
#include <openspace/properties/scalar/floatproperty.h>
namespace openspace {
class AtmosphereModule : public OpenSpaceModule {
public:
AtmosphereModule();
void internalInitialize() override;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_ATMOSPHERE___ATMOSPHERE_MODULE___H__
+1
View File
@@ -0,0 +1 @@
#set (DEFAULT_MODULE ON)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,187 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* 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_MODULE_ATMOSPHERE___ATMOSPHEREDEFERREDCASTER___H__
#define __OPENSPACE_MODULE_ATMOSPHERE___ATMOSPHEREDEFERREDCASTER___H__
#include <ghoul/glm.h>
#include <string>
#include <vector>
#include <openspace/rendering/deferredcaster.h>
#include <ghoul/opengl/textureunit.h>
//#include <modules/atmosphere/rendering/renderableatmosphere.h>
namespace ghoul::opengl {
class Texture;
class ProgramObject;
} // namespace ghoul::opengl
namespace openspace {
struct RenderData;
struct DeferredcastData;
struct ShadowConfiguration;
class AtmosphereDeferredcaster : public Deferredcaster {
public:
AtmosphereDeferredcaster();
virtual ~AtmosphereDeferredcaster() = default;
void initialize();
void deinitialize();
void preRaycast(const RenderData& renderData, const DeferredcastData& deferredData,
ghoul::opengl::ProgramObject& program) override;
void postRaycast(const RenderData& renderData, const DeferredcastData& deferredData,
ghoul::opengl::ProgramObject& program) override;
std::string deferredcastPath() const override;
std::string deferredcastVSPath() const override;
std::string deferredcastFSPath() const override;
std::string helperPath() const override;
void preCalculateAtmosphereParam();
void setModelTransform(const glm::dmat4 &transform);
void setTime(double time);
void setAtmosphereRadius(float atmRadius);
void setPlanetRadius(float planetRadius);
void setPlanetAverageGroundReflectance(float averageGReflectance);
void setPlanetGroundRadianceEmittion(float groundRadianceEmittion);
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(const glm::vec3& rayScattCoeff);
void setOzoneExtinctionCoefficients(const glm::vec3& ozoneExtCoeff);
void setMieScatteringCoefficients(const glm::vec3& mieScattCoeff);
void setMieExtinctionCoefficients(const glm::vec3& mieExtCoeff);
void setEllipsoidRadii(const glm::dvec3& radii);
void setShadowConfigArray(const std::vector<ShadowConfiguration>& shadowConfigArray);
void setHardShadows(bool enabled);
void enableSunFollowing(bool enable);
void setPrecalculationTextureScale(float preCalculatedTexturesScale);
void enablePrecalculationTexturesSaving();
private:
void loadComputationPrograms();
void unloadComputationPrograms();
void createComputationTextures();
void deleteComputationTextures();
void deleteUnusedComputationTextures();
void executeCalculations(GLuint quadCalcVAO, GLenum drawBuffers[1],
GLsizei vertexSize);
void resetAtmosphereTextures();
void createRenderQuad(GLuint* vao, GLuint* vbo, GLfloat size);
void step3DTexture(std::unique_ptr<ghoul::opengl::ProgramObject>& shaderProg,
int layer, bool doCalc = true);
void checkFrameBufferState(const std::string& codePosition) const;
void loadAtmosphereDataIntoShaderProgram(
std::unique_ptr<ghoul::opengl::ProgramObject> & shaderProg
);
void renderQuadForCalc(GLuint vao, GLsizei numberOfVertices);
void saveTextureToPPMFile(GLenum color_buffer_attachment, const std::string& fileName,
int width, int height) const;
bool isAtmosphereInFrustum(const double* MVMatrix, const glm::dvec3& position,
double radius) const;
const double DISTANCE_CULLING = 1e10;
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;
std::unique_ptr<ghoul::opengl::ProgramObject> _atmosphereProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _deferredAtmosphereProgramObject;
GLuint _transmittanceTableTexture;
GLuint _irradianceTableTexture;
GLuint _inScatteringTableTexture;
GLuint _deltaETableTexture;
GLuint _deltaSRayleighTableTexture;
GLuint _deltaSMieTableTexture;
GLuint _deltaJTableTexture;
GLuint _atmosphereTexture;
ghoul::opengl::TextureUnit _transmittanceTableTextureUnit;
ghoul::opengl::TextureUnit _irradianceTableTextureUnit;
ghoul::opengl::TextureUnit _inScatteringTableTextureUnit;
// Atmosphere Data
bool _atmosphereCalculated;
bool _ozoneEnabled;
bool _sunFollowingCameraEnabled;
float _atmosphereRadius;
float _atmospherePlanetRadius;
float _planetAverageGroundReflectance;
float _planetGroundRadianceEmittion;
float _rayleighHeightScale;
float _ozoneHeightScale;
float _mieHeightScale;
float _miePhaseConstant;
float _sunRadianceIntensity;
glm::vec3 _rayleighScatteringCoeff;
glm::vec3 _ozoneExtinctionCoeff;
glm::vec3 _mieScatteringCoeff;
glm::vec3 _mieExtinctionCoeff;
glm::dvec3 _ellipsoidRadii;
// Atmosphere Textures Dimmensions
int _transmittance_table_width;
int _transmittance_table_height;
int _irradiance_table_width;
int _irradiance_table_height;
int _delta_e_table_width;
int _delta_e_table_height;
int _r_samples;
int _mu_samples;
int _mu_s_samples;
int _nu_samples;
glm::dmat4 _modelTransform;
double _time;
// Eclipse Shadows
std::vector<ShadowConfiguration> _shadowConfArray;
bool _hardShadowsEnabled;
// Atmosphere Debugging
float _calculationTextureScale;
bool _saveCalculationTextures;
};
} // openspace
#endif // __OPENSPACE_MODULE_ATMOSPHERE___ATMOSPHEREDEFERREDCASTER___H__
@@ -0,0 +1,763 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/atmosphere/rendering/renderableatmosphere.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <modules/space/rendering/planetgeometry.h>
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#include <openspace/scene/scenegraphnode.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/misc/assert.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/misc/invariants.h>
#include <openspace/rendering/deferredcastermanager.h>
#include <modules/atmosphere/rendering/atmospheredeferredcaster.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/renderer.h>
#include <glm/gtx/string_cast.hpp>
#include <memory>
#include <fstream>
#define _USE_MATH_DEFINES
#include <math.h>
namespace {
static const char* _loggerCat = "RenderableAtmosphere";
const char* keyShadowGroup = "ShadowGroup";
const char* keyShadowSource = "Source";
const char* keyShadowCaster = "Caster";
const char* keyAtmosphere = "Atmosphere";
const char* keyAtmosphereRadius = "AtmosphereRadius";
const char* keyPlanetRadius = "PlanetRadius";
const char* keyAverageGroundReflectance = "PlanetAverageGroundReflectance";
const char* keyRayleigh = "Rayleigh";
const char* keyRayleighHeightScale = "H_R";
const char* keyOzone = "Ozone";
const char* keyOzoneHeightScale = "H_O";
const char* keyMie = "Mie";
const char* keyMieHeightScale = "H_M";
const char* keyMiePhaseConstant = "G";
const char* keyImage = "Image";
const char* keyToneMappingOp = "ToneMapping";
const char* keyATMDebug = "Debug";
const char* keyTextureScale = "PreCalculatedTextureScale";
const char* keySaveTextures = "SaveCalculatedTextures";
static const openspace::properties::Property::PropertyInfo AtmosphereHeightInfo = {
"atmmosphereHeight",
"Atmosphere Height (KM)",
"The thickness of the atmosphere in Km"
};
static const openspace::properties::Property::PropertyInfo AverageGroundReflectanceInfo = {
"AverageGroundReflectance",
"Average Ground Reflectance (%)",
"Average percentage of light reflected by the ground during the pre-calculation phase"
};
static const openspace::properties::Property::PropertyInfo GroundRadianceEmittioninfo = {
"GroundRadianceEmittion",
"Percentage of initial radiance emitted from ground",
"Multiplier of the ground radiance color during the rendering phase"
};
static const openspace::properties::Property::PropertyInfo RayleighHeightScaleInfo = {
"RayleighHeightScale",
"Rayleigh Scale Height (KM)",
"It is the vertical distance over which the density and pressure fall by a constant factor"
};
static const openspace::properties::Property::PropertyInfo RayleighScatteringCoeffXInfo = {
"RayleighScatteringCoeffX",
"Rayleigh Scattering Coeff X (x10e-3)",
"Rayleigh sea-level scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo RayleighScatteringCoeffYInfo = {
"RayleighScatteringCoeffY",
"Rayleigh Scattering Coeff Y (x10e-3)",
"Rayleigh sea-level scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo RayleighScatteringCoeffZInfo = {
"RayleighScatteringCoeffZ",
"Rayleigh Scattering Coeff Z (x10e-3)",
"Rayleigh sea-level scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo OzoneLayerInfo = {
"Ozone",
"Ozone Layer Enabled",
"Enables/Disable Ozone Layer during pre-calculation phase"
};
static const openspace::properties::Property::PropertyInfo OzoneHeightScaleInfo = {
"OzoneLayerHeightScale",
"Ozone Scale Height (KM)",
"It is the vertical distance over which the density and pressure fall by a constant factor"
};
static const openspace::properties::Property::PropertyInfo OzoneLayerCoeffXInfo = {
"OzoneLayerCoeffX",
"Ozone Layer Extinction Coeff X (x10e-5)",
"Ozone scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo OzoneLayerCoeffYInfo = {
"OzoneLayerCoeffY",
"Ozone Layer Extinction Coeff Y (x10e-5)",
"Ozone scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo OzoneLayerCoeffZInfo = {
"OzoneLayerCoeffZ",
"Ozone Layer Extinction Coeff Z (x10e-5)",
"Ozone scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo MieHeightScaleInfo = {
"MieHeightScale",
"Mie Scale Height (KM)",
"It is the vertical distance over which the density and pressure fall by a constant factor"
};
static const openspace::properties::Property::PropertyInfo MieScatteringCoeffXInfo = {
"MieScatteringCoeffX",
"Mie Scattering Coeff X (x10e-3)",
"Mie sea-level scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo MieScatteringCoeffYInfo = {
"MieScatteringCoeffY",
"Mie Scattering Coeff Y (x10e-3)",
"Mie sea-level scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo MieScatteringCoeffZInfo = {
"MieScatteringCoeffZ",
"Mie Scattering Coeff Z (x10e-3)",
"Mie sea-level scattering coefficients in meters"
};
static const openspace::properties::Property::PropertyInfo MieScatteringExtinctionPropCoeffInfo = {
"MieScatteringExtinctionPropCoefficient",
"Mie Scattering/Extinction Proportion Coefficient (%)",
"Mie Scattering/Extinction Proportion Coefficient (%)"
};
static const openspace::properties::Property::PropertyInfo MieAsymmetricFactorGInfo = {
"MieAsymmetricFactorG",
"Mie Asymmetric Factor G",
"Averaging of the scattering angle over a high number of scattering events"
};
static const openspace::properties::Property::PropertyInfo SunIntensityInfo = {
"SunIntensity",
"Sun Intensity",
"Unitless for now"
};
static const openspace::properties::Property::PropertyInfo AtmosphereExposureInfo = {
"HdrExposure",
"Atmosphere Exposure",
"Constant to controls the exposure of the radiance range"
};
static const openspace::properties::Property::PropertyInfo AtmosphereGammaInfo = {
"Gamma",
"Gamma Correction",
"Gamma Correction"
};
static const openspace::properties::Property::PropertyInfo EnableSunOnCameraPositionInfo = {
"SunFollowingCamera",
"Enable Sun On Camera Position",
"When selected the Sun is artificially positioned behind the observer all times"
};
static const openspace::properties::Property::PropertyInfo EclipseHardShadowsInfo = {
"EclipseHardShadowsInfo",
"Enable Hard Shadows for Eclipses",
"Enable/Disables hard shadows through the atmosphere"
};
} // namespace
namespace openspace {
documentation::Documentation RenderableAtmosphere::Documentation() {
using namespace documentation;
return {
"RenderableAtmosphere",
"atmosphere_renderable_atmosphere",
{ /*
{
keyAtmosphereRadius,
new ReferencingVerifier("atmosphere"),
"Specifies the atmosphere's height in this RenderableAtmosphere.",
Optional::No
},
{
KeyShading,
new BoolVerifier,
"Specifies whether the atmosphere should be rendered shaded by the Sun. If "
"this value is 'false', any existing night texture will not be used. "
"This value defaults to 'true'.",
Optional::Yes
}
*/
}
};
}
RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _atmosphereHeightP(AtmosphereHeightInfo, 60.0f, 0.1f, 99.0f)
, _groundAverageReflectanceP(AverageGroundReflectanceInfo, 0.1f, 0.0f, 1.0f)
, _groundRadianceEmittionP(GroundRadianceEmittioninfo, 0.3f, 0.0f, 1.0f)
, _rayleighHeightScaleP(RayleighHeightScaleInfo, 8.0f, 0.1f, 20.0f)
, _rayleighScatteringCoeffXP(RayleighScatteringCoeffXInfo, 1.0f, 0.01f, 100.0f)
, _rayleighScatteringCoeffYP(RayleighScatteringCoeffYInfo, 1.0f, 0.01f, 100.0f)
, _rayleighScatteringCoeffZP(RayleighScatteringCoeffZInfo, 1.0f, 0.01f, 100.0f)
, _ozoneEnabledP(OzoneLayerInfo, true)
, _ozoneHeightScaleP(OzoneHeightScaleInfo, 8.0f, 0.1f, 20.0f)
, _ozoneCoeffXP(OzoneLayerCoeffXInfo, 3.426f, 0.01f, 100.0f)
, _ozoneCoeffYP(OzoneLayerCoeffYInfo, 8.298f, 0.01f, 100.0f)
, _ozoneCoeffZP(OzoneLayerCoeffZInfo, 0.356f, 0.01f, 100.0f)
, _mieHeightScaleP(MieHeightScaleInfo, 1.2f, 0.1f, 20.0f)
, _mieScatteringCoeffXP(MieScatteringCoeffXInfo, 4.0f, 0.01f, 1000.0f)
, _mieScatteringCoeffYP(MieScatteringCoeffYInfo, 4.0f, 0.01f, 1000.0f)
, _mieScatteringCoeffZP(MieScatteringCoeffZInfo, 4.0f, 0.01f, 1000.0f)
, _mieScatteringExtinctionPropCoefficientP(MieScatteringExtinctionPropCoeffInfo, 0.9f, 0.01f, 1.0f)
, _mieAsymmetricFactorGP(MieAsymmetricFactorGInfo, 0.85f, -1.0f, 1.0f)
, _sunIntensityP(SunIntensityInfo, 50.0f, 0.1f, 1000.0f)
, _sunFollowingCameraEnabledP(EnableSunOnCameraPositionInfo, false)
, _hardShadowsEnabledP(EclipseHardShadowsInfo, false)
, _atmosphereEnabled(false)
, _ozoneLayerEnabled(false)
, _sunFollowingCameraEnabled(false)
, _atmosphereRadius(0.f)
, _atmospherePlanetRadius(0.f)
, _planetAverageGroundReflectance(0.f)
, _planetGroundRadianceEmittion(0.f)
, _rayleighHeightScale(0.f)
, _ozoneHeightScale(0.f)
, _mieHeightScale(0.f)
, _miePhaseConstant(0.f)
, _sunRadianceIntensity(50.f)
, _mieExtinctionCoeff(glm::vec3(0.f))
, _rayleighScatteringCoeff(glm::vec3(0.f))
, _ozoneExtinctionCoeff(glm::vec3(0.f))
, _mieScatteringCoeff(glm::vec3(0.f))
, _saveCalculationsToTexture(false)
, _preCalculatedTexturesScale(1.0)
, _shadowEnabled(false)
, _hardShadows(false)
{
ghoul_precondition(
dictionary.hasKeyAndValue<std::string>(SceneGraphNode::KeyName),
"RenderableAtmosphere needs the name to be specified"
);
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableAtmosphere"
);
const std::string name = dictionary.value<std::string>(SceneGraphNode::KeyName);
//================================================================
//======== Reads Shadow (Eclipses) Entries in mod file ===========
//================================================================
ghoul::Dictionary shadowDictionary;
bool success = dictionary.getValue(keyShadowGroup, shadowDictionary);
bool disableShadows = false;
if (success) {
std::vector<std::pair<std::string, double>> sourceArray;
unsigned int sourceCounter = 1;
while (success) {
std::string sourceName;
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Name", sourceName);
if (success) {
double sourceRadius;
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Radius", sourceRadius);
if (success) {
sourceArray.emplace_back(sourceName, sourceRadius);
}
else {
LWARNING("No Radius value expecified for Shadow Source Name "
<< sourceName << " from " << name
<< " planet.\nDisabling shadows for this planet.");
disableShadows = true;
break;
}
}
sourceCounter++;
}
if (!disableShadows && !sourceArray.empty()) {
success = true;
std::vector<std::pair<std::string, double>> casterArray;
unsigned int casterCounter = 1;
while (success) {
std::string casterName;
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Name", casterName);
if (success) {
double casterRadius;
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Radius", casterRadius);
if (success) {
casterArray.emplace_back(casterName, casterRadius);
}
else {
LWARNING("No Radius value expecified for Shadow Caster Name "
<< casterName << " from " << name
<< " planet.\nDisabling shadows for this planet.");
disableShadows = true;
break;
}
}
casterCounter++;
}
if (!disableShadows && (!sourceArray.empty() && !casterArray.empty())) {
for (const auto & source : sourceArray) {
for (const auto & caster : casterArray) {
ShadowConfiguration sc;
sc.source = source;
sc.caster = caster;
_shadowConfArray.push_back(sc);
}
}
_shadowEnabled = true;
}
}
}
//================================================================
//========== Reads Atmosphere Entries from mod file ==============
//================================================================
bool errorReadingAtmosphereData = false;
ghoul::Dictionary atmosphereDictionary;
success = dictionary.getValue(keyAtmosphere, atmosphereDictionary);
if (success) {
if (!atmosphereDictionary.getValue(keyAtmosphereRadius, _atmosphereRadius)) {
errorReadingAtmosphereData = true;
LWARNING("No Atmosphere Radius value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!atmosphereDictionary.getValue(keyPlanetRadius, _atmospherePlanetRadius)) {
errorReadingAtmosphereData = true;
LWARNING("No Planet Radius value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!atmosphereDictionary.getValue(keyAverageGroundReflectance, _planetAverageGroundReflectance)) {
errorReadingAtmosphereData = true;
LWARNING("No Average Atmosphere Ground Reflectance value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!atmosphereDictionary.getValue(GroundRadianceEmittioninfo.identifier, _planetGroundRadianceEmittion)) {
errorReadingAtmosphereData = true;
LWARNING("No Ground Radiance Emitted percentage value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
ghoul::Dictionary rayleighDictionary;
success = atmosphereDictionary.getValue(keyRayleigh, rayleighDictionary);
if (success) {
// Not using right now.
glm::vec3 rayleighWavelengths;
success = rayleighDictionary.getValue("Coefficients.Wavelengths", rayleighWavelengths);
if (!rayleighDictionary.getValue("Coefficients.Scattering", _rayleighScatteringCoeff)) {
errorReadingAtmosphereData = true;
LWARNING("No Rayleigh Scattering parameters expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!rayleighDictionary.getValue(keyRayleighHeightScale, _rayleighHeightScale)) {
errorReadingAtmosphereData = true;
LWARNING("No Rayleigh Height Scale value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
}
else {
errorReadingAtmosphereData = true;
LWARNING("No Rayleigh parameters expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
ghoul::Dictionary ozoneDictionary;
success = atmosphereDictionary.getValue(keyOzone, ozoneDictionary);
if (success) {
_ozoneLayerEnabled = true;
if (!ozoneDictionary.getValue(keyOzoneHeightScale, _ozoneHeightScale)) {
_ozoneLayerEnabled = false;
}
if (!ozoneDictionary.getValue("Coefficients.Extinction", _ozoneExtinctionCoeff)) {
_ozoneLayerEnabled = false;
}
}
else {
_ozoneLayerEnabled = false;
}
ghoul::Dictionary mieDictionary;
success = atmosphereDictionary.getValue(keyMie, mieDictionary);
if (success) {
if (!mieDictionary.getValue(keyMieHeightScale, _mieHeightScale)) {
errorReadingAtmosphereData = true;
LWARNING("No Mie Height Scale value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!mieDictionary.getValue("Coefficients.Scattering", _mieScatteringCoeff)) {
errorReadingAtmosphereData = true;
LWARNING("No Mie Scattering parameters expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!mieDictionary.getValue("Coefficients.Extinction", _mieExtinctionCoeff)) {
errorReadingAtmosphereData = true;
LWARNING("No Mie Extinction parameters expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
if (!mieDictionary.getValue(keyMiePhaseConstant, _miePhaseConstant)) {
errorReadingAtmosphereData = true;
LWARNING("No Mie Phase Constant value expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
}
else {
errorReadingAtmosphereData = true;
LWARNING("No Mie parameters expecified for Atmosphere Effects of "
<< name << " planet.\nDisabling atmosphere effects for this planet.");
}
ghoul::Dictionary ImageDictionary;
success = atmosphereDictionary.getValue(keyImage, ImageDictionary);
if (success) {
if (ImageDictionary.getValue(keyToneMappingOp, _preCalculatedTexturesScale)) {
LDEBUG("Atmosphere Texture Scaled to " << _preCalculatedTexturesScale);
}
}
ghoul::Dictionary debugDictionary;
success = atmosphereDictionary.getValue(keyATMDebug, debugDictionary);
if (success) {
if (debugDictionary.getValue(keyTextureScale, _preCalculatedTexturesScale)) {
LDEBUG("Atmosphere Texture Scaled to " << _preCalculatedTexturesScale);
}
if (debugDictionary.getValue(keySaveTextures, _saveCalculationsToTexture)) {
LDEBUG("Saving Precalculated Atmosphere Textures.");
}
}
if (!errorReadingAtmosphereData) {
_atmosphereEnabled = true;
//========================================================
//============== Atmosphere Properties ===================
//========================================================
auto updateAtmosphere = [this]() { updateAtmosphereParameters(); };
_atmosphereHeightP =_atmosphereRadius - _atmospherePlanetRadius;
_atmosphereHeightP.onChange(updateAtmosphere);
addProperty(_atmosphereHeightP);
_groundAverageReflectanceP = _planetAverageGroundReflectance;
_groundAverageReflectanceP.onChange(updateAtmosphere);
addProperty(_groundAverageReflectanceP);
_groundRadianceEmittionP = _planetGroundRadianceEmittion;
_groundRadianceEmittionP.onChange(updateAtmosphere);
addProperty(_groundRadianceEmittionP);
_rayleighHeightScaleP = _rayleighHeightScale;
_rayleighHeightScaleP.onChange(updateAtmosphere);
addProperty(_rayleighHeightScaleP);
_rayleighScatteringCoeffXP = _rayleighScatteringCoeff.x * 1000.0f;
_rayleighScatteringCoeffXP.onChange(updateAtmosphere);
addProperty(_rayleighScatteringCoeffXP);
_rayleighScatteringCoeffYP = _rayleighScatteringCoeff.y * 1000.0f;
_rayleighScatteringCoeffYP.onChange(updateAtmosphere);
addProperty(_rayleighScatteringCoeffYP);
_rayleighScatteringCoeffZP = _rayleighScatteringCoeff.z * 1000.0f;
_rayleighScatteringCoeffZP.onChange(updateAtmosphere);
addProperty(_rayleighScatteringCoeffZP);
_ozoneEnabledP = _ozoneLayerEnabled;
_ozoneEnabledP.onChange(updateAtmosphere);
addProperty(_ozoneEnabledP);
_ozoneHeightScaleP = _ozoneHeightScale;
_ozoneHeightScaleP.onChange(updateAtmosphere);
addProperty(_ozoneHeightScaleP);
_ozoneCoeffXP = _ozoneExtinctionCoeff.x * 100000.0f;
_ozoneCoeffXP.onChange(updateAtmosphere);
addProperty(_ozoneCoeffXP);
_ozoneCoeffYP = _ozoneExtinctionCoeff.y * 100000.0f;
_ozoneCoeffYP.onChange(updateAtmosphere);
addProperty(_ozoneCoeffYP);
_ozoneCoeffZP = _ozoneExtinctionCoeff.z * 100000.0f;
_ozoneCoeffZP.onChange(updateAtmosphere);
addProperty(_ozoneCoeffZP);
_mieHeightScaleP = _mieHeightScale;
_mieHeightScaleP.onChange(updateAtmosphere);
addProperty(_mieHeightScaleP);
_mieScatteringCoeffXP = _mieScatteringCoeff.x * 1000.0f;
_mieScatteringCoeffXP.onChange(updateAtmosphere);
addProperty(_mieScatteringCoeffXP);
_mieScatteringCoeffYP = _mieScatteringCoeff.y * 1000.0f;
_mieScatteringCoeffYP.onChange(updateAtmosphere);
addProperty(_mieScatteringCoeffYP);
_mieScatteringCoeffZP = _mieScatteringCoeff.z * 1000.0f;
_mieScatteringCoeffZP.onChange(updateAtmosphere);
addProperty(_mieScatteringCoeffZP);
_mieScatteringExtinctionPropCoefficientP =
_mieScatteringCoeff.x / _mieExtinctionCoeff.x;
_mieScatteringExtinctionPropCoefficientP.onChange(updateAtmosphere);
addProperty(_mieScatteringExtinctionPropCoefficientP);
_mieAsymmetricFactorGP = _miePhaseConstant;
_mieAsymmetricFactorGP.onChange(updateAtmosphere);
addProperty(_mieAsymmetricFactorGP);
_sunIntensityP = _sunRadianceIntensity;
_sunIntensityP.onChange(updateAtmosphere);
addProperty(_sunIntensityP);
_sunFollowingCameraEnabledP = _sunFollowingCameraEnabled;
_sunFollowingCameraEnabledP.onChange(updateAtmosphere);
addProperty(_sunFollowingCameraEnabledP);
_hardShadowsEnabledP = _hardShadows;
_hardShadowsEnabledP.onChange(updateAtmosphere);
if (_shadowEnabled) {
addProperty(_hardShadowsEnabledP);
}
}
}
}
void RenderableAtmosphere::deinitialize() {
if (_deferredcaster) {
OsEng.renderEngine().deferredcasterManager().detachDeferredcaster(
*_deferredcaster
);
_deferredcaster = nullptr;
}
}
void RenderableAtmosphere::initializeGL() {
if (_atmosphereEnabled) {
_deferredcaster = std::make_unique<AtmosphereDeferredcaster>();
if (_deferredcaster) {
_deferredcaster->setAtmosphereRadius(_atmosphereRadius);
_deferredcaster->setPlanetRadius(_atmospherePlanetRadius);
_deferredcaster->setPlanetAverageGroundReflectance(
_planetAverageGroundReflectance
);
_deferredcaster->setPlanetGroundRadianceEmittion(
_planetGroundRadianceEmittion
);
_deferredcaster->setRayleighHeightScale(_rayleighHeightScale);
_deferredcaster->enableOzone(_ozoneLayerEnabled);
_deferredcaster->setOzoneHeightScale(_ozoneHeightScale);
_deferredcaster->setMieHeightScale(_mieHeightScale);
_deferredcaster->setMiePhaseConstant(_miePhaseConstant);
_deferredcaster->setSunRadianceIntensity(_sunRadianceIntensity);
_deferredcaster->setRayleighScatteringCoefficients(_rayleighScatteringCoeff);
_deferredcaster->setOzoneExtinctionCoefficients(_ozoneExtinctionCoeff);
_deferredcaster->setMieScatteringCoefficients(_mieScatteringCoeff);
_deferredcaster->setMieExtinctionCoefficients(_mieExtinctionCoeff);
// TODO: Fix the ellipsoid nature of the renderable globe (JCC)
//_deferredcaster->setEllipsoidRadii(_ellipsoid.radii());
_deferredcaster->enableSunFollowing(_sunFollowingCameraEnabled);
_deferredcaster->setPrecalculationTextureScale(_preCalculatedTexturesScale);
if (_saveCalculationsToTexture)
_deferredcaster->enablePrecalculationTexturesSaving();
if (_shadowEnabled) {
_deferredcaster->setShadowConfigArray(_shadowConfArray);
_deferredcaster->setHardShadows(_hardShadows);
}
_deferredcaster->initialize();
}
OsEng.renderEngine().deferredcasterManager().attachDeferredcaster(
*_deferredcaster
);
}
return;
}
void RenderableAtmosphere::deinitializeGL() {
}
bool RenderableAtmosphere::isReady() const {
bool ready = true;
ready &= (_deferredcaster != nullptr);
return ready;
}
glm::dmat4 RenderableAtmosphere::computeModelTransformMatrix(
const openspace::TransformData& transformData)
{
// scale the planet to appropriate size since the planet is a unit sphere
return glm::translate(glm::dmat4(1.0), transformData.translation) * // Translation
glm::dmat4(transformData.rotation) * // Spice rotation
glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(transformData.scale)));
}
void RenderableAtmosphere::render(const RenderData& data, RendererTasks& renderTask) {
if (_atmosphereEnabled) {
DeferredcasterTask task{ _deferredcaster.get(), data };
renderTask.deferredcasterTasks.push_back(task);
}
}
void RenderableAtmosphere::update(const UpdateData& data) {
_stateMatrix = data.modelTransform.rotation;
if (_deferredcaster) {
_deferredcaster->setTime(data.time.j2000Seconds());
glm::dmat4 modelTransform = computeModelTransformMatrix(data.modelTransform);
_deferredcaster->setModelTransform(modelTransform);
}
}
void RenderableAtmosphere::updateAtmosphereParameters() {
bool executeComputation = true;
if (_sunRadianceIntensity != _sunIntensityP ||
_planetGroundRadianceEmittion != _groundRadianceEmittionP ||
_sunFollowingCameraEnabled != _sunFollowingCameraEnabledP ||
_hardShadows != _hardShadowsEnabledP) {
executeComputation = false;
}
_atmosphereRadius = _atmospherePlanetRadius + _atmosphereHeightP;
_planetAverageGroundReflectance = _groundAverageReflectanceP;
_planetGroundRadianceEmittion = _groundRadianceEmittionP;
_rayleighHeightScale = _rayleighHeightScaleP;
_rayleighScatteringCoeff = glm::vec3(
_rayleighScatteringCoeffXP * 0.001f,
_rayleighScatteringCoeffYP * 0.001f,
_rayleighScatteringCoeffZP * 0.001f
);
_ozoneLayerEnabled = _ozoneEnabledP;
_ozoneHeightScale = _ozoneHeightScaleP;
_ozoneExtinctionCoeff = glm::vec3(_ozoneCoeffXP.value() * 0.00001f,
_ozoneCoeffYP.value() * 0.00001f,
_ozoneCoeffZP.value() * 0.00001f);
_mieHeightScale = _mieHeightScaleP;
_mieScatteringCoeff = glm::vec3(
_mieScatteringCoeffXP * 0.001f,
_mieScatteringCoeffYP * 0.001f,
_mieScatteringCoeffZP * 0.001f
);
_mieExtinctionCoeff = _mieScatteringCoeff * (1.0f /
static_cast<float>(_mieScatteringExtinctionPropCoefficientP));
_miePhaseConstant = _mieAsymmetricFactorGP;
_sunRadianceIntensity = _sunIntensityP;
_sunFollowingCameraEnabled = _sunFollowingCameraEnabledP;
_hardShadows = _hardShadowsEnabledP;
if (_deferredcaster) {
_deferredcaster->setAtmosphereRadius(_atmosphereRadius);
_deferredcaster->setPlanetRadius(_atmospherePlanetRadius);
_deferredcaster->setPlanetAverageGroundReflectance(
_planetAverageGroundReflectance
);
_deferredcaster->setPlanetGroundRadianceEmittion(_planetGroundRadianceEmittion);
_deferredcaster->setRayleighHeightScale(_rayleighHeightScale);
_deferredcaster->enableOzone(_ozoneLayerEnabled);
_deferredcaster->setOzoneHeightScale(_ozoneHeightScale);
_deferredcaster->setMieHeightScale(_mieHeightScale);
_deferredcaster->setMiePhaseConstant(_miePhaseConstant);
_deferredcaster->setSunRadianceIntensity(_sunRadianceIntensity);
_deferredcaster->setRayleighScatteringCoefficients(_rayleighScatteringCoeff);
_deferredcaster->setOzoneExtinctionCoefficients(_ozoneExtinctionCoeff);
_deferredcaster->setMieScatteringCoefficients(_mieScatteringCoeff);
_deferredcaster->setMieExtinctionCoefficients(_mieExtinctionCoeff);
_deferredcaster->enableSunFollowing(_sunFollowingCameraEnabled);
//_deferredcaster->setEllipsoidRadii(_ellipsoid.radii());
if (_shadowEnabled) {
_deferredcaster->setHardShadows(_hardShadows);
}
if (executeComputation) {
_deferredcaster->preCalculateAtmosphereParam();
}
}
}
} // namespace openspace
@@ -0,0 +1,153 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* 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_MODULE_SPACE___RENDERABLEATMOSPHERE___H__
#define __OPENSPACE_MODULE_SPACE___RENDERABLEATMOSPHERE___H__
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/opengl/textureunit.h>
#include <modules/atmosphere/rendering/atmospheredeferredcaster.h>
#include <memory>
#include <string>
#include <vector>
namespace ghoul::opengl {
class ProgramObject;
class Texture;
}
namespace openspace {
class AtmosphereDeferredcaster;
struct TransformData;
// Shadow structure
struct ShadowConfiguration {
std::pair<std::string, double> source;
std::pair<std::string, double> caster;
};
struct ShadowRenderingStruct {
double xu,
xp;
double rs,
rc;
glm::dvec3 sourceCasterVec;
glm::dvec3 casterPositionVec;
bool isShadowing;
};
namespace planetgeometry {
class PlanetGeometry;
}
namespace documentation { struct Documentation; }
namespace planetgeometry { class PlanetGeometry; }
class RenderableAtmosphere : public Renderable {
public:
RenderableAtmosphere(const ghoul::Dictionary& dictionary);
void deinitialize() override;
void initializeGL() override;
void deinitializeGL() override;
bool isReady() const override;
void render(const RenderData& data, RendererTasks& rendererTask) override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
private:
glm::dmat4 computeModelTransformMatrix(const openspace::TransformData& transformData);
void updateAtmosphereParameters();
properties::FloatProperty _atmosphereHeightP;
properties::FloatProperty _groundAverageReflectanceP;
properties::FloatProperty _groundRadianceEmittionP;
properties::FloatProperty _rayleighHeightScaleP;
properties::FloatProperty _rayleighScatteringCoeffXP;
properties::FloatProperty _rayleighScatteringCoeffYP;
properties::FloatProperty _rayleighScatteringCoeffZP;
properties::BoolProperty _ozoneEnabledP;
properties::FloatProperty _ozoneHeightScaleP;
properties::FloatProperty _ozoneCoeffXP;
properties::FloatProperty _ozoneCoeffYP;
properties::FloatProperty _ozoneCoeffZP;
properties::FloatProperty _mieHeightScaleP;
properties::FloatProperty _mieScatteringCoeffXP;
properties::FloatProperty _mieScatteringCoeffYP;
properties::FloatProperty _mieScatteringCoeffZP;
properties::FloatProperty _mieScatteringExtinctionPropCoefficientP;
properties::FloatProperty _mieAsymmetricFactorGP;
properties::FloatProperty _sunIntensityP;
properties::BoolProperty _sunFollowingCameraEnabledP;
properties::BoolProperty _hardShadowsEnabledP;
bool _atmosphereEnabled;
bool _ozoneLayerEnabled;
bool _sunFollowingCameraEnabled;
float _atmosphereRadius;
float _atmospherePlanetRadius;
float _planetAverageGroundReflectance;
float _planetGroundRadianceEmittion;
float _rayleighHeightScale;
float _ozoneHeightScale;
float _mieHeightScale;
float _miePhaseConstant;
float _sunRadianceIntensity;
glm::vec3 _mieExtinctionCoeff;
glm::vec3 _rayleighScatteringCoeff;
glm::vec3 _ozoneExtinctionCoeff;
glm::vec3 _mieScatteringCoeff;
// Atmosphere Debug
bool _saveCalculationsToTexture;
float _preCalculatedTexturesScale;
std::unique_ptr<AtmosphereDeferredcaster> _deferredcaster;
bool _shadowEnabled;
bool _hardShadows;
glm::dmat3 _stateMatrix;
std::vector<ShadowConfiguration> _shadowConfArray;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_SPACE___RENDERABLEATMOSPHERE___H__
@@ -0,0 +1,375 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* 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. *
****************************************************************************************/
/*****************************************************************************************
* Modified parts of the code (4D texture mechanism, analytical transmittance etc) *
* from Eric Bruneton is used in the following code. *
****************************************************************************************/
/**
* Precomputed Atmospheric Scattering
* Copyright (c) 2008 INRIA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF 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 groundRadianceEmittion;
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 int TRANSMITTANCE_W;
uniform int TRANSMITTANCE_H;
uniform int SKY_W;
uniform int SKY_H;
uniform int OTHER_TEXTURES_W;
uniform int OTHER_TEXTURES_H;
uniform int SAMPLES_R;
uniform int SAMPLES_MU;
uniform int SAMPLES_MU_S;
uniform int SAMPLES_NU;
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;
uniform sampler2D transmittanceTexture;
float opticalDepth(const float H, const float r, const float mu, const float d) {
float a = sqrt((0.5/H)*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/H*(d/(2.0*r)+mu)));
return sqrt((6.2831*H)*r) * exp((Rg-r)/H) * (x + dot(y, vec2(1.0, -1.0)));
}
vec3 analyticTransmittance(const float r, const float mu, const float d) {
if (ozoneLayerEnabled) {
return exp(-betaRayleigh * opticalDepth(HR, r, mu, d) -
betaOzoneExtinction * (0.0000006) * opticalDepth(HO, r, mu, d) -
betaMieExtinction * opticalDepth(HM, r, mu, d));
} else {
return exp(-betaRayleigh * opticalDepth(HR, r, mu, d) -
betaMieExtinction * opticalDepth(HM, r, mu, d));
}
}
vec3 irradiance(sampler2D sampler, const float r, const float muSun) {
float u_r = (r - Rg) / (Rt - Rg);
float u_muSun = (muSun + 0.2) / (1.0 + 0.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 comming from the opposite direction of the view direction,
// here the vector v or viewDirection.
// Rg is the planet radius and Rt the atmosphere radius.
//--- Calculate the distance of the ray starting at x (height r)
// until the planet's ground 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(const float r, const float mu) {
// 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.
// cosine law
float atmRadiusEps = Rt + ATM_EPSILON;
float rayDistanceAtmosphere = -r * mu +
sqrt(r * r * (mu * mu - 1.0f) + atmRadiusEps * atmRadiusEps);
float delta = r * r * (mu * mu - 1.0f) + Rg * Rg;
// Ray may be hitting ground
if (delta >= 0.0f) {
float rayDistanceGround = -r * mu - sqrt(delta);
if (rayDistanceGround >= 0.0f) {
return min(rayDistanceAtmosphere, rayDistanceGround);
}
}
return rayDistanceAtmosphere;
}
//-- Given the window's fragment coordinates, for a defined
// viewport, gives back the interpolated r e [Rg, Rt] and
// mu e [-1, 1] --
// r := height of starting point vect(x)
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
void unmappingRAndMu(out float r, out float mu) {
float u_mu = gl_FragCoord.x / float(TRANSMITTANCE_W);
float u_r = gl_FragCoord.y / float(TRANSMITTANCE_H);
// In the paper u_r^2 = (r^2-Rg^2)/(Rt^2-Rg^2)
// So, extracting r from u_r in the above equation:
//r = sqrt( Rg * Rg + (u_r * u_r) * (Rt * Rt - Rg * Rg) );
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.
// One must remember that mu is defined from 0 to PI/2 + epsillon.
mu = -0.15f + tan(1.5f * u_mu) / tan(1.5f) * (1.0f + 0.15f);
}
//-- Given the windows's fragment coordinates, for a defined view port,
// gives back the interpolated r e [Rg, Rt] and muSun e [-1, 1] --
// r := height of starting point vect(x)
// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v))
void unmappingRAndMuSun(out float r, out float muSun) {
// See Bruneton and Colliene to understand the mapping.
muSun = -0.2f + (gl_FragCoord.x - 0.5f) / (float(OTHER_TEXTURES_W) - 1.0f) * (1.0f + 0.2f);
//r = Rg + (gl_FragCoord.y - 0.5f) / (float(OTHER_TEXTURES_H) - 1.0f) * (Rt - Rg);
r = Rg + (gl_FragCoord.y - 0.5f) / (float(OTHER_TEXTURES_H) ) * (Rt - Rg);
}
//-- Given the windows's fragment coordinates, for a defined view port,
// gives back the interpolated r e [Rg, Rt] and muSun e [-1, 1] for the
// Irradiance deltaE texture table --
// r := height of starting point vect(x)
// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v))
void unmappingRAndMuSunIrradiance(out float r, out float muSun) {
// See Bruneton and Colliene to understand the mapping.
muSun = -0.2f + (gl_FragCoord.x - 0.5f) / (float(SKY_W) - 1.0f) * (1.0f + 0.2f);
r = Rg + (gl_FragCoord.y - 0.5f) / (float(SKY_H) - 1.0f) * (Rt - Rg);
}
//-- Given the windows's fragment coordinates, for a defined view port,
// gives back the interpolated r e [Rg, Rt] and mu, muSun amd nu e [-1, 1] --
// r := height of starting point vect(x)
// 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 := 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(const float r, vec4 dhdH, out float mu, out float muSun, out float nu) {
// Window coordinates of pixel (uncentering also)
float fragmentX = gl_FragCoord.x - 0.5f;
float fragmentY = gl_FragCoord.y - 0.5f;
// Pre-calculations
float Rg2 = Rg * Rg;
float Rt2 = Rt * Rt;
float r2 = r * r;
float halfSAMPLE_MU = float(SAMPLES_MU) / 2.0f;
// 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 (fragmentY < halfSAMPLE_MU) {
float ud = 1.0f - (fragmentY / (halfSAMPLE_MU - 1.0f));
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.
// If that is the case, we approximate to
// a ray touching the ground.
// cosine(pi-theta) = dh/r = sqrt(r^2-Rg^2)
// cosine(theta) = - sqrt(1 - Rg^2/r^2)
mu = min(mu, -sqrt(1.0 - (Rg2 / r2)) - 0.001);
}
// The light ray is touching the atmosphere and
// not the ground
else {
float d = (fragmentY - halfSAMPLE_MU) / (halfSAMPLE_MU - 1.0f);
d = min(max(dhdH.x, d * dhdH.y), dhdH.y * 0.999);
// cosine law: Rt^2 = r^2 + d^2 - 2rdcos(pi-theta)
// whre cosine(theta) = mu
mu = (Rt2 - r2 - d * d) / (2.0f * r * d);
}
float modValueMuSun = mod(fragmentX, float(SAMPLES_MU_S)) / (float(SAMPLES_MU_S) - 1.0f);
// The following mapping is different from the paper. See Colliene for an details.
muSun = tan((2.0f * modValueMuSun - 1.0f + 0.26f) * 1.1f) / tan(1.26f * 1.1f);
nu = -1.0f + floor(fragmentX / float(SAMPLES_MU_S)) / (float(SAMPLES_NU) - 1.0f) * 2.0f;
}
//-- Function to access the transmittance texture. Given r
// and mu, returns the transmittance of a ray starting at vec(x),
// height r, and direction vec(v), mu, and length until it 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 transmittanceLUT(const float r, const float mu) {
// 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) / (Rt - Rg));
//float u_r = sqrt((r*r - Rg*Rg) / (Rt*Rt - Rg*Rg));
// See Colliene to understand the different mapping.
float u_mu = atan((mu + 0.15f) / (1.0f + 0.15f) * tan(1.5f)) / 1.5f;
return texture(transmittanceTexture, vec2(u_mu, u_r)).rgb;
}
// -- Given a position r and direction mu, calculates de transmittance
// along the ray with length d. This function uses the propriety
// of Transmittance: 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(const float r, const float mu, const float d) {
// 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 (hight 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);
// mu_i = (vec(d) dot vec(v)) / r_i
// = ((vec(x) + vec(d-x)) dot vec(v))/ r_i
// = (r*mu + d) / r_i
float mui = (d + r * mu) / ri;
// It's important to remember that we calculate the Transmittance
// table only for zenith angles between 0 and pi/2+episilon.
// Then, if mu < 0.0, we just need to invert the view direction
// and the start and end points between them, i.e., if
// 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).
if (mu > 0.0f) {
return min(transmittanceLUT(r, mu) /
transmittanceLUT(ri, mui), 1.0f);
} else {
return min(transmittanceLUT(ri, -mui) /
transmittanceLUT(r, -mu), 1.0f);
}
}
// -- 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(const float mu) {
return (3.0f / (16.0f * M_PI)) * (1.0f + mu * mu);
}
// -- Calculates Mie 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 miePhaseFunction(const float mu) {
//return (3.0f / (8.0f * M_PI)) *
// ( ( (1.0f - (mieG * mieG) ) * (1.0f + mu * mu) ) /
// ( (2.0f + mieG * mieG) *
// pow(1.0f + mieG * mieG - 2.0f * mieG * mu, 3.0f/2.0f) ) );
return 1.5f * 1.0f / (4.0f * M_PI) * (1.0f - mieG * mieG) *
pow(1.0f + (mieG * mieG) - 2.0f * mieG * mu, -3.0f/2.0f) * (1.0f + mu * mu) / (2.0f + mieG*mieG);
}
// -- Given the height rm view-zenith angle (cosine) mu,
// sun-zenith angle (cosine) muSun and the angle (cosine)
// between the vec(s) and vec(v), nu, we access the 3D textures
// and interpolate between them (r) to find the value for the
// 4D texture. --
// r := height of starting point vect(x)
// 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, const float r, const float mu,
const float muSun, const float nu)
{
float Rg2 = Rg * Rg;
float Rt2 = Rt * Rt;
float r2 = r * r;
float H = sqrt(Rt2 - Rg2);
float rho = sqrt(r2 - Rg2);
float rmu = r * mu;
float delta = rmu * rmu - r2 + Rg2;
vec4 cst = rmu < 0.0f && delta > 0.0f ?
vec4(1.0f, 0.0f, 0.0f, 0.5f - 0.5f / float(SAMPLES_MU)) :
vec4(-1.0f, H * H, H, 0.5f + 0.5f / float(SAMPLES_MU));
float u_r = 0.5f / float(SAMPLES_R) + rho / H * (1.0f - 1.0f / float(SAMPLES_R));
float u_mu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5f - 1.0f / float(SAMPLES_MU));
float u_mu_s = 0.5f / float(SAMPLES_MU_S) +
(atan(max(muSun, -0.1975) * tan(1.26f * 1.1f)) / 1.1f + (1.0f - 0.26f)) * 0.5f * (1.0f - 1.0f / float(SAMPLES_MU_S));
float lerp = (nu + 1.0f) / 2.0f * (float(SAMPLES_NU) - 1.0f);
float u_nu = floor(lerp);
lerp = lerp - u_nu;
return texture(table, vec3((u_nu + u_mu_s) / float(SAMPLES_NU), u_mu, u_r)) * (1.0f - lerp) +
texture(table, vec3((u_nu + u_mu_s + 1.0f) / float(SAMPLES_NU), 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, const float muSun, const float r) {
// See Bruneton paper and Coliene to understand the mapping
float u_muSun = (muSun + 0.2f) / (1.0f + 0.2f);
float u_r = (r - Rg) / (Rt - Rg);
return texture(lut, vec2(u_muSun, u_r)).rgb;
}
@@ -0,0 +1,744 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* 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. *
****************************************************************************************/
/*****************************************************************************************
* Modified parts of the code (4D texture mechanism) from Eric Bruneton is used in the *
* following code. *
****************************************************************************************/
/**
* Precomputed Atmospheric Scattering
* Copyright (c) 2008 INRIA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#version __CONTEXT__
#include "floatoperations.glsl"
#include "hdr.glsl"
#include "atmosphere_common.glsl"
out vec4 renderTarget;
in vec3 interpolatedNDCPos;
uniform int nAaSamples;
uniform double msaaSamplePatter[48];
uniform int cullAtmosphere;
// The following uniforms are
// set into the current Renderer
// Background exposure hack
uniform float backgroundConstant;
uniform bool firstPaint;
uniform float atmExposure;
uniform sampler2D irradianceTexture;
uniform sampler3D inscatterTexture;
uniform sampler2DMS mainPositionTexture;
uniform sampler2DMS mainNormalTexture;
uniform sampler2DMS mainColorTexture;
uniform sampler2DMS otherDataTexture;
// Model Transform Matrix Used for Globe Rendering
uniform dmat4 dInverseSgctEyeToWorldTranform; // SGCT Eye to OS World
uniform dmat4 dSgctEyeToOSEyeTranform; // SGCT Eye to OS Eye *
uniform dmat4 dInverseSgctProjectionMatrix; // Clip to SGCT Eye *
uniform dmat4 dInverseCamRotTransform;
uniform dmat4 dInverseModelTransformMatrix;
uniform dmat4 dModelTransformMatrix;
//uniform dmat4 dSGCTEyeToOSWorldTransformMatrix;
uniform dvec4 dObjpos;
uniform dvec3 dCampos;
uniform dvec3 sunDirectionObj;
uniform dvec3 ellipsoidRadii;
/*******************************************************************************
***** ALL CALCULATIONS FOR ECLIPSE ARE IN METERS AND IN WORLD SPACE SYSTEM ****
*******************************************************************************/
// JCC: Remove and use dictionary to
// decides the number of shadows
const uint numberOfShadows = 1;
struct ShadowRenderingStruct {
double xu, xp;
double rs, rc;
dvec3 sourceCasterVec;
dvec3 casterPositionVec;
bool isShadowing;
};
// Eclipse shadow data
// JCC: Remove and use dictionary to
// decides the number of shadows
uniform ShadowRenderingStruct shadowDataArray[numberOfShadows];
uniform int shadows;
uniform bool hardShadows;
vec4 butterworthFunc(const float d, const float r, const float n) {
return vec4(vec3(sqrt(r/(r + pow(d, 2*n)))), 1.0);
}
vec4 calcShadow(const ShadowRenderingStruct shadowInfoArray[numberOfShadows], const dvec3 position,
const bool ground) {
if (shadowInfoArray[0].isShadowing) {
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;
float length_d = float(length(d));
double length_pc_proj = length(pc_proj);
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);
if ( length_d < r_u_pi ) { // umbra
if (ground) {
if (hardShadows) {
return vec4(0.2, 0.2, 0.2, 1.0);
} else {
return butterworthFunc(length_d, r_u_pi, 4.0);
}
}
else {
if (hardShadows) {
return vec4(0.5, 0.5, 0.5, 1.0);
} else {
return vec4(vec3(length_d/r_p_pi), 1.0);
}
}
}
else if ( length_d < r_p_pi ) {// penumbra
if (hardShadows) {
return vec4(0.5, 0.5, 0.5, 1.0);
} else {
return vec4(vec3(length_d/r_p_pi), 1.0);
}
}
}
return vec4(1.0);
}
/*******************************************************************************
******* ALL CALCULATIONS FOR ATMOSPHERE ARE KM AND IN WORLD SPACE SYSTEM ******
*******************************************************************************/
struct dRay {
dvec4 origin;
dvec4 direction;
};
/* Function to calculate the initial intersection of the eye (camera) ray
* with the atmosphere.
* In (all parameters in the same coordinate system and same units):
* - planet position
* - ray direction (normalized)
* - eye position
* - atmosphere radius
* Out: true if an intersection happens, false otherwise
* - inside: true if the ray origin is inside atmosphere, false otherwise
* - offset: the initial intersection distance from eye position when
* the eye is outside the atmosphere
* - maxLength : the second intersection distance from eye position when the
* eye is outside the atmosphere or the initial (and only)
* intersection of the ray with atmosphere when the eye position
* is inside atmosphere.
*/
bool dAtmosphereIntersection(const dvec3 planetPosition, const dRay ray, const double atmRadius,
out bool inside, out double offset, out double maxLength ) {
dvec3 l = planetPosition - ray.origin.xyz;
double s = dot(l, ray.direction.xyz);
double l2 = dot(l, l);
double r2 = atmRadius * atmRadius; // avoiding surface acne
// Ray origin (eye position) is behind sphere
if ((s < 0.0) && (l2 > r2)) {
inside = false;
offset = 0.0;
maxLength = 0.0;
return false;
}
double m2 = l2 - s*s;
// Ray misses atmospere
if (m2 > r2) {
inside = false;
offset = 0.0;
maxLength = 0.0;
return false;
}
// We already now the ray hits the atmosphere
// If q = 0.0f, there is only one intersection
double q = sqrt(r2 - m2);
// If l2 < r2, the ray origin is inside the sphere
if (l2 > r2) {
inside = false;
offset = s - q;
maxLength = s + q;
} else {
inside = true;
offset = 0.0;
maxLength = s + q;
}
return true;
}
/*
* Calculates Intersection Ray by walking through
* all the graphic pipile transformations in the
* opposite direction.
* Instead of passing through all the pipeline,
* it starts at NDC from the interpolated
* positions from the screen quad.
* This method avoids matrices multiplications
* wherever is possible.
*/
void dCalculateRayRenderableGlobe(in int mssaSample, out dRay ray,
out dvec4 planetPositionObjectCoords,
out dvec4 cameraPositionInObject) {
// ======================================
// ======= Avoiding Some Matrices =======
// NDC to clip coordinates (gl_FragCoord.w = 1.0/w_clip)
// Using the interpolated coords:
// Assuming Red Book is right: z_ndc e [0, 1] and not [-1, 1]
dvec2 samplePos = dvec2(msaaSamplePatter[mssaSample],
msaaSamplePatter[mssaSample+1]);
dvec4 clipCoords = dvec4(interpolatedNDCPos.xy + samplePos, interpolatedNDCPos.z, 1.0) / gl_FragCoord.w;
// Clip to SGCT Eye
dvec4 sgctEyeCoords = dInverseSgctProjectionMatrix * clipCoords;
sgctEyeCoords.w = 1.0;
// SGCT Eye to OS Eye
dvec4 tOSEyeCoordsInv = dSgctEyeToOSEyeTranform * sgctEyeCoords;
// OS Eye to World coords
dvec4 tmpRInv = dInverseCamRotTransform * tOSEyeCoordsInv;
dvec4 worldCoords = dvec4(dvec3(tmpRInv) + dCampos, 1.0);
// World to Object
dvec4 objectCoords = dInverseModelTransformMatrix * worldCoords;
// Planet Position in Object Space
// JCC: Applying the inverse of the model transformation on the object postion in World
// space results in imprecision.
planetPositionObjectCoords = dvec4(0.0, 0.0, 0.0, 1.0);
//planetPositionObjectCoords = dInverseModelTransformMatrix * dvec4(dObjpos.xyz, 1.0);
// Camera Position in Object Space
cameraPositionInObject = dInverseModelTransformMatrix * dvec4(dCampos, 1.0);
// ============================
// ====== Building Ray ========
// Ray in object space (in KM)
ray.origin = cameraPositionInObject * dvec4(0.001, 0.001, 0.001, 1.0);
ray.direction = dvec4(normalize(objectCoords.xyz - cameraPositionInObject.xyz), 0.0);
}
/*
* Calculates the light scattering in the view direction comming from other
* light rays scattered in the atmosphere.
* Following the paper: S[L]|x - T(x,xs) * S[L]|xs
* The view direction here is the ray: x + tv, s is the sun direction,
* r and mu the position and zenith cosine angle as in the paper.
* Arguments:
* x := camera position
* t := ray displacement variable after calculating the intersection with the
* atmosphere. It is the distance from the camera to the last intersection with
* the atmosphere. If the ray hits the ground, t is updated to the correct value
* v := view direction (ray's direction) (normalized)
* s := Sun direction (normalized)
* r := out of ||x|| inside atmosphere (or top of atmosphere)
* mu := out of cosine of the zenith view angle
* attenuation := out of transmittance T(x,x0). This will be used later when
* calculating the reflectance R[L].
*/
vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor,
const vec3 v, const vec3 s, out float r, out float mu,
out vec3 attenuation, const vec3 fragPosObj,
const double maxLength, const double pixelDepth,
const vec4 spaceColor, const float sunIntensity) {
vec3 radiance;
r = length(x);
mu = dot(x, v) / r;
float mu2 = mu * mu;
float r2 = r * r;
float Rt2 = Rt * Rt;
float Rg2 = Rg * Rg;
float nu = dot(v, s);
float muSun = dot(x, s) / r;
float rayleighPhase = rayleighPhaseFunction(nu);
float miePhase = miePhaseFunction(nu);
// S[L](x,s,v)
// 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);
// 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
vec3 x0 = fragPosObj;
float r0 = length(fragPosObj);
float invr0 = 1.0/r0;
float muSun0 = dot(fragPosObj, s) * invr0;
//vec3 x0 = x + float(pixelDepth) * v;
float mu0 = dot(x0, v) * invr0;
bool groundHit = false;
if ((pixelDepth > 0.0) && (pixelDepth < maxLength)) {
t = float(pixelDepth);
groundHit = true;
// Transmittance from point r, direction mu, distance t
// By Analytical calculation
//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);
// 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);
inscatterRadiance = max(inscatterRadiance - attenuation.rgbr * inscatterFromSurface, 0.0);
// We set the irradianceFactor to 1.0 so the reflected irradiance will be considered
// when calculating the reflected light on the ground.
irradianceFactor = 1.0;
} else {
attenuation = analyticTransmittance(r, mu, t);
//attenuation = transmittance(r, mu, t);
}
// 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.0f - (Rg2 / r2));
// In order to avoid imprecision problems near horizon,
// we interpolate between two points: above and below horizon
const float INTERPOLATION_EPS = 0.004f; // precision const from Brunetton
if (abs(mu - muHorizon) < INTERPOLATION_EPS) {
// We want an interpolation value close to 1/2, so the
// contribution of each radiance value is almost the same
// or it has a havey weight if from above or below horizon
float interpolationValue = ((mu - muHorizon) + INTERPOLATION_EPS) / (2.0f * INTERPOLATION_EPS);
float t2 = t * t;
// Above Horizon
mu = muHorizon - INTERPOLATION_EPS;
//r0 = sqrt(r * r + t * t + 2.0f * 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);
// From the dot product: cos(theta0) = (x0 dot v)/(||ro||*||v||)
// mu0 = ((x + t) dot v) / r0
// mu0 = (x dot v + t dot v) / r0
// mu0 = (r*mu + t) / r0
mu0 = (r * mu + t) / r0;
vec4 inScatterAboveX = texture4D(inscatterTexture, r, mu, muSun, nu);
vec4 inScatterAboveXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu);
// Attention for the attenuation.r value applied to the S_Mie
vec4 inScatterAbove = max(inScatterAboveX - attenuation.rgbr * inScatterAboveXs, 0.0f);
// Below Horizon
mu = muHorizon + INTERPOLATION_EPS;
r0 = sqrt(r2 + t2 + 2.0f * r * t * mu);
mu0 = (r * mu + t) / r0;
vec4 inScatterBelowX = texture4D(inscatterTexture, r, mu, muSun, nu);
vec4 inScatterBelowXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu);
// Attention for the attenuation.r value applied to the S_Mie
vec4 inScatterBelow = max(inScatterBelowX - attenuation.rgbr * inScatterBelowXs, 0.0);
// Interpolate between above and below inScattering radiance
inscatterRadiance = mix(inScatterAbove, inScatterBelow, interpolationValue);
}
// The w component of inscatterRadiance has stored the Cm,r value (Cm = Sm[L0])
// So, we must reintroduce the Mie inscatter by the proximity rule as described in the
// paper by Bruneton and Neyret in "Angular precision" paragraph:
// Hermite interpolation between two values
// This step is done because imprecision problems happen when the Sun is slightly below
// the horizon. When this happen, we avoid the Mie scattering contribution.
inscatterRadiance.w *= smoothstep(0.0f, 0.02f, muSun);
vec3 inscatterMie = inscatterRadiance.rgb * inscatterRadiance.a / max(inscatterRadiance.r, 1e-4) *
(betaRayleigh.r / betaRayleigh);
radiance = max(inscatterRadiance.rgb * rayleighPhase + inscatterMie * miePhase, 0.0f);
// Finally we add the Lsun (all calculations are done with no Lsun so
// we can change it on the fly with no precomputations)
// return radiance * sunRadiance;
vec3 finalScatteringRadiance = radiance * sunIntensity;
if (groundHit) {
return finalScatteringRadiance;
} else {
return ((r-Rg)/(Rt-Rg))*spaceColor.rgb * backgroundConstant + finalScatteringRadiance;
}
}
/*
* Calculates the light reflected in the view direction comming from other
* light rays integrated over the hemispehre plus the direct light (L0) from Sun.
* Following the paper: R[L]= R[L0]+R[L*]
* The the ray is x + tv, v the view direction, s is the sun direction,
* r and mu the position and zenith cosine angle as in the paper.
* As for all calculations in the atmosphere, the center of the coordinate system
* is the planet's center of coordiante system, i.e., the planet's position is (0,0,0).
* Arguments:
* x := camera position
* t := ray displacement variable. Here, differently from the inScatter light calculation,
* the position of the camera is already offset (on top of atmosphere) or inside
* the atmosphere.
* v := view direction (ray's direction) (normalized)
* s := Sun direction (normalized)
* r := ||x|| inside atmosphere (or top of atmosphere). r <= Rt here.
* mu := cosine of the zenith view angle
* attenuationXtoX0 := transmittance T(x,x0)
*/
vec3 groundColor(const vec3 x, const float t, const vec3 v, const vec3 s, const float r,
const float mu, const vec3 attenuationXtoX0, const vec4 groundColor,
const vec3 normal, const float irradianceFactor,
const float waterReflectance, const float sunIntensity)
{
vec3 reflectedRadiance = vec3(0.0f);
// First we obtain the ray's end point on the surface
vec3 x0 = x + t * v;
float r0 = length(x0);
// Normal of intersection point.
vec3 n = normalize(normal);
//vec4 groundReflectance = groundColor * vec4(.37);
vec4 groundReflectance = groundColor *
vec4(groundRadianceEmittion, groundRadianceEmittion, groundRadianceEmittion, 1.0f);
// L0 is not included in the irradiance texture.
// We first calculate the light attenuation from the top of the atmosphere
// to x0.
float dotNS = dot(n, s);
float muSun = max(dotNS, 0.0f);
// Is direct Sun light arriving at x0? If not, there is no direct light from Sun (shadowed)
vec3 transmittanceL0 = muSun < -sqrt(1.0f - ((Rg * Rg) / (r0 * r0))) ?
vec3(0.0f) : transmittanceLUT(r0, muSun);
// E[L*] at x0
vec3 irradianceReflected = irradiance(irradianceTexture, r0, muSun) * irradianceFactor;
// R[L0] + R[L*]
// vec3 groundRadiance = (dotNS < -0.2f ? groundReflectance.rgb * 15 : groundReflectance.rgb) *
// (muSun * transmittanceL0 + irradianceReflected) * sunIntensity / M_PI;
vec3 groundRadiance;
vec3 RLStar = (muSun * transmittanceL0 + irradianceReflected) * sunIntensity / M_PI;
if (dotNS < 0.05f) {
groundRadiance = groundReflectance.rgb * mix(30.0f, 1.0f, smoothstep(-1.0f, 0.05f, dotNS)) * RLStar;
} else {
groundRadiance = groundReflectance.rgb * RLStar;
}
//groundRadiance = groundReflectance.rgb * RLStar;
// Specular reflection from sun on oceans and rivers
if ((waterReflectance > 0.1) && /*(dotNS > -0.2f)*/(muSun > 0.0)) {
vec3 h = normalize(s - v);
// Fresnell Schlick's approximation
float fresnel = 0.02f + 0.98f * pow(1.0f - dot(-v, h), 5.0f);
// Walter BRDF approximation
float waterBrdf = fresnel * pow(max(dot(h, n), 0.0f), 150.0f);
// 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;
}
//return groundRadiance;
// Finally, we attenuate the surface Radiance from the the point x0 to the camera location.
reflectedRadiance = attenuationXtoX0 * groundRadiance;
// Returns reflectedRadiance = 0.0 if the ray doesn't hit the ground.
return reflectedRadiance;
}
/*
* Calculates the Sun color.
* The the ray is x + tv, v the view direction, s is the sun direction,
* r and mu the position and zenith cosine angle as in the paper.
* As for all calculations in the atmosphere, the center of the coordinate system
* is the planet's center of coordiante system, i.e., the planet's position is (0,0,0).
* Arguments:
* x := camera position
* t := ray displacement variable. Here, differently from the inScatter light calculation,
* the position of the camera is already offset (on top of atmosphere) or inside
* the atmosphere.
* v := view direction (ray's direction) (normalized)
* s := Sun direction (normalized)
* r := ||x|| inside atmosphere (or top of atmosphere). r <= Rt here.
* mu := cosine of the zenith view angle
* attenuation := transmittance T(x,x0)
*/
vec3 sunColor(const vec3 x, const float t, const vec3 v, const vec3 s, const float r,
const float mu, const float irradianceFactor) {
vec3 transmittance = (r <= Rt) ? ( mu < -sqrt(1.0f - (Rg*Rg)/(r*r)) ?
vec3(0.0f) : transmittanceLUT(r, mu)) : vec3(1.0f);
// JCC: Change this function to a impostor texture with gaussian decay color weighted
// by tge sunRadiance, transmittance and irradianceColor (11/03/2017)
float sunFinalColor = step(cos(M_PI / 650.0), dot(v, s)) * sunRadiance * (1.0 - irradianceFactor);
return transmittance * sunFinalColor;
}
void main() {
if (cullAtmosphere == 0) {
vec4 atmosphereFinalColor = vec4(0.0f);
// First we determine if the pixel is complex (different fragments on it)
bool complex = false;
vec4 oldColor, currentColor;
//vec4 colorArray[16];
//int colorIndexArray[16];
oldColor = texelFetch(mainColorTexture, ivec2(gl_FragCoord), 0);
//colorArray[0] = oldColor;
//colorIndexArray[0] = 0;
for (int i = 1; i < nAaSamples; i++) {
//vec4 normal = texelFetch(mainNormalTexture, ivec2(gl_FragCoord), i);
vec4 currentColor = texelFetch(mainColorTexture, ivec2(gl_FragCoord), i);
//colorArray[i] = currentColor;
if (currentColor != oldColor) {
complex = true;
break;
// for (int c = 0; c < nAaSamples; c++) {
// if (currentColor == colorArray[c]) {
// colorIndexArray[i] = c;
// break;
// }
// }
}
//else {
// for (int c = 0; c < nAaSamples; c++) {
// if (currentColor == colorArray[c]) {
// colorIndexArray[i] = c;
// break;
// }
// }
// }
oldColor = currentColor;
}
int nSamples = 1;
if (complex) {
//nSamples = nAaSamples;
nSamples = nAaSamples > 1 ? nAaSamples/2 : nAaSamples;
}
for (int i = 0; i < nSamples; i++) {
vec4 normal = texelFetch(mainNormalTexture, ivec2(gl_FragCoord), i);
vec4 color = texelFetch(mainColorTexture, ivec2(gl_FragCoord), i);
// Data in the mainPositionTexture are written in view space (view plus camera rig)
vec4 position = texelFetch(mainPositionTexture, ivec2(gl_FragCoord), i);
vec4 otherData = texelFetch(otherDataTexture, ivec2(gl_FragCoord), i);
// Ray in object space
dRay ray;
dvec4 planetPositionObjectCoords = dvec4(0.0);
dvec4 cameraPositionInObject = dvec4(0.0);
// Get the ray from camera to atm in object space
dCalculateRayRenderableGlobe(i * 3, ray, planetPositionObjectCoords,
cameraPositionInObject);
bool insideATM = false;
double offset = 0.0;
double maxLength = 0.0;
bool intersectATM = false;
// Instead of ray-ellipsoid intersection lets transform the ray to a sphere:
dRay transfRay;
transfRay.origin = ray.origin;
transfRay.direction = ray.direction;
// transfRay.origin.z *= 1000.0/ellipsoidRadii.x;
// transfRay.direction.z *= 1000.0/ellipsoidRadii.x;
// transfRay.origin.x *= 1000.0/ellipsoidRadii.y;
// transfRay.direction.x *= 1000.0/ellipsoidRadii.y;
// transfRay.origin.y *= 1000.0/ellipsoidRadii.z;
// transfRay.direction.y *= 1000.0/ellipsoidRadii.z;
// transfRay.direction.xyz = normalize(transfRay.direction.xyz);
intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay,
Rt - ATM_EPSILON/100.0, insideATM, offset, maxLength );
if ( intersectATM ) {
// Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel
// in the depth buffer is less than the distance to the atmosphere then the atmosphere
// is occluded
// Fragments positions into G-Buffer are written in OS Eye Space (Camera Rig Coords)
// when using their positions later, one must convert them to the planet's coords
// OS Eye to World coords
dvec4 tmpRInvPos = dInverseCamRotTransform * dSgctEyeToOSEyeTranform * position;
dvec4 fragWorldCoords = dvec4(dvec3(tmpRInvPos) + dCampos, 1.0);
// World to Object (Normal and Position in meters)
dvec4 fragObjectCoords = dInverseModelTransformMatrix * fragWorldCoords;
// Distance of the pixel in the gBuffer to the observer
// JCC (12/12/2017): AMD distance function is buggy.
//double pixelDepth = distance(cameraPositionInObject.xyz, fragObjectCoords.xyz);
double pixelDepth = length(cameraPositionInObject.xyz - fragObjectCoords.xyz);
// JCC (12/13/2017): TRick to remove floating error in texture.
// We see a squared noise on planet's surface when seeing the planet
// from far away.
float dC = float(length(cameraPositionInObject.xyz));
float x1 = 1e8;
if (dC > x1) {
pixelDepth += 1000.0;
float alpha = 1000.0;
float beta = 1000000.0;
float x2 = 1e9;
float diffGreek = beta - alpha;
float diffDist = x2 - x1;
float varA = diffGreek/diffDist;
float varB = (alpha - varA * x1);
pixelDepth += double(varA * dC + varB);
}
// All calculations are done in Km:
pixelDepth *= 0.001;
fragObjectCoords.xyz *= 0.001;
if (position.xyz != vec3(0.0) && (pixelDepth < offset)) {
atmosphereFinalColor += vec4(HDR(color.xyz * backgroundConstant, atmExposure), color.a);
//discard;
} else {
// Following paper nomenclature
double t = offset;
vec3 attenuation;
// Moving observer from camera location to top atmosphere
// If the observer is already inside the atm, offset = 0.0
// and no changes at all.
vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz);
float r = 0.0;//length(x);
vec3 v = vec3(ray.direction.xyz);
float mu = 0.0;//dot(x, v) / r;
vec3 s = vec3(sunDirectionObj);
float tF = float(maxLength - t);
// Because we may move the camera origin to the top of atmosphere
// we also need to adjust the pixelDepth for tdCalculateRayRenderableGlobehis offset so the
// next comparison with the planet's ground make sense:
pixelDepth -= offset;
dvec4 onATMPos = dModelTransformMatrix * dvec4(x*1000.0, 1.0);
vec4 eclipseShadowATM = calcShadow(shadowDataArray, onATMPos.xyz, false);
vec4 eclipseShadowPlanet = calcShadow(shadowDataArray, fragWorldCoords.xyz, true);
float sunIntensityInscatter = sunRadiance * eclipseShadowATM.x;
float sunIntensityGround = sunRadiance * eclipseShadowPlanet.x;
float irradianceFactor = 0.0;
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v,
s, r, mu, attenuation,
vec3(fragObjectCoords.xyz),
maxLength, pixelDepth,
color, sunIntensityInscatter);
vec3 groundColor = groundColor(x, tF, v, s, r, mu, attenuation,
color, normal.xyz, irradianceFactor,
otherData.r, sunIntensityGround);
vec3 sunColor = sunColor(x, tF, v, s, r, mu, irradianceFactor);
// Final Color of ATM plus terrain:
vec4 finalRadiance = vec4(HDR(inscatterColor + groundColor + sunColor, atmExposure), 1.0);
atmosphereFinalColor += finalRadiance;
}
}
else { // no intersection
//discard;
atmosphereFinalColor += vec4(HDR(color.xyz * backgroundConstant, atmExposure), color.a);
}
}
renderTarget = atmosphereFinalColor / float(nSamples);
}
else { // culling
if (firstPaint) {
vec4 bColor = vec4(0.0f);
for (int f = 0; f < nAaSamples; f++) {
bColor += texelFetch(mainColorTexture, ivec2(gl_FragCoord), f);
}
bColor /= float(nAaSamples);
renderTarget = vec4(HDR(bColor.xyz * backgroundConstant, atmExposure), bColor.a);
}
else {
discard;
}
//renderTarget = vec4(1.0, 0.0, 0.0, 1.0);
}
}
@@ -0,0 +1,35 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec4 in_position;
out vec3 interpolatedNDCPos;
void main()
{
interpolatedNDCPos = in_position.xyz;
gl_Position = in_position;
}
@@ -0,0 +1,32 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTableColor;
void main(void) {
renderTableColor = vec4(0.0, 0.0, 0.0, 1.0);
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,209 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTarget1;
uniform float r;
uniform vec4 dhdH;
uniform sampler2D deltaETexture;
uniform sampler3D deltaSRTexture;
uniform sampler3D deltaSMTexture;
uniform int firstIteraction;
// -- Spherical Coordinates Steps. phi e [0,2PI] and theta e [0, PI]
const float stepPhi = (2.0f * M_PI) / float(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES);
const float stepTheta = M_PI / float(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES);
void inscatter(float r, float mu, float muSun, float nu, inout vec3 radianceJ) {
// Be sure to not get a cosine or height out of bounds
r = clamp(r, Rg, Rt);
mu = clamp(mu, -1.0f, 1.0f);
muSun = clamp(muSun, -1.0f, 1.0f);
// s sigma | theta v
// \ | /
// \ | /
// \ | /
// \ | / theta + signam = ni
// \ | / cos(theta) = mu
// \ | / cos(sigma) = muSun
// \|/ cos(ni) = nu
float mu2 = mu * mu;
float muSun2 = muSun * muSun;
float sinThetaSinSigma = sqrt(1.0f - mu2) * sqrt(1.0f - 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)
// 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);
// Lets calculate the consine of the angle to the horizon:
// theta is the angle between vec(v) and x
// cos(PI-theta) = d/r
// -cos(theta) = sqrt(r*r-Rg*Rg)/r
float Rg2 = Rg * Rg;
float r2 = r * r;
float cosHorizon = -sqrt(r2 - Rg2)/r;
// Now we get vec(v) and vec(s) from mu, muSun and nu:
// Assuming:
// z |theta
// |\ vec(v) ||vec(v)|| = 1
// | \
// |__\_____x
// sin(PI-theta) = x/||v|| => x = sin(theta) =? x = sqrt(1-mu*mu)
// cos(PI-theta) = z/||v|| => z = cos(theta) = mu
// v.y = 0 because ||v|| = 1
vec3 v = vec3(sqrt(1.0 - mu2), 0.0, mu);
// To obtain vec(s), we use the following properties:
// ||vec(s)|| = 1, ||vec(v)|| = 1
// vec(s) dot vec(v) = cos(ni) = nu
// Following the same idea for vec(v), we now that s.z = cos(sigma) = muSun
// So, from vec(s) dot vec(v) = cos(ni) = nu we have,
// s.x*v.x +s.y*v.y + s.z*v.z = nu
// s.x = (nu - s.z*v.z)/v.x = (nu - mu*muSun)/v.x
float sx = (v.x == 0.0) ? 0.0 : (nu - muSun * mu) / v.x;
// Also, ||vec(s)|| = 1, so:
// 1 = sqrt(s.x*s.x + s.y*s.y + s.z*s.z)
// s.y = sqrt(1 - s.x*s.x - s.z*s.z) = sqrt(1 - s.x*s.x - muSun*muSun)
vec3 s = vec3(sx, sqrt(max(0.0, 1.0 - sx * sx - muSun2)), muSun);
// In order to integrate over 4PI, we scan the sphere using the spherical coordinates
// previously defined
for ( int theta_i = 0; theta_i < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++theta_i ) {
float theta = (float(theta_i) + 0.5f) * stepTheta;
float cosineTheta = cos(theta);
float cosineTheta2 = cosineTheta * cosineTheta;
float distanceToGround = 0.0f;
float groundReflectance = 0.0f;
vec3 groundTransmittance = vec3(0.0f);
// If the ray w can see the ground we must compute the transmittance
// effect from the starting point x to the ground point in direction -vec(v):
if ( cosineTheta < cosHorizon ) { // ray hits ground
// AverageGroundReflectance e [0,1]
groundReflectance = AverageGroundReflectance / M_PI;
// From cosine law: Rg*Rg = r*r + distanceToGround*distanceToGround - 2*r*distanceToGround*cos(PI-theta)
distanceToGround = -r * cosineTheta - sqrt(r2 * (cosineTheta2 - 1.0f) + Rg2);
// |
// | theta
// |
// |\ distGround
// r | \ alpha
// | \/
// | /
// | / Rg
// |/
// So cos(alpha) = ((vec(x)+vec(dg)) dot -vec(distG))/(||(vec(x)+vec(distG))|| * ||vec(distG)||)
// cos(alpha) = (-r*distG*cos(theta) - distG*distG)/(Rg*distG)
// muGround = -(r*cos(theta) + distG)/Rg
float muGround = -(r * cosineTheta + distanceToGround) / Rg;
// We can use the same triangle in calculate the distanceToGround to calculate the cosine of the
// angle between the ground touching point at height Rg and the zenith angle
//float muGround = (r2 - distanceToGround*distanceToGround - Rg2)/(2*distanceToGround*Rg);
// Acesss 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);
}
//for ( int phi_i = 0; phi_i < 2*INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++phi_i ) {
for ( int phi_i = 0; phi_i < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++phi_i ) {
float phi = (float(phi_i) + 0.5) * stepPhi;
// spherical coordinates: dw = dtheta*dphi*sin(theta)*rho^2
// rho = 1, we are integrating over a unit sphere
float dw = stepTheta * stepPhi * sin(theta);
// w = (rho*sin(theta)*cos(phi), rho*sin(theta)*sin(phi), rho*cos(theta))
float sinPhi = sin(phi);
float sinTheta = sin(theta);
float cosPhi = cos(phi);
vec3 w = vec3(sinTheta * cosPhi, sinTheta * sinPhi, cosineTheta);
// We calculate the Rayleigh and Mie phase function for the new scattering angle:
// cos(angle between vec(v) and vec(w)), ||v|| = ||w|| = 1
float nuWV = dot(v, w);
float phaseRayleighWV = rayleighPhaseFunction(nuWV);
float phaseMieWV = miePhaseFunction(nuWV);
vec3 groundNormal = (vec3(0.0, 0.0, r) + distanceToGround * w) / Rg;
vec3 groundIrradiance = irradianceLUT(deltaETexture, dot(groundNormal, s), Rg);
// We finally calculate the radiance from the reflected ray from ground (0.0 if not reflected)
vec3 radianceJ1 = groundTransmittance * groundReflectance * groundIrradiance;
// 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, that's because in the first
// iteraction all the light InScattered are 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 ) {
float phaseRaySW = rayleighPhaseFunction(nuSW);
float phaseMieSW = miePhaseFunction(nuSW);
// 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;
// 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 (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;
}
// Finally, we add the atmospheric scale height (See: Radiation Transfer on the Atmosphere and Ocean from
// Thomas and Stamnes, pg 9-10.
radianceJ += radianceJ1 * (betaRayleigh * exp(-(r - Rg) / HR) * phaseRayleighWV +
betaMieScattering * exp(-(r - Rg) / HM) * phaseMieWV) * dw;
}
}
}
void main(void) {
// cosine variables to access deltaS textures
float mu, muSun, nu;
// InScattering Radiance to be calculated at
// different points in the ray path
vec3 radianceJ = vec3(0.0f);
// Unmapping the variables from texture texels coordinates
// to mapped coordinates
unmappingMuMuSunNu(r, dhdH, 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
inscatter(r, mu, muSun, nu, radianceJ);
// Write to texture detaJ
renderTarget1 = vec4(radianceJ, 1.0);
}
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform int layer;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main()
{
int n;
for (n = 0; n < gl_in.length(); ++n) {
gl_Position = gl_in[n].gl_Position;
gl_Layer = layer;
EmitVertex();
}
EndPrimitive();
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,49 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTarget1;
uniform int layer;
uniform sampler3D deltaSRTexture;
uniform sampler3D deltaSMTexture;
void main(void) {
// First we convert the window's fragment coordinate to
// texel coordinates
vec3 rst = vec3(gl_FragCoord.xy, float(layer) + 0.5f) /
vec3(ivec3(SAMPLES_MU_S * SAMPLES_NU, SAMPLES_MU, SAMPLES_R));
vec4 rayleighInscattering0 = texture(deltaSRTexture, rst);
vec4 mieInscattering0 = texture(deltaSMTexture, rst);
// We are using only the red component of the Mie scattering
// See the Precomputed Atmosphere Scattering paper for details about
// the angular precision.
renderTarget1 = vec4(rayleighInscattering0.rgb, mieInscattering0.r);
}
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform int layer;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main()
{
int n;
for (n = 0; n < gl_in.length(); ++n) {
gl_Position = gl_in[n].gl_Position;
gl_Layer = layer;
EmitVertex();
}
EndPrimitive();
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,45 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTarget1;
uniform int layer;
uniform sampler3D deltaSTexture;
void main(void) {
float x = gl_FragCoord.x - 0.5f;
float y = gl_FragCoord.y - 0.5f;
float nu = -1.0f + floor(x / float(SAMPLES_MU_S)) / (float(SAMPLES_NU) - 1.0f) * 2.0f;
vec3 uvw = vec3(gl_FragCoord.xy, float(layer) + 0.5f) / 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.
renderTarget1 = vec4(texture(deltaSTexture, uvw).rgb / rayleighPhaseFunction(nu), 0.0f);
}
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform int layer;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main()
{
int n;
for (n = 0; n < gl_in.length(); ++n) {
gl_Position = gl_in[n].gl_Position;
gl_Layer = layer;
EmitVertex();
}
EndPrimitive();
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,137 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
layout(location = 0) out vec4 renderTarget1;
layout(location = 1) out vec4 renderTarget2;
uniform float r;
uniform vec4 dhdH;
//uniform sampler2D transmittanceTexture;
void integrand(const float r, const float mu, const float muSun, const float nu,
const float y, out vec3 S_R, out vec3 S_M) {
// The integral's integrand is the single inscattering radiance:
// S[L0] = P_M*S_M[L0] + P_R*S_R[L0]
// where S_M[L0] = T*(betaMScattering * exp(-h/H_M))*L0 and
// S_R[L0] = T*(betaRScattering * exp(-h/H_R))*L0.
// T = transmittance.
// One must remember that because the occlusion on L0, the integrand
// here will be equal to 0 in that cases.
// Also it is important to remember that the phase function for the
// Rayleigh and Mie scattering are added during the rendering time
// to increase the angular precision
S_R = vec3(0.0);
S_M = vec3(0.0);
// cosine law
float ri = max(sqrt(r * r + y * y + 2.0 * r * mu * y), Rg);
// Considering the Sun as a parallel light source,
// thew vector s_i = s.
// So muSun_i = (vec(y_i) dot vec(s))/r_i = ((vec(x) + vec(yi-x)) dot vec(s))/r_i
// muSun_i = (vec(x) dot vec(s) + vec(yi-x) dot vec(s))/r_i = (r*muSun + yi*nu)/r_i
float muSun_i = (nu * y + muSun * r) / ri;
// If the muSun_i is smaller than the angle to horizon (no sun radiance
// hitting the point y), we return S_R = S_M = 0.0f.
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) * transmittanceLUT(ri, muSun_i);
// exp(-h/H)*T(x,v)
if (ozoneLayerEnabled) {
S_R = (exp(-(ri - Rg) / HO) + exp( -(ri - Rg) / HR )) * transmittanceY;
S_M = exp( -(ri - Rg) / HM ) * transmittanceY;
} else {
S_R = exp( -(ri - Rg) / HR ) * transmittanceY;
S_M = exp( -(ri - Rg) / HM ) * transmittanceY;
}
// The L0 (sun radiance) is added in real-time.
}
}
void inscatter(const float r, const float mu, const float muSun, const float nu,
out vec3 S_R, out vec3 S_M) {
// Let's calculate S_M and S_R by integration along the eye ray path inside
// the atmosphere, given a position r, a view angle (cosine) mu, a sun
// position angle (cosine) muSun, and the angle (cosine) between the sun position
// and the view direction, nu.
// 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)))
S_R = vec3(0.0f);
S_M = vec3(0.0f);
float rayDist = rayDistance(r, mu);
float dy = rayDist / float(INSCATTER_INTEGRAL_SAMPLES);
float yi = 0.0f;
vec3 S_Ri;
vec3 S_Mi;
integrand(r, mu, muSun, nu, 0.0, S_Ri, S_Mi);
for (int i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i) {
float yj = float(i) * dy;
vec3 S_Rj;
vec3 S_Mj;
integrand(r, mu, muSun, nu, yj, S_Rj, S_Mj);
S_R += (S_Ri + S_Rj);
S_M += (S_Mi + S_Mj);
yi = yj;
S_Ri = S_Rj;
S_Mi = S_Mj;
}
S_R *= betaRayleigh * (rayDist / (2.0f * float(INSCATTER_INTEGRAL_SAMPLES)));
S_M *= betaMieScattering * (rayDist / (2.0f * float(INSCATTER_INTEGRAL_SAMPLES)));
}
void main(void) {
vec3 S_R; // First Order Rayleigh InScattering
vec3 S_M; // First Order Mie InScattering
float mu, muSun, nu; // parametrization angles
// From the layer interpolation (see C++ code for layer to r)
// and the textures parameters (uv), we unmapping mu, muSun and nu.
unmappingMuMuSunNu(r, dhdH, 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 infinity (top of atmosphere or planet's
// ground), comes only from the light source, i.e., the
// sun. So, the there is no need to integrate over the
// whole solid angle (4pi), we need only to consider
// the Sun position (cosine of sun pos = muSun).
// Then, following the paper notation:
// S[L] = P_R*S_R[L0] + P_M*S_M[L0] + S[L*]
// For single inscattering only:
// 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.
inscatter(r, mu, muSun, nu, S_R, S_M);
renderTarget1 = vec4(S_R, 1.0);
renderTarget2 = vec4(S_M, 1.0);
}
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform int layer;
layout (triangles) in;
layout (triangle_strip, max_vertices=3) out;
void main()
{
int n;
for (n = 0; n < gl_in.length(); ++n) {
gl_Position = gl_in[n].gl_Position;
gl_Layer = layer;
EmitVertex();
}
EndPrimitive();
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,79 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTarget1;
uniform float r;
uniform vec4 dhdH;
//uniform sampler2D transmittanceTexture;
uniform sampler3D deltaJTexture;
// The integrand here is the f(y) of the trapezoidal rule:
vec3 integrand(const float r, const float mu, const float muSun, const float nu, const 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);
// 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
// So, cos(theta_i) = mu_i = (r*dist**mu + dist*2)/(r_i*dist)
float mu_i = (r * mu + dist) / r_i;
// muSun_i can also be found by the dot product:
// cos(sigma_i) = muSun_i = (vec(s) dot vec(y_i))/(||vec(y_i)|| * ||vec(s)||)
// 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;
}
vec3 inscatter(float r, float mu, float muSun, float nu) {
vec3 inScatteringRadiance = vec3(0.0f);
float dy = rayDistance(r, mu) / 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: Integral(f(y)dy)(from a to b) = ((b-a)/2n_steps)*(Sum(f(y_i+1)+f(y_i)))
// where y_i+1 = y_j
for (int i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i) {
float y_j = float(i) * dy;
vec3 inScatteringRadiance_j = integrand(r, mu, muSun, nu, y_j);
inScatteringRadiance += (inScatteringRadiance_i + inScatteringRadiance_j) / 2.0 * dy;
inScatteringRadiance_i = inScatteringRadiance_j;
}
return inScatteringRadiance;
}
void main(void) {
float mu = 0.0f, muSunun = 0.0f, nu = 0.0f;
// Unmapping the variables from texture texels coordinates
// to mapped coordinates
unmappingMuMuSunNu(r, dhdH, mu, muSunun, nu);
// Write to texture deltaSR
renderTarget1 = vec4(inscatter(r, mu, muSunun, nu), 1.0);
}
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform int layer;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main()
{
int n;
for (n = 0; n < gl_in.length(); ++n) {
gl_Position = gl_in[n].gl_Position;
gl_Layer = layer;
EmitVertex();
}
EndPrimitive();
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,43 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTableColor;
//uniform sampler2D transmittanceTexture;
void main(void) {
float muSun, r;
unmappingRAndMuSun(r, muSun);
// We are calculating the Irradiance for L0, i.e.,
// only the radiance comming from sun direction is accounted:
// 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 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(transmittanceLUT(r, muSun) * max(muSun, 0.0), 0.0);
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,37 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTableColor;
uniform sampler2D deltaETexture;
void main(void) {
vec2 uv = gl_FragCoord.xy / vec2(OTHER_TEXTURES_W, OTHER_TEXTURES_H);
// Update texture E with E plus deltaE textures.
renderTableColor = texture(deltaETexture, uv);
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,93 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
out vec4 renderTableColor;
uniform int firstIteraction;
//uniform float firstIteraction;
// -- Spherical Coordinates Steps. phi e [0,2PI] and theta e [0, PI/2]
const float stepPhi = (2.0f * M_PI) / float(IRRADIANCE_INTEGRAL_SAMPLES);
const float stepTheta = M_PI / (2.0f * float(IRRADIANCE_INTEGRAL_SAMPLES));
//uniform sampler2D transmittanceTexture;
uniform sampler3D deltaSRTexture;
uniform sampler3D deltaSMTexture;
void main(void) {
float r = 0.0f;
float muSun = 0.0f;
// Unmapping the variables from texture texels coordinates
// to mapped coordinates
unmappingRAndMuSunIrradiance(r, muSun);
// 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
vec3 s = vec3(max(sqrt(1.0f - muSun * muSun), 0.0f), 0.0f, muSun);
// In order to solve the integral from equation (15) we use the trapezoidal
// rule: Integral(f(y)dy)(from a to b) = ((b-a)/2n_steps)*(Sum(f(y_i+1)+f(y_i)))
vec3 irradianceE = vec3(0.0f);
for (int iphi = 0; iphi < IRRADIANCE_INTEGRAL_SAMPLES; ++iphi) {
float phi = (float(iphi) + 0.5f) * stepPhi;
for (int itheta = 0; itheta < IRRADIANCE_INTEGRAL_SAMPLES; ++itheta) {
float theta = (float(itheta) + 0.5f) * stepTheta;
// spherical coordinates: dw = dtheta*dphi*sin(theta)*rho^2
// rho = 1, we are integrating over a unit sphere
float dw = stepTheta * stepPhi * sin(theta);
// w = (cos(phi) * sin(theta) * rho, sin(phi) * sin(theta) * rho, cos(theta) * rho)
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) {
float phaseRay = rayleighPhaseFunction(nu);
float phaseMie = miePhaseFunction(nu);
vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nu).rgb;
vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, 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 (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;
}
}
}
// Write the higher oder irradiance to texture deltaE
renderTableColor = vec4(irradianceE, 0.0);
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -0,0 +1,91 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "atmosphere_common.glsl"
//layout(location = 1) out vec4 renderTableColor;
out vec4 renderTableColor;
//-- 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)
// mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r
// H := Thickness of atmosphere if its density were uniform (can be used
// for Rayleigh and Mie.
float opticalDepth(const float r, const float mu, const float H) {
float r2 = r*r;
// Is ray below horizon? The transmittance table will have only
// the values for transmittance starting at r (x) until the
// light ray touches the atmosphere or the ground and only for
// view angles v between 0 and pi/2 + eps. That's because we
// can calculate the transmittance for angles bigger than pi/2
// just inverting the ray direction and starting and ending points.
// cosine law for triangles: y_i^2 = a^2 + b^2 - 2abcos(alpha)
float cosZenithHorizon = -sqrt( 1.0f - ( ( 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 deltaStep = b_a / float(TRANSMITTANCE_STEPS);
// cosine law
float y_i = exp(-(r - Rg) / H);
float x_step = 0.0f;
float accumulation = 0.0f;
for (int i = 1; i <= TRANSMITTANCE_STEPS; ++i) {
float x_i = float(i) * deltaStep;
// cosine law for triangles: y_i^2 = a^2 + b^2 - 2abcos(alpha)
// In this case, a = r, b = x_i and cos(alpha) = cos(PI-zenithView) = mu
float y_ii = exp(-(sqrt(r2 + x_i * x_i + 2.0 * x_i * r * mu) - Rg) / H);
accumulation += (y_ii + y_i);
//x_step = x_i;
y_i = y_ii;
}
return accumulation * ( b_a / ( 2 * TRANSMITTANCE_STEPS ) );
}
void main(void) {
float r, muSun;
unmappingRAndMu(r, muSun);
vec3 opDepth = vec3(0.0);
if (ozoneLayerEnabled) {
opDepth = betaOzoneExtinction * (0.0000006) * opticalDepth(r, muSun, HO) +
betaMieExtinction * opticalDepth(r, muSun, HM) +
betaRayleigh * opticalDepth(r, muSun, HR);
} else {
opDepth = betaMieExtinction * opticalDepth(r, muSun, HM) +
betaRayleigh * opticalDepth(r, muSun, HR);
}
renderTableColor = vec4( exp( -opDepth ), 0.0f );
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec4 in_position;
void main() {
gl_Position = in_position;
}
@@ -243,6 +243,9 @@ void RenderablePlane::render(const RenderData& data, RendererTasks&) {
_shader->setUniform("modelViewProjectionTransform",
data.camera.projectionMatrix() * glm::mat4(modelViewTransform));
_shader->setUniform("modelViewTransform",
glm::mat4(data.camera.combinedViewMatrix() * glm::dmat4(modelViewTransform)));
ghoul::opengl::TextureUnit unit;
unit.activate();
_texture->bind();
+62 -11
View File
@@ -84,6 +84,19 @@ namespace {
"This value determines percentage of the sphere is visible before starting "
"fading-out it."
};
static const openspace::properties::Property::PropertyInfo FadeInThreshouldInfo = {
"FadeInThreshould",
"Fade-In Threshould",
"Distance from center of MilkyWay from where the astronomical object starts to "
"fade in."
};
static const openspace::properties::Property::PropertyInfo DisableFadeInOuInfo = {
"DisableFadeInOu",
"Disable Fade-In/Fade-Out effects",
"Enables/Disables the Fade-In/Out effects."
};
} // namespace
namespace openspace {
@@ -129,7 +142,19 @@ documentation::Documentation RenderableSphere::Documentation() {
new DoubleInRangeVerifier(0.0, 1.0),
Optional::Yes,
FadeOutThreshouldInfo.description
}
},
{
FadeInThreshouldInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FadeInThreshouldInfo.description
},
{
DisableFadeInOuInfo.identifier,
new BoolVerifier,
Optional::Yes,
DisableFadeInOuInfo.description
},
}
};
}
@@ -142,7 +167,9 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
, _size(SizeInfo, 1.f, 0.f, 1e35f)
, _segments(SegmentsInfo, 8, 4, 1000)
, _transparency(TransparencyInfo, 1.f, 0.f, 1.f)
, _disableFadeInDistance(DisableFadeInOuInfo, true)
, _fadeOutThreshold(-1.0)
, _fadeInThreshold(0.0)
, _shader(nullptr)
, _texture(nullptr)
, _sphere(nullptr)
@@ -211,7 +238,19 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
if (dictionary.hasKey(FadeOutThreshouldInfo.identifier)) {
_fadeOutThreshold = static_cast<float>(
dictionary.value<double>(FadeOutThreshouldInfo.identifier)
);
);
}
if (dictionary.hasKey(FadeInThreshouldInfo.identifier)) {
_fadeInThreshold = static_cast<float>(
dictionary.value<double>(FadeInThreshouldInfo.identifier)
);
}
if (dictionary.hasKey(FadeOutThreshouldInfo.identifier) ||
dictionary.hasKey(FadeInThreshouldInfo.identifier)) {
_disableFadeInDistance.set(false);
addProperty(_disableFadeInDistance);
}
}
@@ -260,23 +299,35 @@ void RenderableSphere::render(const RenderData& data, RendererTasks&) {
setPscUniforms(*_shader.get(), data.camera, data.position);
float adjustedTransparency = _transparency;
if (_fadeInThreshold > 0.0) {
float distCamera = glm::length(data.camera.positionVec3());
float funcValue = static_cast<float>(
(1.0 / double(_fadeInThreshold/1E24))*(distCamera / 1E24)
);
adjustedTransparency *= funcValue > 1.0 ? 1.0 : funcValue;
}
if (_fadeOutThreshold > -1.0) {
double distCamera = glm::distance(
float distCamera = glm::distance(
data.camera.positionVec3(),
data.position.dvec3()
);
double term = std::exp(
(-distCamera + _size * _fadeOutThreshold) / (_size * _fadeOutThreshold)
);
adjustedTransparency *= static_cast<float>(term / (term + 1.0));
}
// Performance wise
if (adjustedTransparency < 0.01) {
return;
}
_shader->setUniform(
"alpha",
_transparency * static_cast<float>(term / (term + 1.0))
);
}
else {
_shader->setUniform("alpha", _transparency);
}
_shader->setUniform("alpha", adjustedTransparency);
ghoul::opengl::TextureUnit unit;
unit.activate();
@@ -70,7 +70,10 @@ private:
properties::FloatProperty _transparency;
properties::BoolProperty _disableFadeInDistance;
float _fadeOutThreshold;
float _fadeInThreshold;
std::unique_ptr<ghoul::opengl::ProgramObject> _shader;
std::unique_ptr<ghoul::opengl::Texture> _texture;
+2 -2
View File
@@ -250,7 +250,7 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) {
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale));
_programObject->setUniform("projectionTransform", data.camera.projectionMatrix());
_programObject->setUniform("color", _lineColor);
_programObject->setUniform("useLineFade", _useLineFade);
if (_useLineFade) {
@@ -270,7 +270,7 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) {
if (usingFramebufferRenderer) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
bool renderLines =
+6 -2
View File
@@ -26,12 +26,16 @@
#include "PowerScaling/powerScaling_fs.hglsl"
in float vs_screenSpaceDepth;
in vec4 vs_positionViewSpace;
uniform vec4 gridColor;
Fragment getFragment() {
Fragment frag;
frag.color = gridColor;
frag.depth = vs_screenSpaceDepth;
frag.color = gridColor;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionViewSpace;
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
+6 -3
View File
@@ -29,14 +29,17 @@
layout(location = 0) in vec3 in_position;
out float vs_screenSpaceDepth;
out vec4 vs_positionViewSpace;
uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
void main() {
vec4 positionClipSpace = projectionTransform * modelViewTransform * vec4(in_position, 1.0);
vec4 positionViewSpace = modelViewTransform * vec4(in_position, 1.0);
vec4 positionClipSpace = projectionTransform * positionViewSpace;
vec4 positionScreenSpace = z_normalization(positionClipSpace);
vs_screenSpaceDepth = positionScreenSpace.w;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_positionViewSpace = positionViewSpace;
gl_Position = positionScreenSpace;
}
+8
View File
@@ -26,6 +26,8 @@
in float vs_screenSpaceDepth;
in vec2 vs_st;
in vec4 vs_gPosition;
in vec3 vs_gNormal;
uniform sampler2D texture1;
uniform bool additiveBlending;
@@ -49,5 +51,11 @@ Fragment getFragment() {
if (additiveBlending) {
frag.blend = BLEND_MODE_ADDITIVE;
}
// G-Buffer
frag.gOtherData = vec4(frag.color.xyz, 1.0);
frag.gPosition = vs_gPosition;
frag.gNormal = vec4(vs_gNormal, 1.0);
return frag;
}
+8 -1
View File
@@ -32,9 +32,12 @@ layout(location = 1) in vec2 in_st;
out vec2 vs_st;
out float vs_screenSpaceDepth;
out vec4 vs_positionScreenSpace;
// G-Buffer
out vec4 vs_gPosition;
out vec3 vs_gNormal;
uniform mat4 modelViewProjectionTransform;
uniform mat4 modelViewTransform;
void main() {
vec4 position = vec4(in_position.xyz * pow(10, in_position.w), 1);
@@ -43,6 +46,10 @@ void main() {
gl_Position = positionScreenSpace;
// G-Buffer
vs_gNormal = vec3(0.0);
vs_gPosition = vec4(modelViewTransform * position); // Must be in SGCT eye space;
vs_st = in_st;
vs_screenSpaceDepth = positionScreenSpace.w;
}
@@ -25,6 +25,7 @@
#include "fragment.glsl"
in vec4 vs_positionScreenSpace;
in vec4 vs_gPosition;
in float fade;
uniform vec3 color;
@@ -50,5 +51,12 @@ Fragment getFragment() {
frag.color.a *= 1.0 - smoothstep(1.0 - Delta, 1.0, dot(circCoord, circCoord));
}
// G-Buffer
frag.gOtherData = vec4(frag.color.xyz, 1.0);
frag.gPosition = vs_gPosition;
// There is no normal here
// TODO: Add the correct normal if necessary (JCC)
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
+3 -3
View File
@@ -29,6 +29,7 @@
layout(location = 0) in vec3 in_point_position;
out vec4 vs_positionScreenSpace;
out vec4 vs_gPosition;
out float fade;
uniform dmat4 modelViewTransform;
@@ -70,9 +71,8 @@ void main() {
fade = 1.0;
}
vs_positionScreenSpace = z_normalization(
projectionTransform * vec4(modelViewTransform * dvec4(in_point_position, 1))
);
vs_gPosition = vec4(modelViewTransform * dvec4(in_point_position, 1));
vs_positionScreenSpace = z_normalization(projectionTransform * vs_gPosition);
gl_PointSize = (stride == 1 || int(modId) % stride == 0) ? float(pointSize) : float(pointSize) / 2;
gl_Position = vs_positionScreenSpace;
+11 -3
View File
@@ -27,6 +27,7 @@
in vec2 vs_st;
in vec4 vs_position;
in vec4 vs_gPosition;
uniform float time;
uniform sampler2D texture1;
@@ -35,7 +36,6 @@ uniform float alpha;
Fragment getFragment() {
vec4 position = vs_position;
vec2 texCoord = vs_st;
// Why is this here? ---abock
texCoord.s = 1 - texCoord.s;
@@ -43,6 +43,14 @@ Fragment getFragment() {
Fragment frag;
frag.color = texture(texture1, texCoord) * vec4(1.0, 1.0, 1.0, alpha);
frag.depth = pscDepth(position);;
frag.depth = pscDepth(position);
// G-Buffer
frag.gOtherData = vec4(frag.color.xyz, 1.0);
frag.gPosition = vs_gPosition;
// There is no normal here
// TODO: Add the correct normal (JCC)
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
}
+5 -2
View File
@@ -32,6 +32,7 @@ layout(location = 1) in vec2 in_st;
out vec2 vs_st;
out vec4 vs_position;
out float s;
out vec4 vs_gPosition;
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
@@ -45,11 +46,13 @@ void main() {
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0) * ModelTransform;
vec4 position = pscTransform(tmp, mt);
vs_position = tmp;
vs_st = in_st;
vec4 position = pscTransform(tmp, mt);
vs_gPosition = position;
position = ViewProjection * position;
gl_Position = z_normalization(position);
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
out vec4 renderTableColor;
void main() {
renderTableColor = vec4(0.0);
}
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout(location = 0) in vec3 in_position;
void main() {
gl_Position = vec4(in_position, 1.0);
}
@@ -161,11 +161,47 @@ namespace {
"astronomical objects."
};
static const openspace::properties::Property::PropertyInfo TransformationMatrixInfo =
{
"TransformationMatrix",
"Transformation Matrix",
"Transformation matrix to be applied to each astronomical object."
};
static const openspace::properties::Property::PropertyInfo RenderOptionInfo = {
"RenderOptionInfo",
"Render Option",
"Debug option for rendering of billboards and texts."
};
static const openspace::properties::Property::PropertyInfo FadeInDistancesInfo = {
"FadeInDistances",
"Fade-In Start and End Distances",
"These values determine the initial and final distances from the center of "
"our galaxy from which the astronomical object will start and end "
"fading-in."
};
static const openspace::properties::Property::PropertyInfo DisableFadeInInfo = {
"DisableFadeIn",
"Disable Fade-in effect",
"Enables/Disables the Fade-in effect."
};
static const openspace::properties::Property::PropertyInfo BillboardMaxSizeInfo = {
"BillboardMaxSize",
"Billboard Max Size in Pixels",
"The max size (in pixels) for the billboard representing the astronomical "
"object."
};
static const openspace::properties::Property::PropertyInfo BillboardMinSizeInfo = {
"BillboardMinSize",
"Billboard Min Size in Pixels",
"The min size (in pixels) for the billboard representing the astronomical "
"object."
};
} // namespace
namespace openspace {
@@ -271,6 +307,36 @@ documentation::Documentation RenderableBillboardsCloud::Documentation() {
new Vector2ListVerifier<float>,
Optional::Yes,
ColorRangeInfo.description
},
{
TransformationMatrixInfo.identifier,
new Matrix4x4Verifier<double>,
Optional::Yes,
TransformationMatrixInfo.description
},
{
FadeInDistancesInfo.identifier,
new Vector2Verifier<double>,
Optional::Yes,
FadeInDistancesInfo.description
},
{
DisableFadeInInfo.identifier,
new BoolVerifier,
Optional::Yes,
DisableFadeInInfo.description
},
{
BillboardMaxSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
BillboardMaxSizeInfo.description
},
{
BillboardMinSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
BillboardMinSizeInfo.description
}
}
};
@@ -306,6 +372,10 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
, _drawElements(DrawElementsInfo, true)
, _drawLabels(DrawLabelInfo, false)
, _colorOption(ColorOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _fadeInDistance(FadeInDistancesInfo, glm::vec2(0.0f), glm::vec2(0.0), glm::vec2(100.0))
, _disableFadeInDistance(DisableFadeInInfo, true)
, _billboardMaxSize(BillboardMaxSizeInfo, 400.0, 0.0, 1000.0)
, _billboardMinSize(BillboardMinSizeInfo, 0.0, 0.0, 100.0)
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _polygonTexture(nullptr)
, _spriteTexture(nullptr)
@@ -317,6 +387,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
, _labelFile("")
, _colorOptionString("")
, _unit(Parsec)
, _transformationMatrix(glm::dmat4(1.0))
, _nValuesPerAstronomicalObject(0)
, _vao(0)
, _vbo(0)
@@ -460,7 +531,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
_labelFile = absPath(dictionary.value<std::string>(
LabelFileInfo.identifier
));
));
_hasLabel = true;
if (dictionary.hasKey(TextColorInfo.identifier)) {
@@ -479,7 +550,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
_textMinSize = static_cast<int>(dictionary.value<float>(LabelMinSizeInfo.identifier));
}
}
addProperty(_textMinSize);
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
@@ -487,6 +558,37 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
}
addProperty(_textMaxSize);
}
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
_transformationMatrix = dictionary.value<glm::dmat4>(
TransformationMatrixInfo.identifier
);
}
if (dictionary.hasKey(FadeInDistancesInfo.identifier)) {
glm::vec2 fadeInValue = dictionary.value<glm::vec2>(
FadeInDistancesInfo.identifier
);
_fadeInDistance.set(fadeInValue);
_disableFadeInDistance.set(false);
addProperty(_fadeInDistance);
addProperty(_disableFadeInDistance);
}
if (dictionary.hasKey(BillboardMaxSizeInfo.identifier)) {
_billboardMaxSize = static_cast<float>(
dictionary.value<double>(BillboardMaxSizeInfo.identifier)
);
addProperty(_billboardMaxSize);
}
if (dictionary.hasKey(BillboardMinSizeInfo.identifier)) {
_billboardMinSize = static_cast<float>(
dictionary.value<double>(BillboardMinSizeInfo.identifier)
);
addProperty(_billboardMinSize);
}
}
bool RenderableBillboardsCloud::isReady() const {
@@ -554,8 +656,13 @@ void RenderableBillboardsCloud::deinitializeGL() {
}
}
void RenderableBillboardsCloud::renderBillboards(const RenderData& data, const glm::dmat4& modelViewMatrix,
const glm::dmat4& projectionMatrix, const glm::vec3& orthoRight, const glm::vec3& orthoUp) {
void RenderableBillboardsCloud::renderBillboards(const RenderData& data,
const glm::dmat4& modelViewMatrix,
const glm::dmat4& worldToModelTransform,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
glDepthMask(false);
// Saving current OpenGL state
@@ -583,18 +690,28 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data, const g
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_program->setIgnoreUniformLocationError(IgnoreError::Yes);
glm::dmat4 projMatrix = glm::dmat4(data.camera.projectionMatrix());
_program->setUniform("screenSize", glm::vec2(OsEng.renderEngine().renderingResolution()));
_program->setUniform("projection", projectionMatrix);
_program->setUniform("projection", projMatrix);
_program->setUniform("modelViewTransform", modelViewMatrix);
_program->setUniform("modelViewProjectionTransform", glm::dmat4(projectionMatrix) * modelViewMatrix);
_program->setUniform("modelViewProjectionTransform", projMatrix * modelViewMatrix);
_program->setUniform("cameraPosition", glm::dvec3(worldToModelTransform *
glm::dvec4(data.camera.positionVec3(), 1.0)));
_program->setUniform("cameraLookUp", glm::dvec3(worldToModelTransform *
glm::dvec4(data.camera.lookUpVectorWorldSpace(), 1.0)));
//_program->setUniform("cameraPosition", data.camera.positionVec3());
//_program->setUniform("cameraLookUp", data.camera.lookUpVectorWorldSpace());
_program->setUniform("cameraPosition", data.camera.positionVec3());
_program->setUniform("cameraLookUp", data.camera.lookUpVectorWorldSpace());
_program->setUniform("renderOption", _renderOption.value());
glm::dvec4 centerScreenWorld = glm::inverse(data.camera.combinedViewMatrix()) * glm::dvec4(0.0, 0.0, 0.0, 1.0);
glm::dvec4 centerScreenWorld = glm::inverse(data.camera.combinedViewMatrix()) *
glm::dvec4(0.0, 0.0, 0.0, 1.0);
_program->setUniform("centerScreenInWorldPosition", centerScreenWorld);
_program->setUniform("minBillboardSize", 1.f); // in pixels
_program->setUniform("minBillboardSize", _billboardMinSize); // in pixels
_program->setUniform("maxBillboardSize", _billboardMaxSize); // in pixels
_program->setUniform("color", _pointColor);
_program->setUniform("sides", 4);
_program->setUniform("alphaValue", _alphaValue);
@@ -603,6 +720,13 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data, const g
_program->setUniform("up", orthoUp);
_program->setUniform("right", orthoRight);
_program->setUniform("fadeInValue", fadeInVariable);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
_program->setUniform("screenSize", glm::vec2(viewport[2], viewport[3]));
ghoul::opengl::TextureUnit spriteTextureUnit;
if (_hasSpriteTexture) {
spriteTextureUnit.activate();
@@ -647,8 +771,12 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data, const g
}
void RenderableBillboardsCloud::renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp) {
void RenderableBillboardsCloud::renderLabels(const RenderData& data,
const glm::dmat4& modelViewProjectionMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
RenderEngine& renderEngine = OsEng.renderEngine();
_fontRenderer->setFramebufferSize(renderEngine.renderingResolution());
@@ -678,6 +806,8 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data, const glm::
break;
}
glm::vec4 textColor = _textColor;
textColor.a *= fadeInVariable;
for (const std::pair<glm::vec3, std::string>& pair : _labelData) {
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
glm::vec3 scaledPos(pair.first);
@@ -685,7 +815,7 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data, const glm::
_fontRenderer->render(
*_font,
scaledPos,
_textColor,
textColor,
pow(10.0, _textSize.value()),
_textMinSize,
_textMaxSize,
@@ -701,6 +831,58 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data, const glm::
}
void RenderableBillboardsCloud::render(const RenderData& data, RendererTasks&) {
float scale = 0.0;
switch (_unit) {
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
}
float fadeInVariable = 1.0f;
if (!_disableFadeInDistance) {
float distCamera = glm::length(data.camera.positionVec3());
/*
// Linear Fading
float funcValue = static_cast<float>((1.0 / double(_fadeInDistance*scale))*(distCamera));
fadeInVariable *= funcValue > 1.0 ? 1.0 : funcValue;
if (funcValue < 0.01) {
return;
}
*/
glm::vec2 fadeRange = _fadeInDistance;
float a = 1.0f / ((fadeRange.y - fadeRange.x) * scale);
float b = -(fadeRange.x / (fadeRange.y - fadeRange.x));
float funcValue = a * distCamera + b;
fadeInVariable *= funcValue > 1.0 ? 1.0 : funcValue;
if (funcValue < 0.01) {
return;
}
}
glm::dmat4 modelMatrix =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation
glm::dmat4(data.modelTransform.rotation) * // Spice rotation
@@ -709,24 +891,59 @@ void RenderableBillboardsCloud::render(const RenderData& data, RendererTasks&) {
glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix;
glm::mat4 viewMatrix = data.camera.viewMatrix();
glm::mat4 projectionMatrix = data.camera.projectionMatrix();
glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) * modelViewMatrix;
glm::vec3 lookup = data.camera.lookUpVectorWorldSpace();
glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace();
glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) *
modelViewMatrix;
glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix);
/*glm::dmat4 internalCameraMatrix = data.camera.viewRotationMatrix() *
glm::inverse(glm::translate(glm::dmat4(1.0), data.camera.positionVec3()));
glm::dmat4 invInternalCameraMatrix = glm::inverse(internalCameraMatrix);
glm::vec3 lookup = worldToModelTransform * invInternalCameraMatrix * glm::dvec4(data.camera.lookUpVectorWorldSpace(), 0.0);
glm::vec3 viewDirection = worldToModelTransform * invInternalCameraMatrix * glm::dvec4(data.camera.viewDirectionWorldSpace(), 0.0);
glm::vec3 right = glm::cross(viewDirection, lookup);
glm::vec3 up = glm::cross(right, viewDirection);
glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix);
glm::vec3 orthoRight = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)));
glm::vec3 orthoUp = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(up, 0.0)));
glm::vec3 orthoRight = glm::normalize(right);
glm::vec3 orthoUp = glm::normalize(up);*/
/*
glm::dmat4 internalCameraMatrix = data.camera.viewRotationMatrix() *
glm::inverse(glm::translate(glm::dmat4(1.0), data.camera.positionVec3()));
glm::dmat4 invInternalCameraMatrix = glm::inverse(internalCameraMatrix);
glm::dvec4 lookup = worldToModelTransform * glm::dvec4(data.camera.lookUpVectorWorldSpace(), 0.0);
glm::dvec4 viewDirection = worldToModelTransform * glm::dvec4(data.camera.viewDirectionWorldSpace(), 0.0);
glm::vec3 right = glm::cross(glm::vec3(viewDirection), glm::vec3(lookup));
glm::vec3 up = glm::cross(right, glm::vec3(viewDirection));
glm::vec3 orthoRight = glm::normalize(right);
glm::vec3 orthoUp = glm::normalize(up);
*/
// Almost Working
glm::dmat4 invMVPParts = worldToModelTransform * glm::inverse(data.camera.combinedViewMatrix()) *
glm::inverse(glm::dmat4(projectionMatrix));
glm::dvec3 orthoRight = glm::dvec3(glm::normalize(glm::dvec3(invMVPParts * glm::dvec4(1.0, 0.0, 0.0, 0.0))));
glm::dvec3 orthoUp = glm::dvec3(glm::normalize(glm::dvec3(invMVPParts * glm::dvec4(0.0, 1.0, 0.0, 0.0))));
if (_hasSpeckFile) {
renderBillboards(data, modelViewMatrix, projectionMatrix, orthoRight, orthoUp);
renderBillboards(
data,
modelViewMatrix,
worldToModelTransform,
orthoRight,
orthoUp,
fadeInVariable
);
}
if (_drawLabels && _hasLabel) {
renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp);
renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp, fadeInVariable);
}
}
@@ -1119,12 +1336,18 @@ bool RenderableBillboardsCloud::readLabelFile() {
dummy.clear();
while (str >> dummy) {
if (dummy == "#") {
break;
}
label += " " + dummy;
dummy.clear();
}
_labelData.push_back(std::make_pair(position, label));
glm::vec3 transformedPos = glm::vec3(
_transformationMatrix * glm::dvec4(position, 1.0)
);
_labelData.push_back(std::make_pair(transformedPos, label));
} while (!file.eof());
return true;
@@ -1247,13 +1470,20 @@ void RenderableBillboardsCloud::createDataSlice() {
}
}
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) {
glm::dvec4 transformedPos = glm::dvec4(_fullData[i + 0], _fullData[i + 1], _fullData[i + 2], 1.0);
float biggestCoord = -1.0f;
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) {
glm::dvec4 transformedPos = _transformationMatrix * glm::dvec4(
_fullData[i + 0],
_fullData[i + 1],
_fullData[i + 2],
1.0
);
glm::vec4 position(glm::vec3(transformedPos), static_cast<float>(_unit));
if (_hasColorMapFile) {
for (auto j = 0; j < 4; ++j) {
_slicedData.push_back(position[j]);
biggestCoord = biggestCoord < position[j] ? position[j] : biggestCoord;
}
// Finds from which bin to get the color.
// Note: the first color in the colormap file
@@ -1279,6 +1509,7 @@ void RenderableBillboardsCloud::createDataSlice() {
}
}
}
_fadeInDistance.setMaxValue(glm::vec2(10.0f * biggestCoord));
}
void RenderableBillboardsCloud::createPolygonTexture() {
@@ -1363,7 +1594,8 @@ void RenderableBillboardsCloud::renderPolygonGeometry(GLuint vao) {
ghoul::opengl::ProgramObject::Build("RenderableBillboardsCloud_Polygon",
absPath("${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_vs.glsl"),
absPath("${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_fs.glsl"),
absPath("${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_gs.glsl"));
absPath("${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_gs.glsl")
);
program->activate();
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
@@ -31,6 +31,7 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec2property.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
@@ -90,9 +91,10 @@ private:
void loadPolygonGeometryForRendering();
void renderPolygonGeometry(GLuint vao);
void renderBillboards(const RenderData& data, const glm::dmat4& modelViewMatrix,
const glm::dmat4& projectionMatrix, const glm::vec3& orthoRight, const glm::vec3& orthoUp);
const glm::dmat4& worldToModelTransform, const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp, float fadeInVariable);
void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp);
const glm::dvec3& orthoRight, const glm::dvec3& orthoUp, float fadeInVariable);
bool loadData();
bool readSpeckFile();
@@ -126,6 +128,10 @@ private:
properties::BoolProperty _drawElements;
properties::BoolProperty _drawLabels;
properties::OptionProperty _colorOption;
properties::Vec2Property _fadeInDistance;
properties::BoolProperty _disableFadeInDistance;
properties::FloatProperty _billboardMaxSize;
properties::FloatProperty _billboardMinSize;
// DEBUG:
properties::OptionProperty _renderOption;
@@ -152,9 +158,11 @@ private:
std::unordered_map<std::string, int> _variableDataPositionMap;
std::unordered_map<int, std::string> _optionConversionMap;
std::vector<glm::vec2> _colorRangeData;
int _nValuesPerAstronomicalObject;
glm::dmat4 _transformationMatrix;
GLuint _vao;
GLuint _vbo;
@@ -127,7 +127,8 @@ namespace {
"Determines whether labels should be drawn or hidden."
};
static const openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
static const openspace::properties::Property::PropertyInfo TransformationMatrixInfo =
{
"TransformationMatrix",
"Transformation Matrix",
"Transformation matrix to be applied to each astronomical object."
@@ -163,8 +164,8 @@ documentation::Documentation RenderableDUMeshes::Documentation() {
KeyFile,
new StringVerifier,
Optional::No,
"The path to the SPECK file that contains information about the astronomical "
"object being rendered."
"The path to the SPECK file that contains information about the "
"astronomical object being rendered."
},
{
keyColor,
@@ -243,12 +244,9 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
, _dataIsDirty(true)
, _textColorIsDirty(true)
, _hasLabel(false)
, _labelDataIsDirty(true)
, _textMinSize(0)
, _textMaxSize(200)
, _labelDataIsDirty(true)
, _alphaValue(TransparencyInfo, 1.f, 0.f, 1.f)
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 64.f)
//, _pointColor(ColorInfo, glm::vec3(1.f, 0.4f, 0.2f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.0f, 1.0f, 1.0f))
, _textColor(
TextColorInfo,
glm::vec4(1.0f, 1.0, 1.0f, 1.f),
@@ -258,6 +256,8 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
, _textSize(TextSizeInfo, 8.0, 0.5, 24.0)
, _drawElements(DrawElementsInfo, true)
, _drawLabels(DrawLabelInfo, false)
, _textMinSize(LabelMinSizeInfo, 8.0, 0.5, 24.0)
, _textMaxSize(LabelMaxSizeInfo, 500.0, 0.0, 1000.0)
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _program(nullptr)
, _fontRenderer(nullptr)
@@ -361,22 +361,30 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
addProperty(_textSize);
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
_textMinSize = static_cast<int>(dictionary.value<float>(LabelMinSizeInfo.identifier));
_textMinSize = static_cast<int>(
dictionary.value<float>(LabelMinSizeInfo.identifier)
);
}
addProperty(_textMinSize);
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
_textMaxSize = static_cast<int>(dictionary.value<float>(LabelMaxSizeInfo.identifier));
_textMaxSize = static_cast<int>(
dictionary.value<float>(LabelMaxSizeInfo.identifier)
);
}
addProperty(_textMaxSize);
}
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
_transformationMatrix = dictionary.value<glm::dmat4>(TransformationMatrixInfo.identifier);
_transformationMatrix = dictionary.value<glm::dmat4>(
TransformationMatrixInfo.identifier
);
}
if (dictionary.hasKey(MeshColorInfo.identifier)) {
ghoul::Dictionary colorDic = dictionary.value<ghoul::Dictionary>(
MeshColorInfo.identifier
);
);
for (int i = 0; i < static_cast<int>(colorDic.size()); ++i) {
_meshColorMap.insert({ i + 1,
colorDic.value<glm::vec3>(std::to_string(i + 1)) });
@@ -386,7 +394,8 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
}
bool RenderableDUMeshes::isReady() const {
return (_program != nullptr) && (!_renderingMeshesMap.empty() || (!_labelData.empty()));
return (_program != nullptr) &&
(!_renderingMeshesMap.empty() || (!_labelData.empty()));
}
void RenderableDUMeshes::initializeGL() {
@@ -409,9 +418,13 @@ void RenderableDUMeshes::initializeGL() {
_fontRenderer = std::unique_ptr<ghoul::fontrendering::FontRenderer>(
ghoul::fontrendering::FontRenderer::createProjectionSubjectText());
if (_font == nullptr) {
size_t _fontSize = 30;
_font = OsEng.fontManager().font("Mono", static_cast<float>(_fontSize),
ghoul::fontrendering::FontManager::Outline::Yes, ghoul::fontrendering::FontManager::LoadGlyphs::No);
size_t _fontSize = 50;
_font = OsEng.fontManager().font(
"Mono",
static_cast<float>(_fontSize),
ghoul::fontrendering::FontManager::Outline::Yes,
ghoul::fontrendering::FontManager::LoadGlyphs::No
);
}
}
}
@@ -436,6 +449,9 @@ void RenderableDUMeshes::renderMeshes(const RenderData&,
const glm::dmat4& projectionMatrix)
{
// Saving current OpenGL state
GLfloat lineWidth = 1.0f;
glGetFloatv(GL_LINE_WIDTH, &lineWidth);
GLboolean blendEnabled = glIsEnabled(GL_BLEND);
GLenum blendEquationRGB;
GLenum blendEquationAlpha;
@@ -461,7 +477,8 @@ void RenderableDUMeshes::renderMeshes(const RenderData&,
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_program->setIgnoreUniformLocationError(IgnoreError::Yes);
_program->setUniform("modelViewProjectionTransform", glm::dmat4(projectionMatrix) * modelViewMatrix);
_program->setUniform("modelViewTransform", modelViewMatrix);
_program->setUniform("projectionTransform", projectionMatrix);
_program->setUniform("alphaValue", _alphaValue);
_program->setUniform("scaleFactor", _scaleFactor);
@@ -474,7 +491,9 @@ void RenderableDUMeshes::renderMeshes(const RenderData&,
case Solid:
break;
case Wire:
glLineWidth(2.0);
glDrawArrays(GL_LINE_STRIP, 0, pair.second.numV);
glLineWidth(lineWidth);
break;
case Point:
glDrawArrays(GL_POINTS, 0, pair.second.numV);
@@ -502,8 +521,11 @@ void RenderableDUMeshes::renderMeshes(const RenderData&,
}
}
void RenderableDUMeshes::renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp) {
void RenderableDUMeshes::renderLabels(const RenderData& data,
const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight,
const glm::vec3& orthoUp)
{
RenderEngine& renderEngine = OsEng.renderEngine();
_fontRenderer->setFramebufferSize(renderEngine.renderingResolution());
@@ -562,8 +584,8 @@ void RenderableDUMeshes::render(const RenderData& data, RendererTasks&) {
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale));
glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix;
glm::mat4 projectionMatrix = data.camera.projectionMatrix();
glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) * modelViewMatrix;
glm::dmat4 projectionMatrix = data.camera.projectionMatrix();
glm::dmat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
glm::vec3 lookup = data.camera.lookUpVectorWorldSpace();
glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace();
@@ -571,8 +593,12 @@ void RenderableDUMeshes::render(const RenderData& data, RendererTasks&) {
glm::vec3 up = glm::cross(right, viewDirection);
glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix);
glm::vec3 orthoRight = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)));
glm::vec3 orthoUp = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(up, 0.0)));
glm::vec3 orthoRight = glm::normalize(
glm::vec3(worldToModelTransform * glm::vec4(right, 0.0))
);
glm::vec3 orthoUp = glm::normalize(
glm::vec3(worldToModelTransform * glm::vec4(up, 0.0))
);
if (_hasSpeckFile) {
renderMeshes(data, modelViewMatrix, projectionMatrix);
@@ -858,7 +884,9 @@ bool RenderableDUMeshes::readLabelFile() {
dummy.clear();
}
glm::vec3 transformedPos = glm::vec3(_transformationMatrix * glm::dvec4(position, 1.0));
glm::vec3 transformedPos = glm::vec3(
_transformationMatrix * glm::dvec4(position, 1.0)
);
_labelData.push_back(std::make_pair(transformedPos, label));
} while (!file.eof());
@@ -880,7 +908,10 @@ bool RenderableDUMeshes::loadCachedFile(const std::string& file) {
int32_t nValues = 0;
fileStream.read(reinterpret_cast<char*>(&nValues), sizeof(int32_t));
fileStream.read(reinterpret_cast<char*>(&_nValuesPerAstronomicalObject), sizeof(int32_t));
fileStream.read(
reinterpret_cast<char*>(&_nValuesPerAstronomicalObject),
sizeof(int32_t)
);
_fullData.resize(nValues);
fileStream.read(reinterpret_cast<char*>(&_fullData[0]),
@@ -908,8 +939,13 @@ bool RenderableDUMeshes::saveCachedFile(const std::string& file) const {
}
fileStream.write(reinterpret_cast<const char*>(&nValues), sizeof(int32_t));
int32_t nValuesPerAstronomicalObject = static_cast<int32_t>(_nValuesPerAstronomicalObject);
fileStream.write(reinterpret_cast<const char*>(&nValuesPerAstronomicalObject), sizeof(int32_t));
int32_t nValuesPerAstronomicalObject = static_cast<int32_t>(
_nValuesPerAstronomicalObject
);
fileStream.write(
reinterpret_cast<const char*>(&nValuesPerAstronomicalObject),
sizeof(int32_t)
);
size_t nBytes = nValues * sizeof(_fullData[0]);
fileStream.write(reinterpret_cast<const char*>(&_fullData[0]), nBytes);
@@ -927,34 +963,34 @@ void RenderableDUMeshes::createMeshes() {
if (_dataIsDirty && _hasSpeckFile) {
LDEBUG("Creating planes");
std::unordered_map<int, RenderingMesh>::iterator it = _renderingMeshesMap.begin();
std::unordered_map<int, RenderingMesh>::iterator itEnd = _renderingMeshesMap.end();
std::unordered_map<int, RenderingMesh>::iterator itEnd =
_renderingMeshesMap.end();
for (; it != itEnd; ++it) {
float scale = 0.0;
switch (_unit) {
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
}
for (int v = 0; v < static_cast<int>(it->second.vertices.size()); ++v) {
@@ -971,12 +1007,17 @@ void RenderableDUMeshes::createMeshes() {
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//glBufferData(GL_ARRAY_BUFFER, it->second.numV * sizeof(GLfloat),
glBufferData(GL_ARRAY_BUFFER, it->second.vertices.size() * sizeof(GLfloat),
&it->second.vertices[0], GL_STATIC_DRAW);
glBufferData(
GL_ARRAY_BUFFER,
it->second.vertices.size() * sizeof(GLfloat),
&it->second.vertices[0],
GL_STATIC_DRAW
);
// in_position
glEnableVertexAttribArray(0);
// U and V may not be given by the user
if (it->second.vertices.size() / (it->second.numU * it->second.numV) > 3) {
if (it->second.vertices.size() / (it->second.numU * it->second.numV) > 3)
{
glVertexAttribPointer(
0,
3,
@@ -994,7 +1035,9 @@ void RenderableDUMeshes::createMeshes() {
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 7,
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 3 * i * it->second.numV)
reinterpret_cast<GLvoid*>(
sizeof(GLfloat) * 3 * i * it->second.numV
)
);
}
else { // no U and V:
@@ -1004,7 +1047,9 @@ void RenderableDUMeshes::createMeshes() {
GL_FLOAT,
GL_FALSE,
0,
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 3 * i * it->second.numV)
reinterpret_cast<GLvoid*>(
sizeof(GLfloat) * 3 * i * it->second.numV
)
);
}
}
@@ -1020,12 +1065,18 @@ void RenderableDUMeshes::createMeshes() {
glBindVertexArray(cvao);
glBindBuffer(GL_ARRAY_BUFFER, cvbo);
glBufferData(GL_ARRAY_BUFFER, it->second.vertices.size() * sizeof(GLfloat),
&it->second.vertices[0], GL_STATIC_DRAW);
glBufferData(
GL_ARRAY_BUFFER,
it->second.vertices.size() * sizeof(GLfloat),
&it->second.vertices[0],
GL_STATIC_DRAW
);
// in_position
glEnableVertexAttribArray(0);
// U and V may not be given by the user
if (it->second.vertices.size() / (it->second.numU * it->second.numV) > 3) {
if (it->second.vertices.size() /
(it->second.numU * it->second.numV) > 3)
{
glVertexAttribPointer(
0,
3,
@@ -1067,7 +1118,7 @@ void RenderableDUMeshes::createMeshes() {
if (_hasLabel && _labelDataIsDirty) {
_labelDataIsDirty = false;
}
}
}
} // namespace openspace
@@ -122,10 +122,7 @@ private:
bool _textColorIsDirty;
bool _hasLabel;
bool _labelDataIsDirty;
int _textMinSize;
int _textMaxSize;
properties::FloatProperty _alphaValue;
properties::FloatProperty _scaleFactor;
//properties::Vec3Property _pointColor;
@@ -134,6 +131,8 @@ private:
properties::BoolProperty _drawElements;
properties::BoolProperty _drawLabels;
//properties::OptionProperty _blendMode;
properties::FloatProperty _textMinSize;
properties::FloatProperty _textMaxSize;
// DEBUG:
properties::OptionProperty _renderOption;
@@ -40,7 +40,7 @@
#include <ghoul/font/fontrenderer.h>
#include <glm/gtx/string_cast.hpp>
#include <glm/glm.hpp>
#include <ghoul/glm.h>
#include <array>
#include <fstream>
@@ -121,7 +121,8 @@ namespace {
"Enables/Disables the drawing of the astronomical objects."
};
static const openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
static const openspace::properties::Property::PropertyInfo TransformationMatrixInfo =
{
"TransformationMatrix",
"Transformation Matrix",
"Transformation matrix to be applied to each astronomical object."
@@ -157,6 +158,26 @@ namespace {
"Debug option for rendering of billboards and texts."
};
static const openspace::properties::Property::PropertyInfo FadeInDistancesInfo = {
"FadeInDistances",
"Fade-In Start and End Distances",
"These values determine the initial and final distances from the center of "
"our galaxy from which the astronomical object will start and end "
"fading-in."
};
static const openspace::properties::Property::PropertyInfo DisableFadeInInfo = {
"DisableFadeIn",
"Disable Fade-in effect",
"Enables/Disables the Fade-in effect."
};
static const openspace::properties::Property::PropertyInfo PlaneMinSizeInfo = {
"PlaneMinSize",
"Plane Min Size in Pixels",
"The min size (in pixels) for the plane representing the astronomical "
"object."
};
} // namespace
@@ -177,8 +198,8 @@ documentation::Documentation RenderablePlanesCloud::Documentation() {
KeyFile,
new StringVerifier,
Optional::Yes,
"The path to the SPECK file that contains information about the astronomical "
"object being rendered."
"The path to the SPECK file that contains information about the "
"astronomical object being rendered."
},
{
TransparencyInfo.identifier,
@@ -252,6 +273,24 @@ documentation::Documentation RenderablePlanesCloud::Documentation() {
Optional::Yes,
ScaleFactorInfo.description,
},
{
FadeInDistancesInfo.identifier,
new Vector2Verifier<float>,
Optional::Yes,
FadeInDistancesInfo.description
},
{
DisableFadeInInfo.identifier,
new BoolVerifier,
Optional::Yes,
DisableFadeInInfo.description
},
{
PlaneMinSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
PlaneMinSizeInfo.description
},
}
};
}
@@ -279,6 +318,14 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
, _textSize(TextSizeInfo, 8.0, 0.5, 24.0)
, _drawElements(DrawElementsInfo, true)
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _fadeInDistance(
FadeInDistancesInfo,
glm::vec2(0.f),
glm::vec2(0.f),
glm::vec2(200000.f)
)
, _disableFadeInDistance(DisableFadeInInfo, true)
, _planeMinSize(PlaneMinSizeInfo, 0.5, 0.0, 500.0)
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _program(nullptr)
, _fontRenderer(nullptr)
@@ -311,6 +358,7 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
_renderOption.addOption(1, "Camera Position Normal");
_renderOption.addOption(2, "Screen center Position Normal");
addProperty(_renderOption);
//_renderOption.set(1);
if (dictionary.hasKey(keyUnit)) {
std::string unit = dictionary.value<std::string>(keyUnit);
@@ -383,16 +431,22 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
addProperty(_textSize);
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
_textMinSize = static_cast<int>(dictionary.value<float>(LabelMinSizeInfo.identifier));
}
_textMinSize = static_cast<int>(
dictionary.value<float>(LabelMinSizeInfo.identifier)
);
}
if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) {
_textMaxSize = static_cast<int>(dictionary.value<float>(LabelMaxSizeInfo.identifier));
_textMaxSize = static_cast<int>(
dictionary.value<float>(LabelMaxSizeInfo.identifier)
);
}
}
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
_transformationMatrix = dictionary.value<glm::dmat4>(TransformationMatrixInfo.identifier);
_transformationMatrix = dictionary.value<glm::dmat4>(
TransformationMatrixInfo.identifier
);
}
_blendMode.addOptions({
@@ -429,7 +483,26 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary
}
if (dictionary.hasKey(ScaleLuminosityInfo.identifier)) {
_sluminosity = static_cast<float>(dictionary.value<double>(ScaleLuminosityInfo.identifier));
_sluminosity = static_cast<float>(
dictionary.value<double>(ScaleLuminosityInfo.identifier)
);
}
if (dictionary.hasKey(FadeInDistancesInfo.identifier)) {
glm::vec2 fadeInValue = dictionary.value<glm::vec2>(
FadeInDistancesInfo.identifier
);
_fadeInDistance.set(fadeInValue);
_disableFadeInDistance.set(false);
addProperty(_fadeInDistance);
addProperty(_disableFadeInDistance);
}
if (dictionary.hasKey(PlaneMinSizeInfo.identifier)) {
_planeMinSize = static_cast<float>(
dictionary.value<double>(PlaneMinSizeInfo.identifier)
);
addProperty(_planeMinSize);
}
}
@@ -463,17 +536,21 @@ void RenderablePlanesCloud::initializeGL() {
ghoul::fontrendering::FontRenderer::createProjectionSubjectText());
if (_font == nullptr) {
size_t _fontSize = 30;
_font = OsEng.fontManager().font("Mono", static_cast<float>(_fontSize),
ghoul::fontrendering::FontManager::Outline::Yes, ghoul::fontrendering::FontManager::LoadGlyphs::No);
_font = OsEng.fontManager().font(
"Mono",
static_cast<float>(_fontSize),
ghoul::fontrendering::FontManager::Outline::Yes,
ghoul::fontrendering::FontManager::LoadGlyphs::No
);
}
}
}
void RenderablePlanesCloud::deleteDataGPU() {
for (auto pair : _renderingPlanesMap) {
glDeleteVertexArrays(1, &pair.second.vao);
glDeleteBuffers(1, &pair.second.vbo);
for (auto renderingPlane : _renderingPlanesArray) {
glDeleteVertexArrays(1, &renderingPlane.vao);
glDeleteBuffers(1, &renderingPlane.vbo);
}
}
@@ -489,7 +566,8 @@ void RenderablePlanesCloud::deinitializeGL() {
void RenderablePlanesCloud::renderPlanes(const RenderData&,
const glm::dmat4& modelViewMatrix,
const glm::dmat4& projectionMatrix)
const glm::dmat4& projectionMatrix,
const float fadeInVariable)
{
// Saving current OpenGL state
GLboolean blendEnabled = glIsEnabled(GL_BLEND);
@@ -517,34 +595,56 @@ void RenderablePlanesCloud::renderPlanes(const RenderData&,
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_program->setIgnoreUniformLocationError(IgnoreError::Yes);
_program->setUniform("modelViewProjectionTransform", glm::dmat4(projectionMatrix) * modelViewMatrix);
glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) * modelViewMatrix;
_program->setUniform("modelViewProjectionTransform", modelViewProjectionMatrix);
_program->setUniform("alphaValue", _alphaValue);
_program->setUniform("scaleFactor", _scaleFactor);
//_program->setUniform("minPlaneSize", 1.f); // in pixels
_program->setUniform("fadeInValue", fadeInVariable);
//bool usingFramebufferRenderer =
// OsEng.renderEngine().rendererImplementation() == RenderEngine::RendererImplementation::Framebuffer;
//bool usingABufferRenderer =
// OsEng.renderEngine().rendererImplementation() == RenderEngine::RendererImplementation::ABuffer;
//if (usingABufferRenderer) {
// _program->setUniform("additiveBlending", _blendMode == BlendModeAdditive);
//}
//bool additiveBlending = _blendMode == BlendModeAdditive && usingFramebufferRenderer;
//if (additiveBlending) {
// //glDepthMask(false);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
//}
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
for (auto pair : _renderingPlanesMap) {
ghoul::opengl::TextureUnit unit;
unit.activate();
_textureMap[pair.second.planeIndex]->bind();
_program->setUniform("galaxyTexture", unit);
ghoul::opengl::TextureUnit unit;
unit.activate();
_program->setUniform("galaxyTexture", unit);
int currentTextureIndex = -1;
for (auto renderingPlane : _renderingPlanesArray) {
// For planes with undefined textures references
if (renderingPlane.planeIndex == -1) {
continue;
}
glBindVertexArray(pair.second.vao);
glm::dvec4 vertex0(renderingPlane.vertexData[0], renderingPlane.vertexData[1],
renderingPlane.vertexData[2], renderingPlane.vertexData[3]);
glm::dvec4 vertex1(renderingPlane.vertexData[6], renderingPlane.vertexData[7],
renderingPlane.vertexData[8], renderingPlane.vertexData[9]);
vertex0 = modelViewProjectionMatrix * vertex0;
vertex1 = modelViewProjectionMatrix * vertex1;
// Testing size:
glm::vec4 topRight = vertex1 / vertex1.w;
topRight = ((topRight + glm::vec4(1.0)) / glm::vec4(2.0)) *
glm::vec4(viewport[2], viewport[3], 1.0, 1.0);
glm::vec4 bottomLeft = vertex0 / vertex0.w;
bottomLeft = ((bottomLeft + glm::vec4(1.0)) / glm::vec4(2.0)) *
glm::vec4(viewport[2], viewport[3], 1.0, 1.0);
float lengthY = std::fabs(topRight.y - bottomLeft.y);
float lengthX = std::fabs(topRight.x - bottomLeft.x);
float lengthXY = glm::length(glm::vec2(topRight) - glm::vec2(bottomLeft));
float biggestAxis =
lengthY > lengthX ? (lengthY > lengthXY ? lengthY : lengthXY) :
(lengthX > lengthXY ? lengthX : lengthXY);
if (biggestAxis < _planeMinSize ) {
continue;
}
if (currentTextureIndex != renderingPlane.planeIndex) {
_textureMap[renderingPlane.planeIndex]->bind();
currentTextureIndex = renderingPlane.planeIndex;
}
glBindVertexArray(renderingPlane.vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
@@ -570,37 +670,42 @@ void RenderablePlanesCloud::renderPlanes(const RenderData&,
}
}
void RenderablePlanesCloud::renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp) {
void RenderablePlanesCloud::renderLabels(const RenderData& data,
const glm::dmat4& modelViewProjectionMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp, float fadeInVariable)
{
RenderEngine& renderEngine = OsEng.renderEngine();
_fontRenderer->setFramebufferSize(renderEngine.renderingResolution());
float scale = 0.0;
switch (_unit) {
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
}
glm::vec4 textColor = _textColor;
textColor.a *= fadeInVariable;
for (const std::pair<glm::vec3, std::string>& pair : _labelData) {
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
glm::vec3 scaledPos(pair.first);
@@ -608,7 +713,8 @@ void RenderablePlanesCloud::renderLabels(const RenderData& data, const glm::dmat
_fontRenderer->render(
*_font,
scaledPos,
_textColor,
//_textColor,
textColor,
pow(10.0, _textSize.value()),
_textMinSize,
_textMaxSize,
@@ -625,6 +731,56 @@ void RenderablePlanesCloud::renderLabels(const RenderData& data, const glm::dmat
}
void RenderablePlanesCloud::render(const RenderData& data, RendererTasks&) {
double scale = 0.0;
switch (_unit) {
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
}
float fadeInVariable = 1.0f;
if (!_disableFadeInDistance) {
double distCamera = glm::length(data.camera.positionVec3());
//float funcValue = static_cast<float>(
//(1.0 / double(_fadeInDistance))*(distCamera / scale)
//);
//
//// Let's not waste performance
//if (funcValue < 0.01) {
// return;
//}
//fadeInVariable = funcValue > 1.0 ? 1.0 : funcValue;
glm::vec2 fadeRange = _fadeInDistance;
float a = 1.0f / ((fadeRange.y - fadeRange.x) * scale);
float b = -(fadeRange.x / (fadeRange.y - fadeRange.x));
float funcValue = a * distCamera + b;
fadeInVariable *= funcValue > 1.0 ? 1.0 : funcValue;
if (funcValue < 0.01) {
return;
}
}
glm::dmat4 modelMatrix =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation
glm::dmat4(data.modelTransform.rotation) * // Spice rotation
@@ -634,22 +790,36 @@ void RenderablePlanesCloud::render(const RenderData& data, RendererTasks&) {
glm::mat4 projectionMatrix = data.camera.projectionMatrix();
glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) * modelViewMatrix;
glm::vec3 lookup = data.camera.lookUpVectorWorldSpace();
glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace();
glm::vec3 right = glm::cross(viewDirection, lookup);
glm::vec3 up = glm::cross(right, viewDirection);
//glm::vec3 lookup = data.camera.lookUpVectorWorldSpace();
//glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace();
//glm::vec3 right = glm::cross(viewDirection, lookup);
//glm::vec3 up = glm::cross(right, viewDirection);
glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix);
glm::vec3 orthoRight = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)));
glm::vec3 orthoUp = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(up, 0.0)));
//glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix);
//glm::vec3 orthoRight = glm::normalize(
// glm::vec3(worldToModelTransform * glm::vec4(right, 0.0))
//);
//glm::vec3 orthoUp = glm::normalize(
// glm::vec3(worldToModelTransform * glm::vec4(up, 0.0))
//);
//glm::dmat4 invMVP = glm::inverse(modelViewProjectionMatrix);
glm::dmat4 invMVPParts = glm::inverse(modelMatrix) *
glm::inverse(data.camera.combinedViewMatrix()) *
glm::inverse(glm::dmat4(projectionMatrix));
glm::dvec3 orthoRight = glm::dvec3(
glm::normalize(glm::dvec3(invMVPParts * glm::dvec4(1.0, 0.0, 0.0, 0.0)))
);
glm::dvec3 orthoUp = glm::dvec3(
glm::normalize(glm::dvec3(invMVPParts * glm::dvec4(0.0, 1.0, 0.0, 0.0)))
);
if (_hasSpeckFile) {
renderPlanes(data, modelViewMatrix, projectionMatrix);
renderPlanes(data, modelViewMatrix, projectionMatrix, fadeInVariable);
}
if (_hasLabel) {
renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp);
renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp, fadeInVariable);
}
}
@@ -810,11 +980,13 @@ bool RenderablePlanesCloud::readSpeckFile() {
// +3 because of the x, y and z at the begining of each line.
_variableDataPositionMap.insert({ dummy, _nValuesPerAstronomicalObject + 3});
if (dummy == "orientation") { // 3d vectors u and v
_nValuesPerAstronomicalObject += 6; // We want the number, but the index is 0 based
if ((dummy == "orientation") || (dummy == "ori")) { // 3d vectors u and v
// We want the number, but the index is 0 based
_nValuesPerAstronomicalObject += 6;
}
else {
_nValuesPerAstronomicalObject += 1; // We want the number, but the index is 0 based
// We want the number, but the index is 0 based
_nValuesPerAstronomicalObject += 1;
}
}
@@ -841,10 +1013,18 @@ bool RenderablePlanesCloud::readSpeckFile() {
if (line.substr(0, 8) == "texture ") {
std::stringstream str(line);
std::size_t found = line.find("-");
int textureIndex = 0;
std::string dummy;
str >> dummy; // command
if (found != std::string::npos) {
std::string option; // Not being used right now.
str >> option;
}
str >> textureIndex;
str >> dummy; // texture file name
@@ -879,7 +1059,7 @@ bool RenderablePlanesCloud::readSpeckFile() {
for (int i = 0; i < _nValuesPerAstronomicalObject; ++i) {
str >> values[i];
if ((i >= _planeStartingIndexPos) &&
(i <= _planeStartingIndexPos+6)) { // vectors u and v
(i <= _planeStartingIndexPos + 6)) { // vectors u and v
int index = i - _planeStartingIndexPos;
switch (index) {
case 0:
@@ -993,7 +1173,9 @@ bool RenderablePlanesCloud::readLabelFile() {
dummy.clear();
}
glm::vec3 transformedPos = glm::vec3(_transformationMatrix * glm::dvec4(position, 1.0));
glm::vec3 transformedPos = glm::vec3(
_transformationMatrix * glm::dvec4(position, 1.0)
);
_labelData.push_back(std::make_pair(transformedPos, label));
} while (!file.eof());
@@ -1015,7 +1197,10 @@ bool RenderablePlanesCloud::loadCachedFile(const std::string& file) {
int32_t nValues = 0;
fileStream.read(reinterpret_cast<char*>(&nValues), sizeof(int32_t));
fileStream.read(reinterpret_cast<char*>(&_nValuesPerAstronomicalObject), sizeof(int32_t));
fileStream.read(reinterpret_cast<char*>(
&_nValuesPerAstronomicalObject),
sizeof(int32_t)
);
_fullData.resize(nValues);
fileStream.read(reinterpret_cast<char*>(&_fullData[0]),
@@ -1043,8 +1228,13 @@ bool RenderablePlanesCloud::saveCachedFile(const std::string& file) const {
}
fileStream.write(reinterpret_cast<const char*>(&nValues), sizeof(int32_t));
int32_t nValuesPerAstronomicalObject = static_cast<int32_t>(_nValuesPerAstronomicalObject);
fileStream.write(reinterpret_cast<const char*>(&nValuesPerAstronomicalObject), sizeof(int32_t));
int32_t nValuesPerAstronomicalObject = static_cast<int32_t>(
_nValuesPerAstronomicalObject
);
fileStream.write(reinterpret_cast<const char*>(
&nValuesPerAstronomicalObject),
sizeof(int32_t)
);
size_t nBytes = nValues * sizeof(_fullData[0]);
fileStream.write(reinterpret_cast<const char*>(&_fullData[0]), nBytes);
@@ -1061,7 +1251,7 @@ bool RenderablePlanesCloud::saveCachedFile(const std::string& file) const {
void RenderablePlanesCloud::createPlanes() {
if (_dataIsDirty && _hasSpeckFile) {
LDEBUG("Creating planes");
float maxSize = 0.0f;
int planeNumber = 0;
for (int p = 0; p < _fullData.size(); p += _nValuesPerAstronomicalObject) {
glm::vec4 transformedPos = glm::vec4(_transformationMatrix *
@@ -1086,7 +1276,8 @@ void RenderablePlanesCloud::createPlanes() {
v.w = 0.0;
if (!_luminosityVar.empty()) {
float lumS = _fullData[p + _variableDataPositionMap[_luminosityVar]] * _sluminosity;
float lumS = _fullData[p + _variableDataPositionMap[_luminosityVar]] *
_sluminosity;
u *= lumS;
v *= lumS;
}
@@ -1099,8 +1290,7 @@ void RenderablePlanesCloud::createPlanes() {
// JCC: Ask Abbott about these points refeering to a non-existing texture.
if (plane.planeIndex == 30) {
//std::cout << "--- Creating planes - index: " << plane.planeIndex << std::endl;
plane.planeIndex = 0;
plane.planeIndex = -1;
}
glGenVertexArrays(1, &plane.vao);
@@ -1136,11 +1326,18 @@ void RenderablePlanesCloud::createPlanes() {
break;
}
for (int i = 0; i < 3; ++i) {
maxSize = maxSize > vertex0[i] ? maxSize : vertex0[i];
maxSize = maxSize > vertex1[i] ? maxSize : vertex1[i];
maxSize = maxSize > vertex2[i] ? maxSize : vertex2[i];
maxSize = maxSize > vertex4[i] ? maxSize : vertex4[i];
}
vertex0 *= static_cast<float>(scale);
vertex1 *= static_cast<float>(scale);
vertex2 *= static_cast<float>(scale);
vertex4 *= static_cast<float>(scale);
vertex4 *= static_cast<float>(scale);
GLfloat vertexData[] = {
// x y z w s t
vertex0.x, vertex0.y, vertex0.z, 1.f, 0.f, 0.f,
@@ -1155,7 +1352,12 @@ void RenderablePlanesCloud::createPlanes() {
glBindVertexArray(plane.vao);
glBindBuffer(GL_ARRAY_BUFFER, plane.vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(plane.vertexData), plane.vertexData, GL_STATIC_DRAW);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(plane.vertexData),
plane.vertexData,
GL_STATIC_DRAW
);
// in_position
glEnableVertexAttribArray(0);
glVertexAttribPointer(
@@ -1178,18 +1380,29 @@ void RenderablePlanesCloud::createPlanes() {
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 4)
);
_renderingPlanesMap.insert({planeNumber++, plane});
_renderingPlanesArray.push_back(plane);
}
glBindVertexArray(0);
_dataIsDirty = false;
_fadeInDistance.setMaxValue(glm::vec2(10.0f * maxSize));
}
if (_hasLabel && _labelDataIsDirty) {
_labelDataIsDirty = false;
}
// Sort planes by texture index
if (!_renderingPlanesArray.empty()) {
std::sort(_renderingPlanesArray.begin(), _renderingPlanesArray.end(),
[](const RenderingPlane& planeA, const RenderingPlane& planeB) {
return planeA.planeIndex < planeB.planeIndex;
});
}
}
} // namespace openspace
@@ -31,6 +31,7 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec2property.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
@@ -93,9 +94,9 @@ namespace openspace {
void deleteDataGPU();
void createPlanes();
void renderPlanes(const RenderData& data, const glm::dmat4& modelViewMatrix,
const glm::dmat4& projectionMatrix);
const glm::dmat4& projectionMatrix, float fadeInVariable);
void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp);
const glm::dvec3& orthoRight, const glm::dvec3& orthoUp, float fadeInVarible);
bool loadData();
bool loadTextures();
@@ -121,6 +122,9 @@ namespace openspace {
properties::FloatProperty _textSize;
properties::BoolProperty _drawElements;
properties::OptionProperty _blendMode;
properties::Vec2Property _fadeInDistance;
properties::BoolProperty _disableFadeInDistance;
properties::FloatProperty _planeMinSize;
// DEBUG:
properties::OptionProperty _renderOption;
@@ -145,10 +149,10 @@ namespace openspace {
int _nValuesPerAstronomicalObject;
float _sluminosity;
glm::dmat4 _transformationMatrix;
std::unordered_map<int, RenderingPlane> _renderingPlanesMap;
std::vector<RenderingPlane> _renderingPlanesArray;
};
@@ -27,6 +27,7 @@
in vec4 gs_colorMap;
in float vs_screenSpaceDepth;
in vec2 texCoord;
in float ta;
uniform float alphaValue;
uniform vec3 color;
@@ -34,6 +35,7 @@ uniform sampler2D spriteTexture;
uniform sampler2D polygonTexture;
uniform bool hasColorMap;
uniform bool hasPolygon;
uniform float fadeInValue;
Fragment getFragment() {
@@ -50,13 +52,19 @@ Fragment getFragment() {
fullColor = vec4(color.rgb * textureColor.rgb, textureColor.a * alphaValue);
}
fullColor.a *= fadeInValue * ta;
if (fullColor.a == 0.f) {
discard;
}
Fragment frag;
frag.color = fullColor;
frag.depth = vs_screenSpaceDepth;
frag.color = fullColor;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vec4(1e32, 1e32, 1e32, 1.0);
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
@@ -32,19 +32,22 @@ layout(triangle_strip, max_vertices = 6) out;
//uniform dmat4 transformMatrix;
uniform dmat4 modelViewProjectionTransform;
uniform float scaleFactor;
uniform vec3 up;
uniform vec3 right;
uniform dvec3 up;
uniform dvec3 right;
uniform dvec3 cameraPosition;
uniform dvec3 cameraLookUp;
uniform dvec4 centerScreenInWorldPosition;
uniform int renderOption;
uniform vec2 screenSize;
uniform float maxBillboardSize;
uniform float minBillboardSize;
in vec4 colorMap[];
out vec4 gs_colorMap;
out vec2 texCoord;
out float vs_screenSpaceDepth;
out float ta;
const double PARSEC = 0.308567756e17LF;
@@ -57,27 +60,29 @@ const vec2 corners[4] = vec2[4](
void main() {
vec4 pos = gl_in[0].gl_Position;
ta = 1.0f;
vec4 pos = gl_in[0].gl_Position;
gs_colorMap = colorMap[0];
double scaleMultiply = exp(scaleFactor/10);
dvec3 scaledRight = dvec3(0.0);
dvec3 scaledUp = dvec3(0.0);
dvec3 scaledRight = dvec3(0.0);
dvec3 scaledUp = dvec3(0.0);
if (renderOption == 0) {
scaledRight = scaleMultiply * right/2.0f;
scaledUp = scaleMultiply * up/2.0f;
scaledUp = scaleMultiply * up/2.0f;
} else if (renderOption == 1) {
dvec3 normal = normalize(cameraPosition - dvec3(pos.xyz));
dvec3 normal = normalize(cameraPosition - dvec3(pos.xyz));
dvec3 newRight = normalize(cross(cameraLookUp, normal));
dvec3 newUp = cross(normal, newRight);
scaledRight = scaleMultiply * newRight/2.0f;
scaledUp = scaleMultiply * newUp/2.0f;
dvec3 newUp = cross(normal, newRight);
scaledRight = scaleMultiply * newRight/2.0f;
scaledUp = scaleMultiply * newUp/2.0f;
} else if (renderOption == 2) {
dvec3 normal = normalize(centerScreenInWorldPosition.xyz - dvec3(pos.xyz));
dvec3 normal = normalize(centerScreenInWorldPosition.xyz - dvec3(pos.xyz));
dvec3 newRight = normalize(cross(cameraLookUp, normal));
dvec3 newUp = cross(normal, newRight);
scaledRight = scaleMultiply * newRight/2.0f;
scaledUp = scaleMultiply * newUp/2.0f;
dvec3 newUp = cross(normal, newRight);
scaledRight = scaleMultiply * newRight/2.0f;
scaledUp = scaleMultiply * newUp/2.0f;
}
double unit = PARSEC;
@@ -100,32 +105,87 @@ void main() {
//dvec4 dpos = transformMatrix * dvec4(dvec3(pos.xyz) * unit, 1.0);
dvec4 dpos = dvec4(dvec3(pos.xyz) * unit, 1.0);
texCoord = corners[0];
vec4 initialPosition = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w)));
vs_screenSpaceDepth = initialPosition.w;
// texCoord = corners[0];
vec4 initialPosition = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w)));
vs_screenSpaceDepth = initialPosition.w;
// texCoord = corners[1];
vec4 secondPosition = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w)));
//texCoord = corners[2];
vec4 crossCorner = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w)));
// texCoord = corners[3];
vec4 thirdPosition = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w)));
// Testing size:
vec4 topRight = secondPosition/secondPosition.w;
topRight = ((topRight + vec4(1.0)) / vec4(2.0)) * vec4(screenSize.x, screenSize.y, 1.0, 1.0);
vec4 bottomLeft = initialPosition/initialPosition.w;
bottomLeft = ((bottomLeft + vec4(1.0)) / vec4(2.0)) * vec4(screenSize.x, screenSize.y, 1.0, 1.0);
float height = abs(topRight.y - bottomLeft.y);
float width = abs(topRight.x - bottomLeft.x);
float var = (height + width);
if ((height > maxBillboardSize) ||
(width > maxBillboardSize)) {
// Set maximum size as Carter's instructions
float correctionScale = height > maxBillboardSize ? maxBillboardSize / (topRight.y - bottomLeft.y) :
maxBillboardSize / (topRight.x - bottomLeft.x);
scaledRight = correctionScale * scaleMultiply * right/2.0f;
scaledUp = correctionScale * scaleMultiply * up/2.0f;
initialPosition = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w)));
vs_screenSpaceDepth = initialPosition.w;
secondPosition = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w)));
crossCorner = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w)));
thirdPosition = z_normalization(vec4(modelViewProjectionTransform *
dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w)));
// Fade-out
// float maxVar = 2.0f * maxBillboardSize;
// float minVar = maxBillboardSize;
// ta = 1.0f - ( (var - minVar)/(maxVar - minVar) );
// if (ta == 0.0f)
// return;
}
else if (width < 2.0f * minBillboardSize) {
//return;
float maxVar = 2.0f * minBillboardSize;
float minVar = minBillboardSize;
ta = ( (var - minVar)/(maxVar - minVar) );
if (ta == 0.0f)
return;
}
// Build primitive
texCoord = corners[0];
gl_Position = initialPosition;
EmitVertex();
texCoord = corners[1];
gl_Position = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w)));
texCoord = corners[1];
gl_Position = secondPosition;
EmitVertex();
texCoord = corners[2];
vec4 crossCorner = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w)));
texCoord = corners[2];
gl_Position = crossCorner;
EmitVertex();
EndPrimitive(); // First Triangle
texCoord = corners[0];
texCoord = corners[0];
gl_Position = initialPosition;
EmitVertex();
texCoord = corners[2];
texCoord = corners[2];
gl_Position = crossCorner;
EmitVertex();
texCoord = corners[3];
gl_Position = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w)));
texCoord = corners[3];
gl_Position = thirdPosition;
EmitVertex();
EndPrimitive(); // Second Triangle
EndPrimitive(); // Second Triangle
}
@@ -57,6 +57,9 @@ Fragment getFragment() {
Fragment frag;
frag.color = fullColor;
frag.depth = gs_screenSpaceDepth;
frag.gPosition = vec4(1e27, 1e27, 1e27, 1.0);
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
@@ -25,6 +25,7 @@
#include "fragment.glsl"
in float vs_screenSpaceDepth;
in vec4 vs_positionViewSpace;
uniform vec3 color;
uniform float alphaValue;
@@ -39,5 +40,10 @@ Fragment getFragment() {
frag.color = vec4(color, alphaValue);
frag.depth = vs_screenSpaceDepth;
// JCC: Need to change the position to camera space
frag.gPosition = vs_positionViewSpace;
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
@@ -28,16 +28,20 @@
in vec3 in_position;
uniform dmat4 modelViewProjectionTransform;
uniform dmat4 modelViewTransform;
uniform dmat4 projectionTransform;
uniform float scaleFactor;
out float vs_screenSpaceDepth;
out vec4 vs_positionViewSpace;
void main() {
vec4 positionClipSpace = vec4(modelViewProjectionTransform * dvec4(in_position, 1.0));
dvec4 positionViewSpace = modelViewTransform * dvec4(in_position, 1.0);
vec4 positionClipSpace = vec4(projectionTransform * positionViewSpace);
vec4 positionScreenSpace = vec4(z_normalization(positionClipSpace));
vs_screenSpaceDepth = positionScreenSpace.w;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_positionViewSpace = vec4(positionViewSpace);
gl_Position = positionScreenSpace;
}
@@ -30,6 +30,7 @@ in vec2 vs_st;
uniform sampler2D galaxyTexture;
//uniform bool additiveBlending;
uniform float alphaValue;
uniform float fadeInValue;
Fragment getFragment() {
@@ -44,6 +45,8 @@ Fragment getFragment() {
frag.color = texture(galaxyTexture, vs_st);
frag.color *= alphaValue;
frag.color *= fadeInValue;
if (frag.color.a == 0.0) {
discard;
}
@@ -52,8 +55,11 @@ Fragment getFragment() {
// frag.blend = BLEND_MODE_ADDITIVE;
// }
frag.color = texture(galaxyTexture, vs_st);
//frag.color = texture(galaxyTexture, vs_st);
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vec4(1e27, 1e27, 1e27, 1.0);
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
@@ -47,6 +47,9 @@ Fragment getFragment() {
//frag.depth = gs_screenSpaceDepth;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vec4(1e27, 1e27, 1e27, 1.0);
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
return frag;
}
+1 -1
View File
@@ -212,7 +212,7 @@ set(SHADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/shaders/pointglobe_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/texturetilemapping.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tile.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tilefragcolor.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tilefragment.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tileheight.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tilevertexskirt.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globeshading.hglsl
@@ -166,4 +166,18 @@ glm::dvec3 Ellipsoid::cartesianPosition(const Geodetic3& geodetic3) const {
return rSurface + geodetic3.height * normal;
}
void Ellipsoid::setShadowConfigurationArray(
const std::vector<Ellipsoid::ShadowConfiguration>& shadowConfArray)
{
_shadowConfArray = shadowConfArray;
}
std::vector<Ellipsoid::ShadowConfiguration> Ellipsoid::shadowConfigurationArray() const {
return _shadowConfArray;
}
bool Ellipsoid::hasEclipseShadows() const {
return !_shadowConfArray.empty();
}
} // namespace openspace::globebrowsing
@@ -30,6 +30,8 @@
#include <ghoul/glm.h>
#include <vector>
namespace openspace::globebrowsing {
/**
@@ -43,6 +45,12 @@ namespace openspace::globebrowsing {
*/
class Ellipsoid {
public:
// Shadow configuration structure
struct ShadowConfiguration {
std::pair<std::string, double> source;
std::pair<std::string, double> caster;
};
/**
* \param radii defines three radii for the Ellipsoid
*/
@@ -84,6 +92,12 @@ public:
glm::dvec3 cartesianSurfacePosition(const Geodetic2& geodetic2) const;
glm::dvec3 cartesianPosition(const Geodetic3& geodetic3) const;
void setShadowConfigurationArray(
const std::vector<Ellipsoid::ShadowConfiguration>& shadowConfArray
);
std::vector<Ellipsoid::ShadowConfiguration> shadowConfigurationArray() const;
bool hasEclipseShadows() const;
private:
struct EllipsoidCache {
glm::dvec3 _radiiSquared;
@@ -97,6 +111,9 @@ private:
void updateInternalCache();
glm::dvec3 _radii;
// Eclipse shadows conf
std::vector<Ellipsoid::ShadowConfiguration> _shadowConfArray;
};
} // namespace openspace::globebrowsing
@@ -29,11 +29,15 @@
#include <modules/globebrowsing/globes/pointglobe.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
namespace {
const char* keyFrame = "Frame";
const char* keyRadii = "Radii";
const char* keySegmentsPerPatch = "SegmentsPerPatch";
const char* keyLayers = "Layers";
const char* keyShadowGroup = "ShadowGroup";
const char* keyShadowSource = "Source";
const char* keyShadowCaster = "Caster";
static const openspace::properties::Property::PropertyInfo SaveOrThrowInfo = {
"SaveOrThrowCamera",
@@ -131,6 +135,18 @@ namespace {
"" // @TODO Missing documentation
};
static const openspace::properties::Property::PropertyInfo EclipseInfo = {
"Eclipse",
"Eclipse",
"Enables/Disable Eclipse shadows"
};
static const openspace::properties::Property::PropertyInfo EclipseHardShadowsInfo = {
"EclipseHardShadows",
"Eclipse Hard Shadows",
"Enables the rendering of eclipse shadows using hard shadows"
};
static const openspace::properties::Property::PropertyInfo LodScaleFactorInfo = {
"LodScaleFactor",
"Level of Detail Scale Factor",
@@ -175,6 +191,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
BoolProperty(PerformShadingInfo, true),
BoolProperty(AtmosphereInfo, false),
BoolProperty(AccurateNormalsInfo, false),
BoolProperty(EclipseInfo, false),
BoolProperty(EclipseHardShadowsInfo, false),
FloatProperty(LodScaleFactorInfo, 10.f, 1.f, 50.f),
FloatProperty(CameraMinHeightInfo, 100.f, 0.f, 1000.f),
FloatProperty(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f)
@@ -223,6 +241,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
addProperty(_generalProperties.atmosphereEnabled);
addProperty(_generalProperties.performShading);
addProperty(_generalProperties.useAccurateNormals);
addProperty(_generalProperties.eclipseShadowsEnabled);
addProperty(_generalProperties.eclipseHardShadows);
addProperty(_generalProperties.lodScaleFactor);
addProperty(_generalProperties.cameraMinHeight);
addProperty(_generalProperties.orenNayarRoughness);
@@ -248,6 +268,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
};
_generalProperties.atmosphereEnabled.onChange(notifyShaderRecompilation);
_generalProperties.useAccurateNormals.onChange(notifyShaderRecompilation);
_generalProperties.eclipseShadowsEnabled.onChange(notifyShaderRecompilation);
_generalProperties.eclipseHardShadows.onChange(notifyShaderRecompilation);
_generalProperties.performShading.onChange(notifyShaderRecompilation);
_debugProperties.showChunkEdges.onChange(notifyShaderRecompilation);
_debugProperties.showHeightResolution.onChange(notifyShaderRecompilation);
@@ -259,6 +281,78 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
addPropertySubOwner(_layerManager.get());
//addPropertySubOwner(_pointGlobe.get());
//================================================================
//======== Reads Shadow (Eclipses) Entries in mod file ===========
//================================================================
ghoul::Dictionary shadowDictionary;
bool success = dictionary.getValue(keyShadowGroup, shadowDictionary);
bool disableShadows = false;
if (success) {
std::vector<std::pair<std::string, double>> sourceArray;
unsigned int sourceCounter = 1;
while (success) {
std::string sourceName;
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Name", sourceName);
if (success) {
double sourceRadius;
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Radius", sourceRadius);
if (success) {
sourceArray.emplace_back(sourceName, sourceRadius);
}
else {
//LWARNING("No Radius value expecified for Shadow Source Name "
// << sourceName << " from " << name
// << " planet.\nDisabling shadows for this planet.");
disableShadows = true;
break;
}
}
sourceCounter++;
}
if (!disableShadows && !sourceArray.empty()) {
success = true;
std::vector<std::pair<std::string, double>> casterArray;
unsigned int casterCounter = 1;
while (success) {
std::string casterName;
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Name", casterName);
if (success) {
double casterRadius;
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Radius", casterRadius);
if (success) {
casterArray.emplace_back(casterName, casterRadius);
}
else {
//LWARNING("No Radius value expecified for Shadow Caster Name "
// << casterName << " from " << name
// << " planet.\nDisabling shadows for this planet.");
disableShadows = true;
break;
}
}
casterCounter++;
}
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray;
if (!disableShadows && (!sourceArray.empty() && !casterArray.empty())) {
for (const auto & source : sourceArray) {
for (const auto & caster : casterArray) {
Ellipsoid::ShadowConfiguration sc;
sc.source = source;
sc.caster = caster;
shadowConfArray.push_back(sc);
}
}
_ellipsoid.setShadowConfigurationArray(shadowConfArray);
}
}
}
}
void RenderableGlobe::initializeGL() {
@@ -283,7 +377,7 @@ bool RenderableGlobe::isReady() const {
return true;
}
void RenderableGlobe::render(const RenderData& data, RendererTasks& tasks) {
void RenderableGlobe::render(const RenderData& data, RendererTasks& renderTask) {
bool statsEnabled = _debugProperties.collectStats.value();
_chunkedLodGlobe->stats.setEnabled(statsEnabled);
@@ -298,7 +392,7 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& tasks) {
setSaveCamera(nullptr);
}
}
_distanceSwitch.render(data, tasks);
_distanceSwitch.render(data, renderTask);
}
if (_savedCamera != nullptr) {
DebugRenderer::ref().renderCameraFrustum(data, *_savedCamera);
@@ -34,6 +34,12 @@
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#ifdef OPENSPACE_MODULE_ATMOSPHERE_ENABLED
namespace openspace {
class AtmosphereDeferredcaster;
}
#endif
namespace openspace::globebrowsing {
class ChunkedLodGlobe;
@@ -73,11 +79,24 @@ public:
properties::BoolProperty performShading;
properties::BoolProperty atmosphereEnabled;
properties::BoolProperty useAccurateNormals;
properties::BoolProperty eclipseShadowsEnabled;
properties::BoolProperty eclipseHardShadows;
properties::FloatProperty lodScaleFactor;
properties::FloatProperty cameraMinHeight;
properties::FloatProperty orenNayarRoughness;
};
// Shadow structure
struct ShadowRenderingStruct {
double xu,
xp;
double rs,
rc;
glm::dvec3 sourceCasterVec;
glm::dvec3 casterPositionVec;
bool isShadowing;
};
RenderableGlobe(const ghoul::Dictionary& dictionary);
~RenderableGlobe() = default;
@@ -32,6 +32,11 @@
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h>
#include <openspace/util/updatestructures.h>
#include <openspace/util/spicemanager.h>
namespace {
const double KM_TO_M = 1000.0;
}
namespace openspace::globebrowsing {
@@ -111,6 +116,93 @@ ghoul::opengl::ProgramObject* ChunkRenderer::getActivatedProgramWithTileData(
return programObject;
}
void ChunkRenderer::calculateEclipseShadows(const Chunk& chunk, ghoul::opengl::ProgramObject* programObject,
const RenderData& data) {
// Shadow calculations..
if (chunk.owner().ellipsoid().hasEclipseShadows()) {
std::vector<RenderableGlobe::ShadowRenderingStruct> shadowDataArray;
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray = chunk.owner().ellipsoid().shadowConfigurationArray();
shadowDataArray.reserve(shadowConfArray.size());
double lt;
for (const auto & shadowConf : shadowConfArray) {
// TO REMEMBER: all distances and lengths in world coordinates are in meters!!! We need to move this to view space...
// Getting source and caster:
glm::dvec3 sourcePos = SpiceManager::ref().targetPosition(shadowConf.source.first, "SUN", "GALACTIC", {},
data.time.j2000Seconds(), lt);
sourcePos *= KM_TO_M; // converting to meters
glm::dvec3 casterPos = SpiceManager::ref().targetPosition(shadowConf.caster.first, "SUN", "GALACTIC", {},
data.time.j2000Seconds(), lt);
casterPos *= KM_TO_M; // converting to meters
psc caster_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(casterPos.x, casterPos.y, casterPos.z);
// First we determine if the caster is shadowing the current planet (all calculations in World Coordinates):
glm::dvec3 planetCasterVec = casterPos - data.position.dvec3();
glm::dvec3 sourceCasterVec = casterPos - sourcePos;
double sc_length = glm::length(sourceCasterVec);
glm::dvec3 planetCaster_proj = (glm::dot(planetCasterVec, sourceCasterVec) / (sc_length*sc_length)) * sourceCasterVec;
double d_test = glm::length(planetCasterVec - planetCaster_proj);
double xp_test = shadowConf.caster.second * sc_length / (shadowConf.source.second + shadowConf.caster.second);
double rp_test = shadowConf.caster.second * (glm::length(planetCaster_proj) + xp_test) / xp_test;
glm::dvec3 sunPos = SpiceManager::ref().targetPosition("SUN", "SUN", "GALACTIC", {}, data.time.j2000Seconds(), lt);
double casterDistSun = glm::length(casterPos - sunPos);
double planetDistSun = glm::length(data.position.dvec3() - sunPos);
RenderableGlobe::ShadowRenderingStruct shadowData;
shadowData.isShadowing = false;
// Eclipse shadows considers planets and moons as spheres
if (((d_test - rp_test) < (chunk.owner().ellipsoid().radii().x * KM_TO_M)) &&
(casterDistSun < planetDistSun)) {
// The current caster is shadowing the current planet
shadowData.isShadowing = true;
shadowData.rs = shadowConf.source.second;
shadowData.rc = shadowConf.caster.second;
shadowData.sourceCasterVec = glm::normalize(sourceCasterVec);
shadowData.xp = xp_test;
shadowData.xu = shadowData.rc * sc_length / (shadowData.rs - shadowData.rc);
shadowData.casterPositionVec = casterPos;
}
shadowDataArray.push_back(shadowData);
}
const std::string uniformVarName("shadowDataArray[");
unsigned int counter = 0;
for (const auto & sd : shadowDataArray) {
std::stringstream ss;
ss << uniformVarName << counter << "].isShadowing";
programObject->setUniform(ss.str(), sd.isShadowing);
if (sd.isShadowing) {
ss.str(std::string());
ss << uniformVarName << counter << "].xp";
programObject->setUniform(ss.str(), sd.xp);
ss.str(std::string());
ss << uniformVarName << counter << "].xu";
programObject->setUniform(ss.str(), sd.xu);
/*ss.str(std::string());
ss << uniformVarName << counter << "].rs";
programObject->setUniform(ss.str(), sd.rs);*/
ss.str(std::string());
ss << uniformVarName << counter << "].rc";
programObject->setUniform(ss.str(), sd.rc);
ss.str(std::string());
ss << uniformVarName << counter << "].sourceCasterVec";
programObject->setUniform(ss.str(), sd.sourceCasterVec);
ss.str(std::string());
ss << uniformVarName << counter << "].casterPositionVec";
programObject->setUniform(ss.str(), sd.casterPositionVec);
}
counter++;
}
programObject->setUniform("inverseViewTransform", glm::inverse(data.camera.combinedViewMatrix()));
programObject->setUniform("modelTransform", chunk.owner().modelTransform());
programObject->setUniform("hardShadows", chunk.owner().generalProperties().eclipseHardShadows);
programObject->setUniform("calculateEclipseShadows", true);
}
}
void ChunkRenderer::setCommonUniforms(ghoul::opengl::ProgramObject& programObject,
const Chunk& chunk, const RenderData& data)
{
@@ -177,6 +269,12 @@ void ChunkRenderer::setCommonUniforms(ghoul::opengl::ProgramObject& programObjec
programObject.setUniform("deltaPhi0", glm::length(deltaPhi0));
programObject.setUniform("deltaPhi1", glm::length(deltaPhi1));
programObject.setUniform("tileDelta", tileDelta);
// This should not be needed once the light calculations for the atmosphere
// is performed in view space..
programObject.setUniform("invViewModelTransform",
glm::inverse(glm::mat4(data.camera.combinedViewMatrix()) *
glm::mat4(chunk.owner().modelTransform())));
}
}
@@ -190,7 +288,7 @@ void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& da
}
const Ellipsoid& ellipsoid = chunk.owner().ellipsoid();
if (_layerManager->hasAnyBlendingLayersEnabled()) {
// Calculations are done in the reference frame of the globe. Hence, the
// camera position needs to be transformed with the inverse model matrix
@@ -220,6 +318,7 @@ void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& da
"modelViewProjectionTransform", modelViewProjectionTransform);
programObject->setUniform("minLatLon", glm::vec2(swCorner.toLonLatVec2()));
programObject->setUniform("lonLatScalingFactor", glm::vec2(patchSize.toLonLatVec2()));
// Ellipsoid Radius (Model Space)
programObject->setUniform("radiiSquared", glm::vec3(ellipsoid.radiiSquared()));
if (_layerManager->layerGroup(
@@ -242,6 +341,10 @@ void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& da
setCommonUniforms(*programObject, chunk, data);
if (chunk.owner().ellipsoid().hasEclipseShadows()) {
calculateEclipseShadows(chunk, programObject, data);
}
// OpenGL rendering settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
@@ -282,20 +385,24 @@ void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& dat
}
// Calculate other uniform variables needed for rendering
// Send the matrix inverse to the fragment for the global and local shader (JCC)
dmat4 modelTransform = chunk.owner().modelTransform();
dmat4 viewTransform = data.camera.combinedViewMatrix();
dmat4 modelViewTransform = viewTransform * modelTransform;
std::vector<std::string> cornerNames = { "p01", "p11", "p00", "p10" };
std::vector<glm::dvec3> cornersCameraSpace(4);
std::vector<glm::dvec3> cornersModelSpace(4);
for (int i = 0; i < 4; ++i) {
Quad q = static_cast<Quad>(i);
Geodetic2 corner = chunk.surfacePatch().getCorner(q);
glm::dvec3 cornerModelSpace = ellipsoid.cartesianSurfacePosition(corner);
cornersModelSpace[i] = cornerModelSpace;
glm::dvec3 cornerCameraSpace =
glm::dvec3(modelViewTransform * glm::dvec4(cornerModelSpace, 1));
cornersCameraSpace[i] = cornerCameraSpace;
programObject->setUniform(cornerNames[i], vec3(cornerCameraSpace));
}
// TODO: Patch normal can be calculated for all corners and then linearly
@@ -306,6 +413,15 @@ void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& dat
cornersCameraSpace[Quad::NORTH_EAST] -
cornersCameraSpace[Quad::SOUTH_WEST]));
// In order to improve performance, lets use the normal in object space (model space)
// for deferred rendering.
vec3 patchNormalModelSpace = normalize(
cross(cornersModelSpace[Quad::SOUTH_EAST] -
cornersModelSpace[Quad::SOUTH_WEST],
cornersModelSpace[Quad::NORTH_EAST] -
cornersModelSpace[Quad::SOUTH_WEST]));
programObject->setUniform("patchNormalModelSpace", patchNormalModelSpace);
programObject->setUniform("patchNormalCameraSpace", patchNormalCameraSpace);
programObject->setUniform(
"projectionTransform",
@@ -319,6 +435,10 @@ void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& dat
}
setCommonUniforms(*programObject, chunk, data);
if (chunk.owner().ellipsoid().hasEclipseShadows()) {
calculateEclipseShadows(chunk, programObject, data);
}
// OpenGL rendering settings
glEnable(GL_DEPTH_TEST);
@@ -83,6 +83,9 @@ private:
std::shared_ptr<GPULayerManager> gpuLayerManager,
const Chunk& chunk);
void calculateEclipseShadows(const Chunk& chunk, ghoul::opengl::ProgramObject* programObject,
const RenderData& data);
void setCommonUniforms(ghoul::opengl::ProgramObject& programObject,
const Chunk& chunk, const RenderData& data);
@@ -112,6 +112,8 @@ LayerShaderManager::LayerShaderPreprocessingData
);
pairs.emplace_back("useAtmosphere", std::to_string(generalProps.atmosphereEnabled));
pairs.emplace_back("performShading", std::to_string(generalProps.performShading));
pairs.emplace_back("useEclipseShadows", std::to_string(generalProps.eclipseShadowsEnabled));
pairs.emplace_back("useEclipseHardShadows", std::to_string(generalProps.eclipseHardShadows));
pairs.emplace_back("showChunkEdges", std::to_string(debugProps.showChunkEdges));
pairs.emplace_back("showHeightResolution",
std::to_string(debugProps.showHeightResolution)
@@ -234,6 +236,7 @@ void LayerShaderManager::recompileShaderProgram(
ghoul_assert(_programObject != nullptr, "Failed to initialize programObject!");
using IgnoreError = ghoul::opengl::ProgramObject::ProgramObject::IgnoreError;
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
_programObject->setIgnoreUniformLocationError(IgnoreError::Yes);
_updatedOnLastCall = true;
}
@@ -22,17 +22,16 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <${MODULE_GLOBEBROWSING}/shaders/tilefragcolor.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tilefragment.hglsl>
#include "fragment.glsl"
Fragment getFragment() {
Fragment frag;
frag.color = getTileFragColor();
frag = getTileFragment();
#if SHOW_CHUNK_EDGES
frag.color += patchBorderOverlay(fs_uv, vec3(0.0, 1.0, 0.0), 0.02);
#endif // SHOW_CHUNK_EDGES
frag.depth = fs_position.w;
return frag;
}
@@ -35,6 +35,7 @@ layout(location = 1) in vec2 in_uv;
out vec2 fs_uv;
out vec4 fs_position;
out vec3 fs_normal;
out vec3 ellipsoidNormalCameraSpace;
out LevelWeights levelWeights;
out vec3 positionCameraSpace;
@@ -44,6 +45,11 @@ out vec3 ellipsoidTangentThetaCameraSpace;
out vec3 ellipsoidTangentPhiCameraSpace;
#endif //USE_ACCURATE_NORMALS
#if USE_ECLIPSE_SHADOWS
out vec3 positionWorldSpace;
uniform dmat4 modelTransform;
#endif
uniform mat4 modelViewProjectionTransform;
uniform mat4 modelViewTransform;
uniform vec3 radiiSquared;
@@ -109,12 +115,17 @@ void main() {
// Add the height in the direction of the normal
pair.position += pair.normal * height;
vec4 positionClippingSpace =
modelViewProjectionTransform * vec4(pair.position, 1);
modelViewProjectionTransform * vec4(pair.position, 1.0);
// Write output
fs_uv = in_uv;
fs_position = z_normalization(positionClippingSpace);
gl_Position = fs_position;
ellipsoidNormalCameraSpace = mat3(modelViewTransform) * pair.normal;
positionCameraSpace = vec3(modelViewTransform * vec4(pair.position, 1));
fs_normal = pair.normal;
positionCameraSpace = vec3(modelViewTransform * vec4(pair.position, 1.0));
#if USE_ECLIPSE_SHADOWS
positionWorldSpace = vec3(modelTransform * dvec4(pair.position, 1.0));
#endif
}
@@ -22,17 +22,16 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <${MODULE_GLOBEBROWSING}/shaders/tilefragcolor.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tilefragment.hglsl>
#include "fragment.glsl"
Fragment getFragment() {
Fragment frag;
frag.color = getTileFragColor();
frag = getTileFragment();
#if SHOW_CHUNK_EDGES
frag.color += patchBorderOverlay(fs_uv, vec3(1,0,0), 0.005);
#endif // SHOW_CHUNK_EDGES
frag.depth = fs_position.w;
return frag;
}
@@ -35,6 +35,7 @@ layout(location = 1) in vec2 in_uv;
out vec2 fs_uv;
out vec4 fs_position;
out vec3 fs_normal;
out vec3 ellipsoidNormalCameraSpace;
out LevelWeights levelWeights;
out vec3 positionCameraSpace;
@@ -44,6 +45,11 @@ out vec3 ellipsoidTangentThetaCameraSpace;
out vec3 ellipsoidTangentPhiCameraSpace;
#endif // USE_ACCURATE_NORMALS
#if USE_ECLIPSE_SHADOWS
out vec3 positionWorldSpace;
uniform dmat4 inverseViewTransform;
#endif
uniform mat4 projectionTransform;
// Input points in camera space
uniform vec3 p00;
@@ -51,12 +57,12 @@ uniform vec3 p10;
uniform vec3 p01;
uniform vec3 p11;
uniform vec3 patchNormalCameraSpace;
uniform vec3 patchNormalModelSpace;
uniform float chunkMinHeight;
uniform float distanceScaleFactor;
uniform int chunkLevel;
vec3 bilinearInterpolation(vec2 uv) {
vec3 p0 = (1 - uv.x) * p00 + uv.x * p10;
vec3 p1 = (1 - uv.x) * p01 + uv.x * p11;
@@ -101,5 +107,10 @@ void main() {
fs_position = z_normalization(positionClippingSpace);
gl_Position = fs_position;
ellipsoidNormalCameraSpace = patchNormalCameraSpace;
fs_normal = patchNormalModelSpace;
positionCameraSpace = p;
#if USE_ECLIPSE_SHADOWS
positionWorldSpace = vec3(inverseViewTransform * dvec4(p, 1.0));
#endif
}
@@ -61,6 +61,8 @@
#define USE_ATMOSPHERE #{useAtmosphere}
#define USE_ACCURATE_NORMALS #{useAccurateNormals}
#define PERFORM_SHADING #{performShading}
#define USE_ECLIPSE_SHADOWS #{useEclipseShadows}
#define USE_ECLIPSE_HARD_SHADOWS #{useEclipseHardShadows}
#define SHOW_CHUNK_EDGES #{showChunkEdges}
#define SHOW_HEIGHT_RESOLUTION #{showHeightResolution}
#define SHOW_HEIGHT_INTENSITIES #{showHeightIntensities}
@@ -321,7 +323,7 @@ vec4 calculateNight(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec3 n = normalize(ellipsoidNormalCameraSpace);
vec3 l = lightDirectionCameraSpace;
float cosineFactor = clamp(dot(l, normalize(n + 0.15 * l)) * 3 , 0, 1);
float cosineFactor = clamp(dot(l, normalize(n + 0.20 * l)) * 3 , 0, 1);
#for i in 0..#{lastLayerIndexNightLayers}
{
@@ -390,7 +392,8 @@ vec4 calculateOverlay(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec4 calculateWater(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
Layer WaterMasks[NUMLAYERS_WATERMASK],
vec3 ellipsoidNormalCameraSpace,
vec3 lightDirectionCameraSpace, vec3 positionCameraSpace)
vec3 lightDirectionCameraSpace, vec3 positionCameraSpace,
out float reflectance)
{
vec4 waterColor = vec4(0.0);
@@ -422,8 +425,10 @@ vec4 calculateWater(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec3 specularTotal = specularColor * cosineFactor * specularIntensity * waterColor.a;
reflectance = waterColor.a;
//return blendNormal(currentColor, waterColor);
return currentColor + vec4(specularTotal, 1);
//return currentColor + vec4(specularTotal, 1);
return currentColor;
}
#endif // TEXTURETILEMAPPING_HGLSL
@@ -29,6 +29,7 @@
#include <${MODULE_GLOBEBROWSING}/shaders/texturetilemapping.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tileheight.hglsl>
#include "PowerScaling/powerScaling_fs.hglsl"
#include "fragment.glsl"
// Below are all the tiles that are used for contributing the actual fragment color
@@ -46,6 +47,7 @@ uniform Layer Overlays[NUMLAYERS_OVERLAY];
#if USE_WATERMASK
uniform Layer WaterMasks[NUMLAYERS_WATERMASK];
float waterReflectance = 0.0;
#endif // USE_WATERMASK
#if SHOW_HEIGHT_RESOLUTION
@@ -64,7 +66,77 @@ uniform vec3 lightDirectionCameraSpace;
uniform float orenNayarRoughness;
#endif
#if USE_ECLIPSE_SHADOWS
in vec3 positionWorldSpace;
/*******************************************************************************
***** ALL CALCULATIONS FOR ECLIPSE ARE IN METERS AND IN WORLD SPACE SYSTEM ****
*******************************************************************************/
// JCC: Remove and use dictionary to
// decides the number of shadows
const uint numberOfShadows = 1;
struct ShadowRenderingStruct {
double xu, xp;
double rs, rc;
dvec3 sourceCasterVec;
dvec3 casterPositionVec;
bool isShadowing;
};
// Eclipse shadow data
// JCC: Remove and use dictionary to
// decides the number of shadows
uniform ShadowRenderingStruct shadowDataArray[numberOfShadows];
uniform int shadows;
uniform bool hardShadows;
vec4 butterworthFunc(const float d, const float r, const float n) {
return vec4(vec3(sqrt(r/(r + pow(d, 2*n)))), 1.0);
}
vec4 calcShadow(const ShadowRenderingStruct shadowInfoArray[numberOfShadows], const dvec3 position,
const bool ground) {
if (shadowInfoArray[0].isShadowing) {
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;
float length_d = float(length(d));
double length_pc_proj = length(pc_proj);
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);
if ( length_d < r_u_pi ) { // umbra
if (ground) {
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.2, 0.2, 0.2, 1.0);
#endif
return butterworthFunc(length_d, r_u_pi, 4.0);
}
else {
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.5, 0.5, 0.5, 1.0);
#endif
return vec4(vec3(length_d/r_p_pi), 1.0);
}
}
else if ( length_d < r_p_pi ) {// penumbra
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.5, 0.5, 0.5, 1.0);
#endif
return vec4(vec3(length_d/r_p_pi), 1.0);
}
}
return vec4(1.0);
}
#endif
in vec4 fs_position;
in vec3 fs_normal;
in vec2 fs_uv;
in vec3 ellipsoidNormalCameraSpace;
in vec3 positionCameraSpace;
@@ -72,6 +144,10 @@ in vec3 positionCameraSpace;
#if USE_ACCURATE_NORMALS
in vec3 ellipsoidTangentThetaCameraSpace;
in vec3 ellipsoidTangentPhiCameraSpace;
// Once deferred light calculations are done in view space this can be removed
// so that we only need one normal; in view space.
uniform mat4 invViewModelTransform;
#endif // USE_ACCURATE_NORMALS
// levelInterpolationParameter is used to interpolate between a tile and its parent tiles
@@ -83,10 +159,12 @@ in LevelWeights levelWeights;
* the local and global chunk rendering.
*
*/
vec4 getTileFragColor() {
vec4 color = vec4(0.3, 0.3, 0.3, 1.0);
Fragment getTileFragment() {
Fragment frag;
frag.color = vec4(0.3, 0.3, 0.3, 1.0);
vec3 normal = normalize(ellipsoidNormalCameraSpace);
vec3 normalModelSpace = normalize(fs_normal);
#if USE_ACCURATE_NORMALS
normal = getTileNormal(
fs_uv,
@@ -95,11 +173,14 @@ vec4 getTileFragColor() {
normalize(ellipsoidTangentThetaCameraSpace),
normalize(ellipsoidTangentPhiCameraSpace)
);
// Once deferred light calculations are done in view space this can be removed
// so that we only need one normal; in view space.
normalModelSpace = mat3(invViewModelTransform) * normal;
#endif /// USE_ACCURATE_NORMALS
#if USE_COLORTEXTURE
color = calculateColor(
color,
frag.color = calculateColor(
frag.color,
fs_uv,
levelWeights,
ColorLayers
@@ -107,21 +188,22 @@ vec4 getTileFragColor() {
#endif // USE_COLORTEXTURE
#if USE_WATERMASK
color = calculateWater(
color,
frag.color = calculateWater(
frag.color,
fs_uv,
levelWeights,
WaterMasks,
normal,
lightDirectionCameraSpace, // Should already be normalized
positionCameraSpace
positionCameraSpace,
waterReflectance
);
#endif // USE_WATERMASK
#if USE_NIGHTTEXTURE
color = calculateNight(
color,
frag.color = calculateNight(
frag.color,
fs_uv,
levelWeights,
NightLayers,
@@ -132,8 +214,8 @@ vec4 getTileFragColor() {
#endif // USE_NIGHTTEXTURE
#if PERFORM_SHADING
color = calculateShadedColor(
color,
frag.color = calculateShadedColor(
frag.color,
normal,
lightDirectionCameraSpace,
normalize(positionCameraSpace),
@@ -143,10 +225,10 @@ vec4 getTileFragColor() {
#if USE_ATMOSPHERE
// Temporary until the real atmosphere code is here
//color = color + vec4(0.5,0.5,1,0) * 0.3; // Just to see something for now
vec3 n = normalize(ellipsoidNormalCameraSpace);
vec3 l = lightDirectionCameraSpace;
vec3 c = normalize(positionCameraSpace);
//frag.color = frag.color + vec4(0.5,0.5,1,0) * 0.3; // Just to see something for now
const vec3 n = normalize(ellipsoidNormalCameraSpace);
const vec3 l = lightDirectionCameraSpace;
const vec3 c = normalize(positionCameraSpace);
float cosFactor = 1 - clamp(dot(-n * 0.9, c), 0, 1);
cosFactor *= 1.1;
cosFactor -= 0.1;
@@ -159,13 +241,17 @@ vec4 getTileFragColor() {
//float cosFactorLight = max(dot(-lightDirectionCameraSpace, normalize(ellipsoidNormalCameraSpace)), 0);
//vec3 r = reflect(l, n);
//float scatteredLight = pow(clamp(dot(-r,c), 0, 1), 20);
vec3 atmosphereColor = vec3(0.5, 0.5, 1.0) * 2.0;
color += vec4(atmosphereColor,0) * cosFactor * cosFactorLight * 0.5;
const vec3 atmosphereColor = vec3(0.5, 0.5, 1.0) * 2.0;
frag.color += vec4(atmosphereColor,0) * cosFactor * cosFactorLight * 0.5;
#endif // USE_ATMOSPHERE
#if USE_ECLIPSE_SHADOWS
frag.color *= calcShadow(shadowDataArray, dvec3(positionWorldSpace), true);
#endif
#if USE_OVERLAY
color = calculateOverlay(
color,
frag.color = calculateOverlay(
frag.color,
fs_uv,
levelWeights,
Overlays
@@ -173,25 +259,40 @@ vec4 getTileFragColor() {
#endif // USE_OVERLAY
#if SHOW_HEIGHT_INTENSITIES
color.r *= 0.1;
color.g *= 0.1;
color.b *= 0.1;
frag.color.r *= 0.1;
frag.color.g *= 0.1;
frag.color.b *= 0.1;
float untransformedHeight = getUntransformedTileVertexHeight(fs_uv, levelWeights);
float contourLine = fract(10.0 * untransformedHeight) > 0.98 ? 1.0 : 0.0;
color.r += untransformedHeight;
color.b = contourLine;
frag.color.r += untransformedHeight;
frag.color.b = contourLine;
#endif
#if SHOW_HEIGHT_RESOLUTION
color += 0.0001*calculateDebugColor(fs_uv, fs_position, vertexResolution);
frag.color += 0.0001*calculateDebugColor(fs_uv, fs_position, vertexResolution);
#if USE_HEIGHTMAP
color.r = min(color.r, 0.8);
color.r += tileResolution(fs_uv, HeightLayers[0].pile.chunkTile0) > 0.9 ? 1 : 0;
frag.color.r = min(frag.color.r, 0.8);
frag.color.r += tileResolution(fs_uv, HeightLayers[0].pile.chunkTile0) > 0.9 ? 1 : 0;
#endif
#endif
return color;
// Other data
#if USE_WATERMASK
// Water reflectance is added to the G-Buffer.
frag.gOtherData = vec4(waterReflectance, waterReflectance, waterReflectance, 1.0);
#else
frag.gOtherData = vec4(0.0, 0.0, 0.0, 1.0);
#endif
// Normal is written Object Space.
// Right now the only renderable using this info is the atm and,
// because all calculation for light interactions are done in Object
// Space, we avoid a new computation saving the normals in Object Space.
frag.gNormal = vec4(normalModelSpace, 1.0);
frag.gPosition = vec4(positionCameraSpace, 1.0); // in Camera Rig Space
frag.depth = fs_position.w;
return frag;
}
#endif ///TILE_FRAG_COLOR_HGLSL
@@ -97,7 +97,9 @@ vec3 getTileNormal(vec2 uv, LevelWeights levelWeights, vec3 ellipsoidNormalCamer
vec3 ellipsoidTangentThetaCameraSpace,
vec3 ellipsoidTangentPhiCameraSpace)
{
#if USE_ACCURATE_NORMALS && USE_HEIGHTMAP
vec3 normal = ellipsoidNormalCameraSpace;
#if USE_ACCURATE_NORMALS
float deltaPhi = mix(deltaPhi0, deltaPhi1, uv.x);
float deltaTheta = mix(deltaTheta0, deltaTheta1, uv.y);
@@ -111,10 +113,9 @@ vec3 getTileNormal(vec2 uv, LevelWeights levelWeights, vec3 ellipsoidNormalCamer
vec3 diffTheta = deltaThetaVec + ellipsoidNormalCameraSpace * (height10 - height00);
vec3 diffPhi = deltaPhiVec + ellipsoidNormalCameraSpace * (height01 - height00);
return normalize(cross(diffTheta, diffPhi));
#else // USE_ACCURATE_NORMALS && USE_HEIGHTMAP
return ellipsoidNormalCameraSpace;
#endif
normal = normalize(cross(diffTheta, diffPhi));
#endif // USE_ACCURATE_NORMALS
return normal;
}
#endif // TILE_HEIGHT_HGLSL
+79
View File
@@ -0,0 +1,79 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/imgui/include/guiorigincomponent.h>
#include <modules/imgui/include/imgui_include.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scene/scene.h>
#include <ghoul/misc/assert.h>
namespace openspace::gui {
GuiOriginComponent::GuiOriginComponent()
: GuiComponent("Origin")
{}
void GuiOriginComponent::render() {
SceneGraphNode* currentFocus = OsEng.navigationHandler().focusNode();
std::vector<SceneGraphNode*> nodes =
OsEng.renderEngine().scene()->allSceneGraphNodes();
std::sort(
nodes.begin(),
nodes.end(),
[](SceneGraphNode* lhs, SceneGraphNode* rhs) {
return lhs->name() < rhs->name();
}
);
std::string nodeNames = "";
for (SceneGraphNode* n : nodes) {
nodeNames += n->name() + '\0';
}
auto iCurrentFocus = std::find(nodes.begin(), nodes.end(), currentFocus);
if (!nodes.empty()) {
// Only check if we found the current focus node if we have any nodes at all
// only then it would be a real error
ghoul_assert(iCurrentFocus != nodes.end(), "Focus node not found");
}
int currentPosition = static_cast<int>(std::distance(nodes.begin(), iCurrentFocus));
bool hasChanged = ImGui::Combo("Origin", &currentPosition, nodeNames.c_str());
if (hasChanged) {
OsEng.scriptEngine().queueScript(
"openspace.setPropertyValue('NavigationHandler.Origin', '" +
nodes[currentPosition]->name() + "');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
}
} // namespace openspace::gui
+1
View File
@@ -37,6 +37,7 @@
#include <openspace/scripting/scriptengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <glm/ext.hpp>
#include <ghoul/misc/misc.h>
#include <glm/gtx/component_wise.hpp>
+59 -54
View File
@@ -27,13 +27,12 @@
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <modules/space/rendering/planetgeometry.h>
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/misc/assert.h>
@@ -46,15 +45,17 @@
#include <memory>
#include <fstream>
#define _USE_MATH_DEFINES
#include <math.h>
namespace {
constexpr const char* KeyGeometry = "Geometry";
constexpr const char* KeyRadius = "Radius";
constexpr const char* KeyGeometry = "Geometry";
constexpr const char* KeyRadius = "Radius";
constexpr const char* _loggerCat = "RenderablePlanet";
constexpr const char* _loggerCat = "RenderablePlanet";
constexpr const char* keyShadowGroup = "Shadow_Group";
constexpr const char* keyShadowSource = "Source";
constexpr const char* keyShadowCaster = "Caster";
constexpr const char* keyShadowGroup = "Shadow_Group";
constexpr const char* keyShadowSource = "Source";
constexpr const char* keyShadowCaster = "Caster";
static const openspace::properties::Property::PropertyInfo ColorTextureInfo = {
"ColorTexture",
@@ -173,6 +174,7 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
, _hasNightTexture(false)
, _hasHeightTexture(false)
, _shadowEnabled(false)
, _time(0.f)
{
ghoul_precondition(
dictionary.hasKeyAndValue<std::string>(SceneGraphNode::KeyName),
@@ -257,26 +259,25 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
}
addProperty(_performShading);
// Shadow data:
//================================================================
//======== Reads Shadow (Eclipses) Entries in mod file ===========
//================================================================
ghoul::Dictionary shadowDictionary;
bool success = dictionary.getValue(keyShadowGroup, shadowDictionary);
bool disableShadows = false;
if (success) {
std::vector< std::pair<std::string, float > > sourceArray;
std::vector<std::pair<std::string, float>> sourceArray;
unsigned int sourceCounter = 1;
while (success) {
std::string sourceName;
std::stringstream ss;
ss << keyShadowSource << sourceCounter << ".Name";
success = shadowDictionary.getValue(ss.str(), sourceName);
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Name", sourceName);
if (success) {
float sourceRadius;
ss.str(std::string());
ss << keyShadowSource << sourceCounter << ".Radius";
success = shadowDictionary.getValue(ss.str(), sourceRadius);
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Radius", sourceRadius);
if (success) {
sourceArray.push_back(std::pair< std::string, float>(
sourceName, sourceRadius));
sourceArray.emplace_back(sourceName, sourceRadius);
}
else {
LWARNING(
@@ -297,17 +298,14 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
unsigned int casterCounter = 1;
while (success) {
std::string casterName;
std::stringstream ss;
ss << keyShadowCaster << casterCounter << ".Name";
success = shadowDictionary.getValue(ss.str(), casterName);
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Name", casterName);
if (success) {
float casterRadius;
ss.str(std::string());
ss << keyShadowCaster << casterCounter << ".Radius";
success = shadowDictionary.getValue(ss.str(), casterRadius);
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Radius", casterRadius);
if (success) {
casterArray.push_back(std::pair< std::string, float>(
casterName, casterRadius));
casterArray.emplace_back(casterName, casterRadius);
}
else {
LWARNING("No Radius value expecified for Shadow Caster Name "
@@ -322,13 +320,14 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
}
if (!disableShadows && (!sourceArray.empty() && !casterArray.empty())) {
for (const auto & source : sourceArray)
for (const auto & caster : casterArray) {
ShadowConf sc;
for (auto & source : sourceArray) {
for (auto & caster : casterArray) {
ShadowConfiguration sc;
sc.source = source;
sc.caster = caster;
_shadowConfArray.push_back(sc);
}
}
_shadowEnabled = true;
}
}
@@ -370,12 +369,14 @@ void RenderablePlanet::initializeGL() {
absPath("${MODULE_SPACE}/shaders/renderableplanet_fs.glsl")
);
}
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
_programObject->setIgnoreUniformLocationError(IgnoreError::Yes);
_geometry->initialize(this);
// Deactivate any previously activated shader program.
_programObject->deactivate();
loadTexture();
@@ -406,14 +407,12 @@ bool RenderablePlanet::isReady() const {
return ready;
}
void RenderablePlanet::render(const RenderData& data, RendererTasks&) {
// activate shader
_programObject->activate();
glm::dmat4 RenderablePlanet::computeModelTransformMatrix(const openspace::TransformData & transformData) {
// scale the planet to appropriate size since the planet is a unit sphere
glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation
glm::dmat4(data.modelTransform.rotation) * // Spice rotation
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale));
glm::translate(glm::dmat4(1.0), transformData.translation) * // Translation
glm::dmat4(transformData.rotation) * // Spice rotation
glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(transformData.scale)));
// scale the planet to appropriate size since the planet is a unit sphere
//glm::mat4 transform = glm::mat4(1);
@@ -433,14 +432,22 @@ void RenderablePlanet::render(const RenderData& data, RendererTasks&) {
// glm::dmat4(1.0),
// glm::radians(static_cast<double>(_rotation)), glm::dvec3(0, 1, 0)
//);
modelTransform = modelTransform * rot * roty /** rotProp*/;
return modelTransform = modelTransform * rot * roty /** rotProp*/;
}
void RenderablePlanet::render(const RenderData& data, RendererTasks& renderTask) {
// activate shader
_programObject->activate();
glm::dmat4 modelTransform = computeModelTransformMatrix(data.modelTransform);
glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
_programObject->setUniform("transparency", _alpha);
_programObject->setUniform(
"modelViewProjectionTransform",
data.camera.projectionMatrix() * glm::mat4(modelViewTransform)
_programObject->setUniform("modelViewTransform", modelViewTransform);
_programObject->setUniform("modelViewProjectionTransform",
data.camera.sgctInternal.projectionMatrix() * glm::mat4(modelViewTransform)
);
_programObject->setUniform("ModelTransform", glm::mat4(modelTransform));
@@ -459,7 +466,6 @@ void RenderablePlanet::render(const RenderData& data, RendererTasks&) {
setPscUniforms(*_programObject.get(), data.camera, data.position);
_programObject->setUniform("_performShading", _performShading);
_programObject->setUniform("_hasHeightMap", _hasHeightTexture);
_programObject->setUniform("_heightExaggeration", _heightExaggeration);
@@ -488,10 +494,11 @@ void RenderablePlanet::render(const RenderData& data, RendererTasks&) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// TODO: Move Calculations to VIEW SPACE (precision problems avoidance...)
//=============================================================================
//============= Eclipse Shadow Calculations and Uniforms Loading ==============
//=============================================================================
// TODO: Move Calculations to VIEW SPACE (let's avoid precision problems...)
double lt;
// Shadow calculations..
if (!_shadowConfArray.empty()) {
std::vector<ShadowRenderingStruct> shadowDataArray;
shadowDataArray.reserve(_shadowConfArray.size());
@@ -546,8 +553,8 @@ void RenderablePlanet::render(const RenderData& data, RendererTasks&) {
ShadowRenderingStruct shadowData;
shadowData.isShadowing = false;
if (((d_test - rp_test) < _planetRadius) &&
(casterDistSun < planetDistSun) ) {
if ( ((d_test - rp_test) < _planetRadius) &&
(casterDistSun < planetDistSun) ) {
// The current caster is shadowing the current planet
shadowData.isShadowing = true;
shadowData.rs = shadowConf.source.second;
@@ -602,12 +609,10 @@ void RenderablePlanet::render(const RenderData& data, RendererTasks&) {
void RenderablePlanet::update(const UpdateData& data) {
// set spice-orientation in accordance to timestamp
_stateMatrix = data.modelTransform.rotation;
//_stateMatrix = SpiceManager::ref().positionTransformMatrix(
// _frame,
// "GALACTIC",
// data.time
//);
_time = data.time.j2000Seconds();
if (_programObject && _programObject->isDirty())
_programObject->rebuildFromFile();
}
void RenderablePlanet::loadTexture() {
+21 -10
View File
@@ -46,26 +46,33 @@ namespace ghoul::opengl {
namespace openspace {
struct TransformData;
namespace planetgeometry {
class PlanetGeometry;
}
namespace documentation { struct Documentation; }
namespace planetgeometry { class PlanetGeometry; }
class RenderablePlanet : public Renderable {
public:
// Shadow structure
typedef struct {
struct ShadowConfiguration {
std::pair<std::string, float> source;
std::pair<std::string, float> caster;
} ShadowConf;
};
struct ShadowRenderingStruct {
float xu, xp;
float rs, rc;
float xu,
xp;
float rs,
rc;
glm::vec3 sourceCasterVec;
glm::vec3 casterPositionVec;
bool isShadowing;
};
public:
RenderablePlanet(const ghoul::Dictionary& dictionary);
void initializeGL() override;
@@ -80,7 +87,9 @@ public:
protected:
void loadTexture();
private:
private:
glm::dmat4 computeModelTransformMatrix(const openspace::TransformData & transformData);
properties::StringProperty _colorTexturePath;
properties::StringProperty _nightTexturePath;
properties::StringProperty _heightMapTexturePath;
@@ -95,15 +104,17 @@ private:
std::unique_ptr<planetgeometry::PlanetGeometry> _geometry;
properties::BoolProperty _performShading;
float _alpha;
std::vector< ShadowConf > _shadowConfArray;
float _planetRadius;
glm::dmat3 _stateMatrix;
float _alpha;
float _planetRadius;
bool _hasNightTexture;
bool _hasHeightTexture;
bool _shadowEnabled;
double _time;
glm::dmat3 _stateMatrix;
std::vector<ShadowConfiguration> _shadowConfArray;
};
} // namespace openspace
+11 -2
View File
@@ -645,8 +645,17 @@ bool RenderableStars::readSpeckFile() {
for (int i = 0; i < _nValuesPerStar; ++i) {
str >> values[i];
}
_fullData.insert(_fullData.end(), values.begin(), values.end());
bool nullArray = true;
for (int i = 0; i < values.size(); ++i) {
if (values[i] != 0.0) {
nullArray = false;
break;
}
}
if (!nullArray) {
_fullData.insert(_fullData.end(), values.begin(), values.end());
}
} while (!file.eof());
return true;
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -29,6 +29,8 @@ in vec2 vs_st;
in vec2 vs_nightTex;
in vec4 vs_normal;
in vec4 vs_position;
in vec4 vs_gPosition;
in vec3 vs_gNormal;
uniform vec4 objpos;
@@ -67,6 +69,10 @@ Fragment getFragment() {
frag.color = vec4(diffuse.rgb, transparency);
frag.depth = vs_position.w;
frag.gOtherData = vec4(diffuse.xyz, 1.0);
frag.gPosition = vs_gPosition;
frag.gNormal = vec4(vs_gNormal, 1.0);
return frag;
}
+12 -4
View File
@@ -33,8 +33,11 @@ layout(location = 2) in vec3 in_normal;
out vec2 vs_st;
out vec4 vs_normal;
out vec4 vs_position;
out vec4 vs_gPosition;
out vec3 vs_gNormal;
uniform mat4 ModelTransform;
uniform dmat4 modelViewTransform;
uniform mat4 modelViewProjectionTransform;
uniform sampler2D heightTex;
@@ -44,14 +47,16 @@ uniform float _heightExaggeration;
void main() {
// set variables
vs_st = in_st;
vec4 tmp = in_position;
// this is wrong for the normal. The normal transform is the transposed inverse of the model transform
vs_normal = normalize(ModelTransform * vec4(in_normal,0));
// vs_normal = vec4(in_normal, 0.0);
vec4 position = vec4(tmp.xyz * pow(10, tmp. w), 1.0);
// G-Buffer
vs_gNormal = in_normal;
vec4 position = vec4(in_position.xyz * pow(10, in_position.w), 1.0);
if (_hasHeightMap) {
float height = texture(heightTex, in_st).r;
vec3 displacementDirection = abs(normalize(in_normal.xyz));
@@ -59,6 +64,9 @@ void main() {
position.xyz = position.xyz + displacementDirection * displacementFactor;
}
// G-Buffer
vs_gPosition = vec4(modelViewTransform * position); // Must be in SGCT eye space
position = modelViewProjectionTransform * position;
vs_position = z_normalization(position);
@@ -28,6 +28,8 @@
in vec2 vs_st;
in vec4 vs_normal;
in vec4 vs_position;
in vec4 vs_gPosition;
in vec3 vs_gNormal;
uniform vec4 objpos;
uniform vec3 sun_pos;
@@ -35,7 +37,6 @@ uniform bool _performShading = true;
uniform float transparency;
uniform sampler2D texture1;
Fragment getFragment() {
vec4 diffuse = texture(texture1, vs_st);
@@ -52,5 +53,9 @@ Fragment getFragment() {
frag.color = vec4(diffuse.rgb, transparency);
frag.depth = vs_position.w;
frag.gOtherData = vec4(diffuse.xyz, 1.0);
frag.gPosition = vs_gPosition;
frag.gNormal = vec4(vs_gNormal, 1.0);
return frag;
}
+11 -2
View File
@@ -33,20 +33,29 @@ layout(location = 2) in vec3 in_normal;
out vec2 vs_st;
out vec4 vs_normal;
out vec4 vs_position;
out vec4 vs_gPosition;
out vec3 vs_gNormal;
uniform mat4 ModelTransform;
uniform dmat4 modelViewTransform;
uniform mat4 modelViewProjectionTransform;
void main() {
vs_st = in_st;
vec4 tmp = in_position;
// G-Buffer
vs_gNormal = in_normal;
// this is wrong for the normal. The normal transform is the transposed inverse of the model transform
vs_normal = normalize(ModelTransform * vec4(in_normal,0));
// vs_normal = vec4(in_normal, 0.0);
vec4 position = vec4(tmp.xyz * pow(10, tmp.w), 1.0);
vec4 position = vec4(in_position.xyz * pow(10, in_position.w), 1.0);
// G-Buffer
vs_gPosition = vec4(modelViewTransform * position); // Must be in SGCT eye space;
position = modelViewProjectionTransform * position;
vs_position = z_normalization(position);
+7
View File
@@ -27,6 +27,8 @@
in vec2 vs_st;
in vec4 vs_position;
//in vec4 vs_gPosition;
//in vec3 vs_gNormal;
uniform sampler1D texture1;
uniform vec2 textureOffset;
@@ -86,5 +88,10 @@ Fragment getFragment() {
Fragment frag;
frag.color = diffuse;
frag.depth = vs_position.w;
//frag.gOtherData = diffuse;
//frag.gPosition = vs_gPosition;
//frag.gNormal = vs_gNormal;
return frag;
}
+2
View File
@@ -31,6 +31,8 @@ layout(location = 1) in vec2 in_st;
out vec2 vs_st;
out vec4 vs_position;
//out vec4 vs_gPosition;
//out vec3 vs_gNormal;
uniform mat4 modelViewProjectionTransform;
+8 -3
View File
@@ -29,6 +29,8 @@ in vec2 vs_st;
in vec4 vs_normal;
in vec4 vs_position;
in vec4 vs_posWorld;
in vec4 vs_gPosition;
in vec3 vs_gNormal;
const uint numberOfShadows = 1;
@@ -51,8 +53,7 @@ uniform float transparency;
uniform sampler2D texture1;
vec4 butterworthFunc(float d, float r, float n) {
vec4 butterworthFunc(const float d, const float r, const float n) {
return vec4(vec3(sqrt(r / (r + pow(d, 2 * n)))), 1.0);
}
@@ -109,6 +110,10 @@ Fragment getFragment() {
frag.color = vec4(diffuse.rgb, transparency);
frag.depth = depth;
frag.gOtherData = vec4(diffuse.xyz, 1.0);
frag.gPosition = vs_gPosition;
frag.gNormal = vec4(vs_gNormal, 1.0);
return frag;
}
@@ -30,6 +30,8 @@ in vec2 vs_nightTex;
in vec4 vs_normal;
in vec4 vs_position;
in vec4 vs_posWorld;
in vec4 vs_gPosition;
in vec3 vs_gNormal;
const uint numberOfShadows = 1;
@@ -56,8 +58,7 @@ uniform float time;
uniform sampler2D texture1;
uniform sampler2D nightTex;
vec4 butterworthFunc(float d, float r, float n) {
vec4 butterworthFunc(const float d, const float r, const float n) {
return vec4(vec3(sqrt(r/(r + pow(d, 2*n)))), 1.0);
}
@@ -117,5 +118,9 @@ Fragment getFragment() {
frag.color = vec4(diffuse.rgb, transparency);
frag.depth = depth;
frag.gOtherData = vec4(diffuse.xyz, 1.0);
frag.gPosition = vs_gPosition;
frag.gNormal = vec4(vs_gNormal, 1.0);
return frag;
}
@@ -34,6 +34,8 @@ out vec2 vs_st;
out vec4 vs_normal;
out vec4 vs_position;
out vec4 vs_posWorld;
out vec4 vs_gPosition;
out vec3 vs_gNormal;
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
@@ -47,10 +49,18 @@ void main() {
// this is wrong for the normal. The normal transform is the transposed inverse of the model transform
vs_normal = normalize(ModelTransform * vec4(in_normal,0));
// The things is not in world coordinates, they are in
// regular view/eye coordinates.
// G-Buffer
vs_gNormal = in_normal;
// The tmp is now in the OS eye space (camera rig space)
// and wrtitten using PSC coords.
// position is in the same space, i.e., OS eye space but
// in meters (no PSC coords).
vec4 position = pscTransform(tmp, ModelTransform);
// G-Buffer
vs_gPosition = position;
vec3 local_vertex_pos = mat3(ModelTransform) * in_position.xyz;
vec4 vP = psc_addition(vec4(local_vertex_pos, in_position.w), objpos);
vs_posWorld = vec4(vP.xyz * pow(10, vP.w), 1.0);
+26 -6
View File
@@ -30,15 +30,19 @@ layout(location = 0) in vec4 in_position;
layout(location = 1) in vec2 in_st;
layout(location = 2) in vec3 in_normal;
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
uniform bool _hasHeightMap;
uniform float _heightExaggeration;
uniform sampler2D heightTex;
out vec2 vs_st;
out vec4 vs_normal;
out vec4 vs_position;
out vec4 vs_posWorld;
out float s;
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
out vec4 vs_gPosition;
out vec3 vs_gNormal;
void main() {
// set variables
@@ -49,15 +53,31 @@ void main() {
// this is wrong for the normal. The normal transform is the transposed inverse of the model transform
vs_normal = normalize(ModelTransform * vec4(in_normal,0));
// The things is not in world coordinates, they are in
// regular view/eye coordinates.
// We are using the normal in Object (model) space in G-Buffer (because of atm).
vs_gNormal = in_normal;
// The tmp is now in the OS eye space (camera rig space)
// and wrtitten using PSC coords.
// position is in the same space, i.e., OS eye space but
// in meters (no PSC coords).
vec4 position = pscTransform(tmp, ModelTransform);
// G-Buffer
vs_gPosition = position;
vec3 local_vertex_pos = mat3(ModelTransform) * in_position.xyz;
vec4 vP = psc_addition(vec4(local_vertex_pos,in_position.w),objpos);
vs_posWorld = vec4(vP.xyz * pow(10,vP.w), 1.0);
vs_position = tmp;
if (_hasHeightMap) {
float height = texture(heightTex, in_st).r;
vec3 displacementDirection = abs(normalize(in_normal.xyz));
float displacementFactor = height * _heightExaggeration;
position.xyz = position.xyz + displacementDirection * displacementFactor;
}
// Now is transforming from view position to SGCT projection
// coordinates.
position = ViewProjection * position;
+17 -8
View File
@@ -25,14 +25,6 @@
#include "fragment.glsl"
#include "PowerScaling/powerScaling_fs.hglsl"
in vec4 vs_position;
in vec3 ge_brightness;
in vec3 ge_velocity;
in float ge_speed;
in vec2 texCoord;
in float billboardSize;
// keep in sync with renderablestars.h:ColorOption enum
const int COLOROPTION_COLOR = 0;
const int COLOROPTION_VELOCITY = 1;
@@ -45,6 +37,17 @@ uniform float minBillboardSize;
uniform float alphaValue;
uniform int colorOption;
in vec4 vs_position;
in vec4 ge_gPosition;
in vec3 ge_brightness;
in vec3 ge_velocity;
in float ge_speed;
in vec2 texCoord;
in float billboardSize;
#include "fragment.glsl"
//#include "PowerScaling/powerScaling_fs.hglsl"
uniform vec2 magnitudeClamp;
@@ -84,6 +87,12 @@ Fragment getFragment() {
frag.color = fullColor;
frag.depth = pscDepth(position);
// G-Buffer
frag.gOtherData = vec4(fullColor.xyz, 1.0);
frag.gPosition = ge_gPosition;
// There is no normal here
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
if (fullColor.a == 0) {
discard;
}
+16 -8
View File
@@ -30,11 +30,14 @@ layout(points) in;
in vec4 psc_position[];
in vec3 vs_brightness[];
in vec3 vs_velocity[];
in vec4 vs_gPosition[];
in float vs_speed[];
in vec4 cam_position[];
layout(triangle_strip, max_vertices = 4) out;
out vec4 vs_position;
out vec4 ge_gPosition;
out vec3 ge_brightness;
out vec3 ge_velocity;
out float ge_speed;
@@ -56,12 +59,13 @@ const vec2 corners[4] = vec2[4](
void main() {
if ((psc_position[0].x == 0.0) &&
(psc_position[0].y == 0.0) &&
(psc_position[0].z == 0.0))
{
return;
}
// JCC: We want to display the Sun.
// if ((psc_position[0].x == 0.0) &&
// (psc_position[0].y == 0.0) &&
// (psc_position[0].z == 0.0))
// {
// return;
// }
ge_brightness = vs_brightness[0];
ge_velocity = vs_velocity[0];
@@ -92,9 +96,13 @@ void main() {
for (int i = 0; i < 4; i++) {
vs_position = gl_in[0].gl_Position;
gl_Position = projPos[i];
texCoord = corners[i];
texCoord = corners[i];
// G-Buffer
ge_gPosition = vs_gPosition[0];
billboardSize = sizeInPixels;
EmitVertex();
EmitVertex();
}
EndPrimitive();
}
+10 -4
View File
@@ -35,7 +35,7 @@ out vec4 psc_position;
out vec3 vs_brightness;
out vec3 vs_velocity;
out float vs_speed;
out vec4 cam_position;
out vec4 vs_gPosition;
uniform mat4 model;
uniform mat4 view;
@@ -48,8 +48,14 @@ void main() {
vs_brightness = in_brightness;
vs_velocity = in_velocity;
vs_speed = in_speed;
cam_position = campos;
vec4 tmp = p;
gl_Position = view * pscTransform(tmp, mat4(1.0));
}
vec4 position = pscTransform(tmp, mat4(1.0));
// G-Buffer
vs_gPosition = position;
position = view * position;
gl_Position = position;
}