diff --git a/CMakeLists.txt b/CMakeLists.txt index c08556a2d1..978a00258a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ cmake_minimum_required (VERSION 3.0 FATAL_ERROR) project (OpenSpace) message(STATUS "Generating OpenSpace project") +set(BOOST_ROOT "G:/deps/bin/boost_1_60_0") + set(OPENSPACE_BASE_DIR "${PROJECT_SOURCE_DIR}") set(OPENSPACE_APPS_DIR "${OPENSPACE_BASE_DIR}/apps") set(OPENSPACE_EXT_DIR "${OPENSPACE_BASE_DIR}/ext") diff --git a/apps/DataConverter/CMakeLists.txt b/apps/DataConverter/CMakeLists.txt index 54ebfe6ac3..24bfdc7968 100644 --- a/apps/DataConverter/CMakeLists.txt +++ b/apps/DataConverter/CMakeLists.txt @@ -31,11 +31,13 @@ set(application_path ${OPENSPACE_APPS_DIR}/DataConverter) set(SOURCE_FILES ${application_path}/main.cpp - ${application_path}/milkywayconversiontask.cpp + ${application_path}/milkywayconversiontask.cpp + ${application_path}/milkywaypointsconversiontask.cpp ) set(HEADER_FILES ${application_path}/conversiontask.h - ${application_path}/milkywayconversiontask.h + ${application_path}/milkywayconversiontask.h + ${application_path}/milkywaypointsconversiontask.h ) add_executable(${APPLICATION_NAME} MACOSX_BUNDLE diff --git a/apps/DataConverter/main.cpp b/apps/DataConverter/main.cpp index 9f4cdb418d..d0f8579a0a 100644 --- a/apps/DataConverter/main.cpp +++ b/apps/DataConverter/main.cpp @@ -36,6 +36,7 @@ #include #include +#include int main(int argc, char** argv) { using namespace openspace; @@ -61,14 +62,19 @@ int main(int argc, char** argv) { // or at the very least: a command line interface. MilkyWayConversionTask mwConversionTask( - "F:/milky-way/cam2_main.", + "F:/mw_june2016/volumeslices/img/comp/v003/frames/primary/0100/cam2_main.", ".exr", 1385, 512, - "F:/milky-way/mw_512_512_64.rawvolume", + "F:/mw_june2016/mw_512_512_64_june.rawvolume", glm::vec3(512, 512, 64)); + //MilkyWayPointsConversionTask mwpConversionTask("F:/mw_june2016/points.off", "F:/mw_june2016/points.off.binary"); + + mwConversionTask.perform(onProgress); + //mwpConversionTask.perform(onProgress); + std::cout << "Done." << std::endl; diff --git a/apps/DataConverter/milkywaypointsconversiontask.cpp b/apps/DataConverter/milkywaypointsconversiontask.cpp new file mode 100644 index 0000000000..0287bbf80b --- /dev/null +++ b/apps/DataConverter/milkywaypointsconversiontask.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +namespace openspace { +namespace dataconverter { + + + +MilkyWayPointsConversionTask::MilkyWayPointsConversionTask( + const std::string& inFilename, + const std::string& outFilename) + : _inFilename(inFilename) + , _outFilename(outFilename) {} + + +void MilkyWayPointsConversionTask::perform(const std::function& onProgress) { + std::ifstream in(_inFilename, std::ios::in); + std::ofstream out(_outFilename, std::ios::out | std::ios::binary); + + std::string format; + int64_t nPoints; + in >> format >> nPoints; + + + + size_t nFloats = nPoints * 7; + + float* pointData = new float[nFloats]; + + float x, y, z, r, g, b, a; + for (size_t i = 0; i < nPoints; ++i) { + in >> x >> y >> z >> r >> g >> b >> a; + if (in.good()) { + pointData[i * 7 + 0] = x; + pointData[i * 7 + 1] = y; + pointData[i * 7 + 2] = z; + pointData[i * 7 + 3] = r; + pointData[i * 7 + 4] = g; + pointData[i * 7 + 5] = b; + pointData[i * 7 + 6] = a; + onProgress(static_cast(i + 1) / nPoints); + } else { + std::cout << "Failed to convert point data."; + return; + } + } + + out.write(reinterpret_cast(&nPoints), sizeof(int64_t)); + out.write(reinterpret_cast(pointData), nFloats * sizeof(float)); + + in.close(); + out.close(); +} + + + +} +} diff --git a/apps/DataConverter/milkywaypointsconversiontask.h b/apps/DataConverter/milkywaypointsconversiontask.h new file mode 100644 index 0000000000..3b5e8abb15 --- /dev/null +++ b/apps/DataConverter/milkywaypointsconversiontask.h @@ -0,0 +1,35 @@ +#ifndef __MILKYWAYPOINTSCONVERSIONTASK_H__ +#define __MILKYWAYPOINTSCONVERSIONTASK_H__ + +#include +#include +#include +#include +#include +#include + + +namespace openspace { +namespace dataconverter { + +/** + * Converts ascii based point data + * int64_t n + * (float x, float y, float z, float r, float g, float b) * n + * to a binary (floating point) representation with the same layout. + */ +class MilkyWayPointsConversionTask : public ConversionTask { +public: + MilkyWayPointsConversionTask(const std::string& inFilename, + const std::string& outFilename); + + void perform(const std::function& onProgress) override; +private: + std::string _inFilename; + std::string _outFilename; +}; + +} +} + +#endif diff --git a/config/sgct/single_stereo.xml b/config/sgct/single_stereo.xml index 30188156b0..71f83845c3 100644 --- a/config/sgct/single_stereo.xml +++ b/config/sgct/single_stereo.xml @@ -1,7 +1,7 @@ - + diff --git a/data/scene/default.scene b/data/scene/default.scene index fbac639198..094d36ca04 100644 --- a/data/scene/default.scene +++ b/data/scene/default.scene @@ -17,18 +17,16 @@ function postInitialization() graphical settings for the renderables. ]]-- openspace.printInfo("Setting default values") - openspace.setPropertyValue("Sun.renderable.enabled", true) - openspace.setPropertyValue("SunGlare.renderable.enabled", false) - openspace.setPropertyValue("SunMarker.renderable.enabled", false) - openspace.setPropertyValue("EarthMarker.renderable.enabled", false) - --openspace.setPropertyValue("Constellation Bounds.renderable.enabled", false) - -- openspace.setPropertyValue("PlutoTrail.renderable.enabled", false) - -- openspace.setPropertyValue("PlutoTexture.renderable.enabled", false) + openspace.setPropertyValue("Sun.renderable.enabled", false) + openspace.setPropertyValue("SunMarker.renderable.enabled", true) + openspace.setPropertyValue("EarthMarker.renderable.enabled", true) + openspace.setPropertyValue("Constellation Bounds.renderable.enabled", false) openspace.setPropertyValue("MilkyWay.renderable.transparency", 0.55) openspace.setPropertyValue("MilkyWay.renderable.segments", 50) openspace.printInfo("Done setting default values") +<<<<<<< HEAD openspace.iswa.addCdfFiles("${OPENSPACE_DATA}/cdflist.json"); --openspace.iswa.addCygnet(7); @@ -39,6 +37,12 @@ function postInitialization() --openspace.iswa.addCygnet(-7,"Data","Gm"); --openspace.iswa.addCygnet(-8,"Data","Gm"); --openspace.iswa.addCygnet(-9,"Data","Gm"); +======= + + if openspace.modules.isLoaded("ISWA") then + openspace.iswa.addCdfFiles("${OPENSPACE_DATA}/cdflist.json"); + end +>>>>>>> develop end @@ -47,7 +51,7 @@ return { CommonFolder = "common", Camera = { Focus = "Earth", - Position = {1, 0, 0, 5}, + Position = {1, 0, 0, 2}, }, Modules = { "sun", diff --git a/data/scene/enlilnh/enlilnh.mod b/data/scene/enlilnh/enlilnh.mod index 497a9d4439..0cfb1abbb5 100644 --- a/data/scene/enlilnh/enlilnh.mod +++ b/data/scene/enlilnh/enlilnh.mod @@ -12,8 +12,9 @@ return { Translation = {0, 0, 0}, Rotation = {2.1, 0, 0}, Scaling = {1.1, 1.1, 1.1}, - ScalingExponent = 12, + ScalingExponent = 13, Source = "tsp/enlil_nh_128_128_16.tsp", + ErrorHistogramsSource = "tsp/enlil_nh_128_128_16.errorHistograms", TransferFunction = "transferfunctions/fire.txt", BrickSelector = "tf", }, diff --git a/data/scene/milkyway/milkyway.mod b/data/scene/milkyway/milkyway.mod index 99ac4f1a89..148ac2b331 100644 --- a/data/scene/milkyway/milkyway.mod +++ b/data/scene/milkyway/milkyway.mod @@ -7,7 +7,7 @@ return { }, Renderable = { Type = "RenderableSphere", - Size = {10, 20}, + Size = {10, 22}, Segments = 40, Texture = "textures/DarkUniverse_mellinger_8k.jpg", Orientation = "Inside/Outside" diff --git a/data/scene/newhorizons.scene b/data/scene/newhorizons.scene index 114070e22a..6512ec8948 100644 --- a/data/scene/newhorizons.scene +++ b/data/scene/newhorizons.scene @@ -1,4 +1,7 @@ UseAccurateNewHorizonsKernels = false +-- TextureResolution = "low" +TextureResolution = "med" +-- TextureResolution = "high" function preInitialization() --[[ @@ -8,6 +11,8 @@ function preInitialization() critical objects. ]]-- + -- openspace.time.setTime("2007-02-28T11:40:00.000") + -- openspace.time.setTime("2015-07-08T15:57:45.00") -- openspace.time.setTime("2015-07-12T07:41:00.00") -- openspace.time.setTime("2015-07-12T15:43:00.00") diff --git a/data/scene/newhorizons/jupiter/jupiter/jupiter.mod b/data/scene/newhorizons/jupiter/jupiter/jupiter.mod index 5853649995..03e8f46b12 100644 --- a/data/scene/newhorizons/jupiter/jupiter/jupiter.mod +++ b/data/scene/newhorizons/jupiter/jupiter/jupiter.mod @@ -39,7 +39,7 @@ return { }, Projection = { --Sequence = "F:/JupiterFullSequence", - Sequence = "${OPENSPACE_DATA}/scene/newhorizons/jupiter/jupiterprojection/ProjectionsOfInterest", + Sequence = "${OPENSPACE_DATA}/scene/newhorizons/jupiter/jupiter/ProjectionsOfInterest", SequenceType = "image-sequence", Observer = "NEW HORIZONS", Target = "JUPITER", diff --git a/data/scene/newhorizons/pluto/charon/charon.mod b/data/scene/newhorizons/pluto/charon/charon.mod index 70ba1533aa..674cb55892 100644 --- a/data/scene/newhorizons/pluto/charon/charon.mod +++ b/data/scene/newhorizons/pluto/charon/charon.mod @@ -8,6 +8,12 @@ else } end +Files = { + low = "textures/charon_highres.jpg", + med = "textures/charon_highres.jpg", + high = "textures/cpmap_cyl_HR_0e.jpg" +} +ColorTexture = Files[TextureResolution] return { -- CharonProjection module @@ -25,15 +31,11 @@ return { }, Textures = { Type = "simple", - Color = "textures/charon_highres.jpg", + Color = ColorTexture, + Height = "textures/cpdem-Mcolor2-MLorriCA-lr-5_ZMfs-cyl.jpg", Project = "textures/defaultProj.png", Sequencing = "true", }, - Atmosphere = { - Type = "Nishita", -- for example, values missing etc etc - MieFactor = 1.0, - MieColor = {1.0, 1.0, 1.0} - }, Projection = { Observer = "NEW HORIZONS", Target = "CHARON", diff --git a/data/scene/newhorizons/pluto/pluto/pluto.data b/data/scene/newhorizons/pluto/pluto/pluto.data index 626f2eb2b5..fff1025604 100644 --- a/data/scene/newhorizons/pluto/pluto/pluto.data +++ b/data/scene/newhorizons/pluto/pluto/pluto.data @@ -1,7 +1,7 @@ return { FileRequest = { { Identifier = "newhorizons_plutoencounter_pluto_assets", Destination = "assets", Version = 1 }, - { Identifier = "newhorizons_plutoencounter_pluto_textures", Destination = "textures", Version = 2 }, + { Identifier = "newhorizons_plutoencounter_pluto_textures", Destination = "textures", Version = 3 }, { Identifier = "pluto_textures", Destination = "textures", Version = 2 }, { Identifier = "newhorizons_plutoencounter_pluto_images", Destination = "images", Version = 1 } }, diff --git a/data/scene/newhorizons/pluto/pluto/pluto.mod b/data/scene/newhorizons/pluto/pluto/pluto.mod index ad08e9b186..4f71b1c04c 100644 --- a/data/scene/newhorizons/pluto/pluto/pluto.mod +++ b/data/scene/newhorizons/pluto/pluto/pluto.mod @@ -9,6 +9,13 @@ else } end +Files = { + low = "textures/pluto_large.jpg", + med = "textures/Shenk_180.jpg", + high = "textures/pmap_cyl_HR_LOR_lowres.jpg" +} +ColorTexture = Files[TextureResolution] + return { -- Pluto barycenter module { @@ -37,22 +44,13 @@ return { }, Textures = { Type = "simple", - -- Color = "textures/pluto_highres_180.jpg", - Color = "textures/Shenk_180.jpg", - -- Color = "textures/pluto_large.jpg", - -- Color = "textures/white.png", + Color = ColorTexture, + Height = "textures/pluto_shenk_heightmap.jpg", Project = "textures/3.jpg", - -- Height = "textures/pluto_shenk_heightmap.jpg", - -- NormalMap = "textures/pluto_shenk_normalmap.png", Sequencing = "true" }, - Atmosphere = { - Type = "Nishita", -- for example, values missing etc etc - MieFactor = 1.0, - MieColor = {1.0, 1.0, 1.0} - }, Projection = { - Sequence = "${OPENSPACE_DATA}/scene/newhorizons/pluto/pluto/images", + Sequence = "${OPENSPACE_DATA}/scene/newhorizons/pluto/pluto/full_images", EventFile = "${OPENSPACE_DATA}/scene/newhorizons/pluto/pluto/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt", SequenceType = "hybrid", Observer = "NEW HORIZONS", diff --git a/data/scene/rosetta.scene b/data/scene/rosetta.scene index 2c3d8268b2..903362699b 100644 --- a/data/scene/rosetta.scene +++ b/data/scene/rosetta.scene @@ -6,7 +6,10 @@ function preInitialization() critical objects. ]]-- - openspace.time.setTime("2014 AUG 21 18:00:00") + openspace.time.setTime("2014-08-15T03:05:18.101") + -- openspace.time.setTime("2014-11-17T03:05:18.101") + -- openspace.time.setTime("2015-07-29T06:02:10.000") + -- openspace.time.setTime("2014 AUG 21 18:00:00") -- openspace.time.setTime("2015 SEP 10 19:39:00") dofile(openspace.absPath('${SCRIPTS}/bind_keys_rosetta.lua')) end diff --git a/data/scene/rosetta/67P/67P.mod b/data/scene/rosetta/67P/67P.mod index bb37f7b630..a6ec406f4c 100644 --- a/data/scene/rosetta/67P/67P.mod +++ b/data/scene/rosetta/67P/67P.mod @@ -23,7 +23,7 @@ return { Destination = "GALACTIC" }, Projection = { - Sequence = "rosettaimages2", + Sequence = "rosettaimages", SequenceType = "image-sequence", Observer = "ROSETTA", Target = "CHURYUMOV-GERASIMENKO", @@ -87,32 +87,14 @@ return { '${OPENSPACE_DATA}/spice/RosettaKernels/SPK/CORL_DL_006_01____H__00156.BSP', --Jan 2014 - May 2015 (version match with 00162 ck files) - "${OPENSPACE_DATA}/spice/RosettaKernels_New/SPK/CORB_DV_211_01_______00288.BSP", - "${OPENSPACE_DATA}/spice/RosettaKernels_New/SPK/RORB_DV_211_01_______00288.BSP", - "${OPENSPACE_DATA}/spice/RosettaKernels_New/SPK/LORB_DV_211_01_______00288.BSP", "${OPENSPACE_DATA}/spice/RosettaKernels/SPK/CORB_DV_097_01_______00162.BSP", "${OPENSPACE_DATA}/spice/RosettaKernels/SPK/RORB_DV_097_01_______00162.BSP", "${OPENSPACE_DATA}/spice/RosettaKernels/SPK/LORB_DV_097_01_______00162.BSP", - --SCLK - -- "${OPENSPACE_DATA}/spice/RosettaKernels/SCLK/ROS_150227_STEP.TSC", - "${OPENSPACE_DATA}/spice/RosettaKernels_New/SCLK/ROS_160425_STEP.TSC", - - -- FK + "${OPENSPACE_DATA}/spice/RosettaKernels_New/SPK/CORB_DV_211_01_______00288.BSP", + "${OPENSPACE_DATA}/spice/RosettaKernels_New/SPK/RORB_DV_211_01_______00288.BSP", + "${OPENSPACE_DATA}/spice/RosettaKernels_New/SPK/LORB_DV_211_01_______00288.BSP", - "${OPENSPACE_DATA}/spice/RosettaKernels_New/FK/ROS_CHURYUMOV_V01.TF", - "${OPENSPACE_DATA}/spice/RosettaKernels_New/FK/ROS_V26.TF", - -- "${OPENSPACE_DATA}/spice/RosettaKernels/FK/ROS_V24.TF", - -- CK - "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/RATT_DV_211_01_01____00288.BC", - "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/CATT_DV_211_01_______00288.BC", - '${OPENSPACE_DATA}/spice/RosettaKernels/CK/RATT_DV_097_01_01____00162.BC', - "${OPENSPACE_DATA}/spice/RosettaKernels/CK/CATT_DV_097_01_______00162.BC", - - -- PCK - "${OPENSPACE_DATA}/spice/RosettaKernels_New/PCK/ROS_CGS_RSOC_V03.TPC", - -- "${OPENSPACE_DATA}/spice/RosettaKernels/PCK/ROS_CGS_RSOC_V03.TPC", - } }, diff --git a/data/scene/rosetta/rosetta/rosetta.mod b/data/scene/rosetta/rosetta/rosetta.mod index dffa3b30f6..9dd867355b 100644 --- a/data/scene/rosetta/rosetta/rosetta.mod +++ b/data/scene/rosetta/rosetta/rosetta.mod @@ -54,6 +54,27 @@ return { -- '${OPENSPACE_DATA}/spice/RosettaKernels/CK/RATT_DV_097_01_01____00162.BC', -- "${OPENSPACE_DATA}/spice/RosettaKernels/CK/CATT_DV_097_01_______00162.BC", + --SCLK + -- "${OPENSPACE_DATA}/spice/RosettaKernels/SCLK/ROS_150227_STEP.TSC", + "${OPENSPACE_DATA}/spice/RosettaKernels_New/SCLK/ROS_160425_STEP.TSC", + + -- FK + + "${OPENSPACE_DATA}/spice/RosettaKernels_New/FK/ROS_CHURYUMOV_V01.TF", + "${OPENSPACE_DATA}/spice/RosettaKernels_New/FK/ROS_V26.TF", + -- "${OPENSPACE_DATA}/spice/RosettaKernels/FK/ROS_V24.TF", + -- CK + "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/RATT_DV_211_01_01____00288.BC", + "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/CATT_DV_211_01_______00288.BC", + '${OPENSPACE_DATA}/spice/RosettaKernels/CK/RATT_DV_097_01_01____00162.BC', + "${OPENSPACE_DATA}/spice/RosettaKernels/CK/CATT_DV_097_01_______00162.BC", + + -- PCK + "${OPENSPACE_DATA}/spice/RosettaKernels_New/PCK/ROS_CGS_RSOC_V03.TPC", + -- "${OPENSPACE_DATA}/spice/RosettaKernels/PCK/ROS_CGS_RSOC_V03.TPC", + + + "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/ROS_SA_2014_V0047.BC", "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/ROS_SA_2015_V0042.BC", "${OPENSPACE_DATA}/spice/RosettaKernels_New/CK/ROS_SA_2016_V0019.BC", diff --git a/include/openspace/engine/moduleengine.h b/include/openspace/engine/moduleengine.h index bb7c86aa15..a15515c4d0 100644 --- a/include/openspace/engine/moduleengine.h +++ b/include/openspace/engine/moduleengine.h @@ -26,6 +26,7 @@ #define __MODULEENGINE_H__ #include +#include #include #include @@ -74,6 +75,12 @@ public: */ std::vector modules() const; + /** + * Returns the Lua library that contains all Lua functions available to affect the + * modules. + */ + static scripting::ScriptEngine::LuaLibrary luaLibrary(); + private: /// The list of all registered OpenSpaceModule%s std::vector> _modules; diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 6aa13c20a4..ee36f2f0f8 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -83,7 +83,10 @@ public: properties::PropertyOwner& globalPropertyOwner(); WindowWrapper& windowWrapper(); ghoul::fontrendering::FontManager& fontManager(); + +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED gui::GUI& gui(); +#endif // SGCT callbacks bool initialize(); @@ -127,7 +130,9 @@ private: std::unique_ptr _commandlineParser; std::unique_ptr _console; std::unique_ptr _moduleEngine; +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED std::unique_ptr _gui; +#endif std::unique_ptr _parallelConnection; std::unique_ptr _windowWrapper; std::unique_ptr _fontManager; diff --git a/include/openspace/openspace.h b/include/openspace/openspace.h index c6640e989d..75fb83e1c8 100644 --- a/include/openspace/openspace.h +++ b/include/openspace/openspace.h @@ -32,10 +32,10 @@ namespace openspace { std::string licenseText(); const int OPENSPACE_VERSION_MAJOR = 0; -const int OPENSPACE_VERSION_MINOR = 3; +const int OPENSPACE_VERSION_MINOR = 4; const int OPENSPACE_VERSION_PATCH = 0; -const std::string OPENSPACE_VERSION_STRING = "prerelease-8"; +const std::string OPENSPACE_VERSION_STRING = "prerelease-9 (IPS)"; } // namespace openspace diff --git a/include/openspace/performance/performancelayout.h b/include/openspace/performance/performancelayout.h new file mode 100644 index 0000000000..70568e67e5 --- /dev/null +++ b/include/openspace/performance/performancelayout.h @@ -0,0 +1,61 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __PERFORMANCELAYOUT_H__ +#define __PERFORMANCELAYOUT_H__ + +#include + +namespace openspace { +namespace performance { + +struct PerformanceLayout { + static const int8_t Version = 0; + static const int LengthName = 256; + static const int NumberValues = 256; + static const int MaxValues = 256; + + PerformanceLayout(); + + struct SceneGraphPerformanceLayout { + char name[LengthName]; + float renderTime[NumberValues]; + float updateRenderable[NumberValues]; + float updateEphemeris[NumberValues]; + }; + SceneGraphPerformanceLayout sceneGraphEntries[MaxValues]; + int16_t nScaleGraphEntries; + + struct FunctionPerformanceLayout { + char name[LengthName]; + float time[NumberValues]; + }; + FunctionPerformanceLayout functionEntries[MaxValues]; + int16_t nFunctionEntries; +}; + +} // namespace performance +} // namespace openspace + +#endif // __PERFORMANCELAYOUT_H__ diff --git a/include/openspace/performance/performancemanager.h b/include/openspace/performance/performancemanager.h new file mode 100644 index 0000000000..c99538358b --- /dev/null +++ b/include/openspace/performance/performancemanager.h @@ -0,0 +1,67 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __PERFORMANCEMANAGER_H__ +#define __PERFORMANCEMANAGER_H__ + +#include +#include +#include + +namespace ghoul { + class SharedMemory; +} + +namespace openspace { + +class SceneGraphNode; + +namespace performance { + +class PerformanceManager { +public: + static const std::string PerformanceMeasurementSharedData; + + PerformanceManager(); + ~PerformanceManager(); + + void resetPerformanceMeasurements(); + + bool isMeasuringPerformance() const; + + void storeIndividualPerformanceMeasurement(std::string identifier, long long nanoseconds); + void storeScenePerformanceMeasurements(const std::vector& sceneNodes); + +private: + bool _doPerformanceMeasurements; + + std::map individualPerformanceLocations; + + ghoul::SharedMemory* _performanceMemory; +}; + +} // namespace performance +} // namespace openspace + +#endif // __PERFORMANCEMANAGER_H__ diff --git a/include/openspace/performance/performancemeasurement.h b/include/openspace/performance/performancemeasurement.h new file mode 100644 index 0000000000..f08dbb94b2 --- /dev/null +++ b/include/openspace/performance/performancemeasurement.h @@ -0,0 +1,57 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __PERFORMANCEMEASUREMENT_H__ +#define __PERFORMANCEMEASUREMENT_H__ + +#include +#include + +namespace openspace { +namespace performance { + +class PerformanceManager; + +class PerformanceMeasurement { +public: + PerformanceMeasurement(std::string identifier, performance::PerformanceManager* manager); + ~PerformanceMeasurement(); + +private: + std::string _identifier; + performance::PerformanceManager* _manager; + + std::chrono::high_resolution_clock::time_point _startTime; +}; + +#define __MERGE(a,b) a##b +#define __LABEL(a) __MERGE(unique_name_, a) + +/// Declare a new variable for measuring the performance of the current block +#define PerfMeasure(name) auto __LABEL(__LINE__) = openspace::performance::PerformanceMeasurement((name), OsEng.renderEngine().performanceManager()) + +} // namespace performance +} // namespace openspace + +#endif // __PERFORMANCEMEASUREMENTHELPER_H__ diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h index 1351643e8f..4a9689fa9f 100644 --- a/include/openspace/rendering/abufferrenderer.h +++ b/include/openspace/rendering/abufferrenderer.h @@ -35,6 +35,7 @@ #include +#include #include #include #include @@ -68,6 +69,10 @@ public: void setCamera(Camera* camera) override; void setScene(Scene* scene) override; void setResolution(glm::ivec2 res) override; + void setNAaSamples(int nAaSamples) override; + + void preRaycast(ghoul::opengl::ProgramObject& programObject); + void postRaycast(ghoul::opengl::ProgramObject& programObject); void update(); void render(float blackoutFactor, bool doPerformanceMeasurements) override; @@ -110,6 +115,12 @@ private: ghoul::Dictionary _resolveDictionary; + GLuint _mainColorTexture; + GLuint _mainDepthTexture; + std::unique_ptr _mainColorTextureUnit; + std::unique_ptr _mainDepthTextureUnit; + + GLuint _mainFramebuffer; GLuint _screenQuad; GLuint _anchorPointerTexture; GLuint _anchorPointerTextureInitializer; @@ -119,6 +130,11 @@ private: GLuint _vertexPositionBuffer; int _nAaSamples; + + std::unique_ptr _rendererTasks; + std::unique_ptr _renderData; + float _blackoutFactor; + ghoul::Dictionary _rendererData; }; // ABufferRenderer } // openspace diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index fb65728005..df996e695f 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -68,6 +68,7 @@ public: void setCamera(Camera* camera) override; void setScene(Scene* scene) override; void setResolution(glm::ivec2 res) override; + void setNAaSamples(int nAaSamples) override; void update() override; void render(float blackoutFactor, bool doPerformanceMeasurements) override; @@ -84,6 +85,7 @@ private: std::map _raycastData; std::map> _exitPrograms; std::map> _raycastPrograms; + std::map> _insideRaycastPrograms; std::unique_ptr _resolveProgram; diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index c70f10bcb1..e6e50692de 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -68,6 +68,7 @@ public: virtual void render(const RenderData& data); virtual void render(const RenderData& data, RendererTasks& rendererTask); + virtual void postRender(const RenderData& data); virtual void update(const UpdateData& data); bool isVisible() const; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index da62938f01..65e1359b9b 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -31,6 +31,7 @@ #include #include +#include namespace ghoul { namespace fontrendering { @@ -62,8 +63,11 @@ public: Invalid }; - static const std::string PerformanceMeasurementSharedData; - + enum class RenderProgramType { + Default = 0, + Post + }; + static const std::string KeyFontMono; static const std::string KeyFontLight; @@ -91,14 +95,18 @@ public: void takeScreenshot(); void toggleInfoText(bool b); + // Performance measurements void setPerformanceMeasurements(bool performanceMeasurements); bool doesPerformanceMeasurements() const; + performance::PerformanceManager* performanceManager(); void serialize(SyncBuffer* syncBuffer); void deserialize(SyncBuffer* syncBuffer); float globalBlackOutFactor(); void setGlobalBlackOutFactor(float factor); + void setNAaSamples(int nAaSamples); + void setDisableRenderingOnMaster(bool enabled); @@ -111,24 +119,43 @@ public: std::string name, std::string vsPath, std::string fsPath, - const ghoul::Dictionary& dictionary = ghoul::Dictionary()); + const ghoul::Dictionary& dictionary = ghoul::Dictionary(), + RenderEngine::RenderProgramType type = RenderEngine::RenderProgramType::Default); std::unique_ptr buildRenderProgram( std::string name, std::string vsPath, std::string fsPath, std::string csPath, - const ghoul::Dictionary& dictionary = ghoul::Dictionary()); + const ghoul::Dictionary& dictionary = ghoul::Dictionary(), + RenderEngine::RenderProgramType type = RenderEngine::RenderProgramType::Default); void removeRenderProgram(const std::unique_ptr& program); + /** + * Set raycasting uniforms on the program object, and setup raycasting. + */ + void preRaycast(ghoul::opengl::ProgramObject& programObject); + + /** + * Tear down raycasting for the specified program object. + */ + void postRaycast(ghoul::opengl::ProgramObject& programObject); + + void setRendererFromString(const std::string& method); /** - * Let's the renderer update the data to be brought into the rendererer programs + * Lets the renderer update the data to be brought into the rendererer programs * as a 'rendererData' variable in the dictionary. */ - void setRendererData(const ghoul::Dictionary& renderer); + void setRendererData(const ghoul::Dictionary& rendererData); + + /** + * Lets the renderer update the data to be brought into the post rendererer programs + * as a 'resolveData' variable in the dictionary. + */ + void setResolveData(const ghoul::Dictionary& resolveData); /** * Returns the Lua library that contains all Lua functions available to affect the @@ -153,7 +180,7 @@ public: private: void setRenderer(std::unique_ptr renderer); RendererImplementation rendererFromString(const std::string& method); - void storePerformanceMeasurements(); + void renderInformation(); void renderScreenLog(); @@ -161,22 +188,23 @@ private: Scene* _sceneGraph; RaycasterManager* _raycasterManager; + std::unique_ptr _performanceManager; + std::unique_ptr _renderer; RendererImplementation _rendererImplementation; ghoul::Dictionary _rendererData; + ghoul::Dictionary _resolveData; ScreenLog* _log; bool _showInfo; bool _showLog; bool _takeScreenshot; - bool _doPerformanceMeasurements; - ghoul::SharedMemory* _performanceMemory; - float _globalBlackOutFactor; float _fadeDuration; float _currentFadeTime; int _fadeDirection; + int _nAaSamples; std::vector _programs; std::vector> _screenSpaceRenderables; diff --git a/include/openspace/rendering/renderer.h b/include/openspace/rendering/renderer.h index 0a3113a3b1..3258be73c0 100644 --- a/include/openspace/rendering/renderer.h +++ b/include/openspace/rendering/renderer.h @@ -58,6 +58,18 @@ public: virtual void setCamera(Camera* camera) = 0; virtual void setScene(Scene* scene) = 0; virtual void setResolution(glm::ivec2 res) = 0; + virtual void setNAaSamples(int nAaSamples) = 0; + + /** + * Set raycasting uniforms on the program object, and setup raycasting. + */ + virtual void preRaycast(ghoul::opengl::ProgramObject& programObject) {}; + + /** + * Tear down raycasting for the specified program object. + */ + virtual void postRaycast(ghoul::opengl::ProgramObject& programObject) {}; + virtual void update() = 0; virtual void render(float blackoutFactor, bool doPerformanceMeasurements) = 0; diff --git a/include/openspace/rendering/volumeraycaster.h b/include/openspace/rendering/volumeraycaster.h index 5dfb480df8..dc4bbcee57 100644 --- a/include/openspace/rendering/volumeraycaster.h +++ b/include/openspace/rendering/volumeraycaster.h @@ -70,6 +70,11 @@ public: */ virtual void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) {}; + /** + * Return true if the camera is inside the volume. + * Also set localPosition to the camera position in the volume's local coordainte system. + */ + virtual bool cameraIsInside(const RenderData& data, glm::vec3& localPosition) { return false; }; /** * Return a path the file to use as vertex shader * diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index 07f1e27252..d871fac952 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -84,6 +84,11 @@ public: */ void render(const RenderData& data, RendererTasks& tasks); + /* + * Post-Render visible SceneGraphNodes using the provided camera + */ + void postRender(const RenderData& data); + /* * Returns the root SceneGraphNode */ diff --git a/include/openspace/scene/scenegraphnode.h b/include/openspace/scene/scenegraphnode.h index bb577fdd99..687c68ebad 100644 --- a/include/openspace/scene/scenegraphnode.h +++ b/include/openspace/scene/scenegraphnode.h @@ -67,6 +67,7 @@ public: void update(const UpdateData& data); void evaluate(const Camera* camera, const psc& parentPosition = psc()); void render(const RenderData& data, RendererTasks& tasks); + void postRender(const RenderData& data); void updateCamera(Camera* camera) const; //void addNode(SceneGraphNode* child); diff --git a/include/openspace/util/screenlog.h b/include/openspace/util/screenlog.h index 01c9e9283e..afeaf2ecc2 100644 --- a/include/openspace/util/screenlog.h +++ b/include/openspace/util/screenlog.h @@ -22,6 +22,9 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#ifndef __SCREENLOG_H__ +#define __SCREENLOG_H__ + #include #include @@ -110,4 +113,6 @@ private: LogLevel _logLevel; }; -} // namespace openspace \ No newline at end of file +} // namespace openspace + +#endif // __SCREENLOG_H__ diff --git a/include/openspace/util/transformationmanager.h b/include/openspace/util/transformationmanager.h index bd3f74065b..93618266aa 100644 --- a/include/openspace/util/transformationmanager.h +++ b/include/openspace/util/transformationmanager.h @@ -27,11 +27,19 @@ #include #include +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED #include +#endif + +#include + +namespace ccmc { + class Kameleon; +} // namespace ccmc namespace openspace { -class ccmc::Kameleon; - +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +#endif class TransformationManager : public ghoul::Singleton { friend class ghoul::Singleton; @@ -43,8 +51,11 @@ public: private: glm::dmat3 kameleonTransformationMatrix(std::string from, std::string to, double ephemerisTime) const; - std::shared_ptr _kameleon; + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + std::shared_ptr _kameleon; +#endif std::set _kameleonFrames; std::set _dipoleFrames; }; diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 76d16ff58e..bd1137554b 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -267,6 +267,7 @@ void RenderableModel::loadTexture() { if (_texture) { LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); _texture->uploadTexture(); + _texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); } } } diff --git a/modules/base/rendering/renderablestars.cpp b/modules/base/rendering/renderablestars.cpp index 9cc959270f..cf4c2bc3cd 100644 --- a/modules/base/rendering/renderablestars.cpp +++ b/modules/base/rendering/renderablestars.cpp @@ -316,10 +316,12 @@ void RenderableStars::update(const UpdateData& data) { _pointSpreadFunctionTexture = nullptr; if (_pointSpreadFunctionTexturePath.value() != "") { _pointSpreadFunctionTexture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_pointSpreadFunctionTexturePath))); + if (_pointSpreadFunctionTexture) { LDEBUG("Loaded texture from '" << absPath(_pointSpreadFunctionTexturePath) << "'"); _pointSpreadFunctionTexture->uploadTexture(); } + _pointSpreadFunctionTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); delete _psfTextureFile; _psfTextureFile = new ghoul::filesystem::File(_pointSpreadFunctionTexturePath); diff --git a/modules/base/shaders/sphere_vs.glsl b/modules/base/shaders/sphere_vs.glsl index 11c4f4c2db..7c64455d68 100644 --- a/modules/base/shaders/sphere_vs.glsl +++ b/modules/base/shaders/sphere_vs.glsl @@ -49,7 +49,7 @@ void main() vec4 position = pscTransform(tmp, mt); - vs_position = in_position; + vs_position = tmp; vs_st = in_st; position = ViewProjection * position; diff --git a/modules/base/shaders/star_fs.glsl b/modules/base/shaders/star_fs.glsl index 43f77a26b7..39cdcd0bc9 100644 --- a/modules/base/shaders/star_fs.glsl +++ b/modules/base/shaders/star_fs.glsl @@ -58,7 +58,7 @@ vec4 bv2rgb(float bv) { Fragment getFragment() { // Something in the color calculations need to be changed because before it was dependent // on the gl blend functions since the abuffer was not involved - + vec4 color = vec4(0.0); switch (colorOption) { case COLOROPTION_COLOR: @@ -79,7 +79,7 @@ Fragment getFragment() { vec4 position = vs_position; // This has to be fixed when the scale graph is in place ---emiax - position.w = 19; + position.w = 15; Fragment frag; frag.color = fullColor; diff --git a/modules/fieldlines/shaders/fieldline_fs.glsl b/modules/fieldlines/shaders/fieldline_fs.glsl index 084f3bd3b6..1bbaf74cba 100644 --- a/modules/fieldlines/shaders/fieldline_fs.glsl +++ b/modules/fieldlines/shaders/fieldline_fs.glsl @@ -40,9 +40,9 @@ Fragment getFragment() float alpha = 1-length(gs_normal)*length(gs_normal); vec4 fragColor; if (classification) - fragColor = vec4(gs_color.rgb, alpha); + fragColor = vec4(gs_color.rgb * alpha, 1.0); else - fragColor = vec4(fieldLineColor.rgb, fieldLineColor.a * alpha); + fragColor = vec4(fieldLineColor.rgb * fieldLineColor.a * alpha, 1.0); float depth = pscDepth(gs_position); diff --git a/modules/galaxy/CMakeLists.txt b/modules/galaxy/CMakeLists.txt new file mode 100644 index 0000000000..afb55cfbb3 --- /dev/null +++ b/modules/galaxy/CMakeLists.txt @@ -0,0 +1,45 @@ +######################################################################################### +# # +# OpenSpace # +# # +# Copyright (c) 2014-2015 # +# # +# 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}/galaxymodule.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/galaxyraycaster.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.h +) +source_group("Header Files" FILES ${HEADER_FILES}) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/galaxymodule.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/galaxyraycaster.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.cpp +) +source_group("Source Files" FILES ${SOURCE_FILES}) + +create_new_module( + "Galaxy" + galaxy + ${HEADER_FILES} ${SOURCE_FILES} +) diff --git a/modules/galaxy/galaxymodule.cpp b/modules/galaxy/galaxymodule.cpp new file mode 100644 index 0000000000..714818604e --- /dev/null +++ b/modules/galaxy/galaxymodule.cpp @@ -0,0 +1,41 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2015 * + * * + * 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 +#include +#include +#include +#include + +namespace openspace { + +GalaxyModule::GalaxyModule() : OpenSpaceModule("Galaxy") {} + +void GalaxyModule::internalInitialize() { + auto fRenderable = FactoryManager::ref().factory(); + ghoul_assert(fRenderable, "No renderable factory existed"); + fRenderable->registerClass("RenderableGalaxy"); +} + +} // namespace openspace diff --git a/modules/galaxy/galaxymodule.h b/modules/galaxy/galaxymodule.h new file mode 100644 index 0000000000..26b4341b30 --- /dev/null +++ b/modules/galaxy/galaxymodule.h @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2015 * + * * + * 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 __GALAXYMODULE_H__ +#define __GALAXYMODULE_H__ + +#include + +namespace openspace { + +class GalaxyModule : public OpenSpaceModule { +public: + GalaxyModule(); + void internalInitialize() override; +}; + +} // namespace openspace + +#endif // __GALAXYMODULE_H__ diff --git a/modules/galaxy/include.cmake b/modules/galaxy/include.cmake new file mode 100644 index 0000000000..163c5a64bf --- /dev/null +++ b/modules/galaxy/include.cmake @@ -0,0 +1,4 @@ +set (DEFAULT_MODULE ON) +set (OPENSPACE_DEPENDENCIES + volume +) \ No newline at end of file diff --git a/modules/galaxy/rendering/galaxyraycaster.cpp b/modules/galaxy/rendering/galaxyraycaster.cpp new file mode 100644 index 0000000000..91a6689f35 --- /dev/null +++ b/modules/galaxy/rendering/galaxyraycaster.cpp @@ -0,0 +1,177 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace { + const std::string GlslRaycastPath = "${MODULES}/galaxy/shaders/galaxyraycast.glsl"; + const std::string GlslBoundsVsPath = "${MODULES}/galaxy/shaders/raycasterbounds.vs"; + const std::string GlslBoundsFsPath = "${MODULES}/galaxy/shaders/raycasterbounds.fs"; +} + +namespace openspace { + +GalaxyRaycaster::GalaxyRaycaster(ghoul::opengl::Texture& texture) + : _boundingBox(glm::vec3(1.0)) + , _texture(texture) + , _textureUnit(nullptr) {} + +GalaxyRaycaster::~GalaxyRaycaster() {} + +void GalaxyRaycaster::initialize() { + _boundingBox.initialize(); +} + +void GalaxyRaycaster::deinitialize() { +} + +void GalaxyRaycaster::renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) { + program.setUniform("modelTransform", _modelTransform); + program.setUniform("viewProjection", data.camera.viewProjectionMatrix()); + program.setUniform("blendMode", static_cast(1)); + + Renderable::setPscUniforms(program, data.camera, data.position); + + // Cull back face + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + // Render bounding geometry + _boundingBox.render(); +} + +void GalaxyRaycaster::renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) { + // Uniforms + program.setUniform("modelTransform", _modelTransform); + program.setUniform("viewProjection", data.camera.viewProjectionMatrix()); + program.setUniform("blendMode", static_cast(1)); + Renderable::setPscUniforms(program, data.camera, data.position); + + // Cull front face + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + + // Render bounding geometry + _boundingBox.render(); + + // Restore defaults + glCullFace(GL_BACK); +} + +void GalaxyRaycaster::preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + std::string colorUniformName = "color" + std::to_string(data.id); + std::string stepSizeUniformName = "maxStepSize" + std::to_string(data.id); + std::string galaxyTextureUniformName = "galaxyTexture" + std::to_string(data.id); + std::string volumeAspectUniformName = "aspect" + std::to_string(data.id); + std::string opacityCoefficientUniformName = "opacityCoefficient" + std::to_string(data.id); + + program.setUniform(volumeAspectUniformName, _aspect); + program.setUniform(stepSizeUniformName, _stepSize); + program.setUniform(opacityCoefficientUniformName, _opacityCoefficient); + + _textureUnit = std::make_unique(); + _textureUnit->activate(); + _texture.bind(); + program.setUniform(galaxyTextureUniformName, *_textureUnit); + +} + +void GalaxyRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + _textureUnit = nullptr; // release texture unit. +} + +bool GalaxyRaycaster::cameraIsInside(const RenderData& data, glm::vec3& localPosition) { + // Camera rig position in world coordinates. + glm::vec4 rigWorldPos = glm::vec4(data.camera.position().vec3(), 1.0); + //rigWorldPos /= data.camera.scaling().x * pow(10.0, data.camera.scaling().y); + //glm::mat4 invSgctMatrix = glm::inverse(data.camera.viewMatrix()); + + // Camera position in world coordinates. + glm::vec4 camWorldPos = rigWorldPos; + glm::vec3 objPos = data.position.vec3(); + + glm::mat4 modelTransform = glm::translate(_modelTransform, objPos); + + float divisor = 1.0; + for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { + if (abs(modelTransform[i][j] > divisor)) divisor = modelTransform[i][j]; + } + + glm::mat4 scaledModelTransform = modelTransform / divisor; + + glm::vec4 modelPos = (glm::inverse(scaledModelTransform) / divisor) * camWorldPos; + + localPosition = (modelPos.xyz() + glm::vec3(0.5)); + return (localPosition.x > 0 && localPosition.y > 0 && localPosition.z > 0 && localPosition.x < 1 && localPosition.y < 1 && localPosition.z < 1); +} + +std::string GalaxyRaycaster::getBoundsVsPath() const { + return GlslBoundsVsPath; +} + +std::string GalaxyRaycaster::getBoundsFsPath() const { + return GlslBoundsFsPath; +} + +std::string GalaxyRaycaster::getRaycastPath() const { + return GlslRaycastPath; +} + +std::string GalaxyRaycaster::getHelperPath() const { + return ""; // no helper file +} + +void GalaxyRaycaster::setAspect(const glm::vec3& aspect) { + _aspect = aspect / std::max(std::max(aspect.x, aspect.y), aspect.z); +} + +void GalaxyRaycaster::setModelTransform(glm::mat4 transform) { + _modelTransform = transform; +} + +void GalaxyRaycaster::setOpacityCoefficient(float opacityCoefficient) { + _opacityCoefficient = opacityCoefficient; +} + +void GalaxyRaycaster::setTime(double time) { + _time = time; +} + +void GalaxyRaycaster::setStepSize(float stepSize) { + _stepSize = stepSize; +} + +} diff --git a/modules/galaxy/rendering/galaxyraycaster.h b/modules/galaxy/rendering/galaxyraycaster.h new file mode 100644 index 0000000000..34720a0868 --- /dev/null +++ b/modules/galaxy/rendering/galaxyraycaster.h @@ -0,0 +1,87 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __GALAXYRAYCASTER_H__ +#define __GALAXYRAYCASTER_H__ + +#include +#include +#include +#include +#include +#include + +namespace ghoul { + namespace opengl { + class Texture; + class TextureUnit; + class ProgramObject; + } +} + +namespace openspace { + +class RenderData; +class RaycastData; + +class GalaxyRaycaster : public VolumeRaycaster { +public: + + GalaxyRaycaster(ghoul::opengl::Texture& texture); + + virtual ~GalaxyRaycaster(); + void initialize(); + void deinitialize(); + void renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; + void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; + void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + bool cameraIsInside(const RenderData& data, glm::vec3& localPosition) override; + + + std::string getBoundsVsPath() const override; + std::string getBoundsFsPath() const override; + std::string getRaycastPath() const override; + std::string getHelperPath() const override; + + void setAspect(const glm::vec3& aspect); + void setModelTransform(glm::mat4 transform); + void setTime(double time); + void setStepSize(float stepSize); + void setOpacityCoefficient(float opacityCoefficient); +private: + BoxGeometry _boundingBox; + float _stepSize; + glm::mat4 _modelTransform; + glm::vec3 _aspect; + double _time; + float _opacityCoefficient; + ghoul::opengl::Texture& _texture; + std::unique_ptr _textureUnit; + +}; // GalaxyRaycaster + +} // openspace + +#endif // __GALAXYRRAYCASTER_H__ diff --git a/modules/galaxy/rendering/renderablegalaxy.cpp b/modules/galaxy/rendering/renderablegalaxy.cpp new file mode 100644 index 0000000000..6ecfd1a46d --- /dev/null +++ b/modules/galaxy/rendering/renderablegalaxy.cpp @@ -0,0 +1,367 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + + +namespace { + const std::string GlslRayCastPath = "${MODULES}/toyvolume/shaders/rayCast.glsl"; + const std::string GlslBoundsVsPath = "${MODULES}/toyvolume/shaders/boundsVs.glsl"; + const std::string GlslBoundsFsPath = "${MODULES}/toyvolume/shaders/boundsFs.glsl"; + const std::string _loggerCat = "Renderable Galaxy"; +} + +namespace openspace { + + RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _stepSize("stepSize", "Step Size", 0.012, 0.0005, 0.05) + , _pointStepSize("pointStepSize", "Point Step Size", 0.01, 0.01, 0.1) + , _translation("translation", "Translation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0), glm::vec3(10.0)) + , _rotation("rotation", "Euler rotation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0), glm::vec3(6.28)) + , _enabledPointsRatio("nEnabledPointsRatio", "Enabled points", 0.2, 0, 1) { + + float stepSize; + glm::vec3 scaling, translation, rotation; + glm::vec4 color; + ghoul::Dictionary volumeDictionary, pointsDictionary; + + if (dictionary.getValue("Translation", translation)) { + _translation = translation; + } + if (dictionary.getValue("Rotation", rotation)) { + _rotation = rotation; + } + if (dictionary.getValue("StepSize", stepSize)) { + _stepSize = stepSize; + } + if (dictionary.getValue("Volume", volumeDictionary)) { + std::string volumeFilename; + if (volumeDictionary.getValue("Filename", volumeFilename)) { + _volumeFilename = absPath(volumeFilename); + } else { + LERROR("No volume filename specified."); + } + glm::vec3 volumeDimensions; + if (volumeDictionary.getValue("Dimensions", volumeDimensions)) { + _volumeDimensions = static_cast(volumeDimensions); + } else { + LERROR("No volume dimensions specified."); + } + glm::vec3 volumeSize; + if (volumeDictionary.getValue("Size", volumeSize)) { + _volumeSize = static_cast(volumeSize); + } + else { + LERROR("No volume dimensions specified."); + } + + } else { + LERROR("No volume dictionary specified."); + } + if (dictionary.getValue("Points", pointsDictionary)) { + std::string pointsFilename; + if (pointsDictionary.getValue("Filename", pointsFilename)) { + _pointsFilename = absPath(pointsFilename); + } else { + LERROR("No points filename specified."); + } + glm::vec3 pointsScaling; + if (pointsDictionary.getValue("Scaling", pointsScaling)) { + _pointScaling = static_cast(pointsScaling); + } + else { + LERROR("No volume dimensions specified."); + } + } else { + LERROR("No points dictionary specified."); + } + +} + +RenderableGalaxy::~RenderableGalaxy() {} + +bool RenderableGalaxy::initialize() { + // Aspect is currently hardcoded to cubic voxels. + _aspect = static_cast(_volumeDimensions); + _aspect = _aspect / std::max(std::max(_aspect.x, _aspect.y), _aspect.z); + + RawVolumeReader> reader(_volumeFilename, _volumeDimensions); + _volume = reader.read(); + + _texture = std::make_unique( + _volumeDimensions, + ghoul::opengl::Texture::Format::RGBA, + GL_RGBA32F, + GL_FLOAT, + ghoul::opengl::Texture::FilterMode::Linear, + ghoul::opengl::Texture::WrappingMode::Clamp); + + _texture->setPixelData(reinterpret_cast(_volume->data()), ghoul::opengl::Texture::TakeOwnership::No); + _texture->setDimensions(_volume->dimensions()); + _texture->uploadTexture(); + + _raycaster = std::make_unique(*_texture); + _raycaster->initialize(); + + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + + std::function onChange = [&](bool enabled) { + if (enabled) { + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + } + else { + OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get()); + } + }; + + onEnabledChange(onChange); + + addProperty(_stepSize); + addProperty(_pointStepSize); + addProperty(_translation); + addProperty(_rotation); + addProperty(_enabledPointsRatio); + + // initialize points. + std::ifstream pointFile(_pointsFilename, std::ios::in | std::ios::binary); + + std::vector pointPositions; + std::vector pointColors; + + int64_t nPoints; + pointFile.seekg(0, std::ios::beg); // read heder. + pointFile.read(reinterpret_cast(&nPoints), sizeof(int64_t)); + + _nPoints = static_cast(nPoints); + + size_t nFloats = _nPoints * 7; + + float* pointData = new float[nFloats]; + pointFile.seekg(sizeof(int64_t), std::ios::beg); // read past heder. + pointFile.read(reinterpret_cast(pointData), nFloats * sizeof(float)); + pointFile.close(); + + float maxdist = 0; + + + float x, y, z, r, g, b, a; + for (size_t i = 0; i < _nPoints; ++i) { + float x = pointData[i * 7 + 0]; + float y = pointData[i * 7 + 1]; + float z = pointData[i * 7 + 2]; + float r = pointData[i * 7 + 3]; + float g = pointData[i * 7 + 4]; + float b = pointData[i * 7 + 5]; + maxdist = std::max(maxdist, glm::length(glm::vec3(x, y, z))); + //float a = pointData[i * 7 + 6]; alpha is not used. + + pointPositions.push_back(glm::vec3(x, y, z)); + pointColors.push_back(glm::vec3(r, g, b)); + } + + std::cout << maxdist << std::endl; + + delete[] pointData; + + glGenVertexArrays(1, &_pointsVao); + glGenBuffers(1, &_positionVbo); + glGenBuffers(1, &_colorVbo); + + glBindVertexArray(_pointsVao); + glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); + glBufferData(GL_ARRAY_BUFFER, + pointPositions.size()*sizeof(glm::vec3), + pointPositions.data(), + GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); + glBufferData(GL_ARRAY_BUFFER, + pointColors.size()*sizeof(glm::vec3), + pointColors.data(), + GL_STATIC_DRAW); + + + RenderEngine& renderEngine = OsEng.renderEngine(); + _pointsProgram = renderEngine.buildRenderProgram("Galaxy points", + "${MODULE_GALAXY}/shaders/points.vs", + "${MODULE_GALAXY}/shaders/points.fs", + ghoul::Dictionary(), + RenderEngine::RenderProgramType::Post); + + _pointsProgram->setIgnoreUniformLocationError(ghoul::opengl::ProgramObject::IgnoreError::Yes); + + GLint positionAttrib = _pointsProgram->attributeLocation("inPosition"); + GLint colorAttrib = _pointsProgram->attributeLocation("inColor"); + + glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); + glEnableVertexAttribArray(positionAttrib); + glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); + glEnableVertexAttribArray(colorAttrib); + glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + return true; +} + +bool RenderableGalaxy::deinitialize() { + if (_raycaster) { + OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get()); + _raycaster = nullptr; + } + return true; +} + +bool RenderableGalaxy::isReady() const { + return true; +} + +void RenderableGalaxy::update(const UpdateData& data) { + if (_raycaster) { + + //glm::mat4 transform = glm::translate(, static_cast(_translation)); + glm::vec3 eulerRotation = static_cast(_rotation); + glm::mat4 transform = glm::rotate(glm::mat4(1.0), eulerRotation.x, glm::vec3(1, 0, 0)); + transform = glm::rotate(transform, eulerRotation.y, glm::vec3(0, 1, 0)); + transform = glm::rotate(transform, eulerRotation.z, glm::vec3(0, 0, 1)); + + + glm::mat4 volumeTransform = glm::scale(transform, static_cast(_volumeSize)); + _pointTransform = glm::scale(transform, static_cast(_pointScaling)); + + glm::vec4 translation = glm::vec4(static_cast(_translation), 0.0); + + // Todo: handle floating point overflow, to actually support translation. + + volumeTransform[3] += translation; + _pointTransform[3] += translation; + + + _raycaster->setStepSize(_stepSize); + _raycaster->setAspect(_aspect); + _raycaster->setModelTransform(volumeTransform); + _raycaster->setTime(data.time); + } +} + +void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { + RaycasterTask task{ _raycaster.get(), data }; + + glm::vec3 position = data.camera.position().vec3(); + float length = safeLength(position); + glm::vec3 galaxySize = static_cast(_volumeSize); + + float maxDim = std::max(std::max(galaxySize.x, galaxySize.y), galaxySize.z); + + + float lowerRampStart = maxDim * 0.02; + float lowerRampEnd = maxDim * 0.5; + + float upperRampStart = maxDim * 2.0; + float upperRampEnd = maxDim * 10; + + float opacityCoefficient = 1.0; + + if (length < lowerRampStart) { + opacityCoefficient = 0; // camera really close + } else if (length < lowerRampEnd) { + opacityCoefficient = (length - lowerRampStart) / (lowerRampEnd - lowerRampStart); + } else if (length < upperRampStart) { + opacityCoefficient = 1.0; // sweet spot (max) + } else if (length < upperRampEnd) { + opacityCoefficient = 1.0 - (length - upperRampStart) / (upperRampEnd - upperRampStart); //fade out + } else { + opacityCoefficient = 0; + } + + _opacityCoefficient = opacityCoefficient; + ghoul_assert(_opacityCoefficient >= 0.0 && _opacityCoefficient <= 1.0, "Opacity coefficient was not between 0 and 1"); + if (opacityCoefficient > 0) { + _raycaster->setOpacityCoefficient(_opacityCoefficient); + tasks.raycasterTasks.push_back(task); + } +} + +float RenderableGalaxy::safeLength(const glm::vec3& vector) { + float maxComponent = std::max(std::max(std::abs(vector.x), std::abs(vector.y)), std::abs(vector.z)); + return glm::length(vector / maxComponent) * maxComponent; +} + +void RenderableGalaxy::postRender(const RenderData& data) { + + _raycaster->setStepSize(_pointStepSize); + + _pointsProgram->activate(); + setPscUniforms(*_pointsProgram.get(), data.camera, data.position); + + OsEng.ref().renderEngine().preRaycast(*_pointsProgram); + + glm::mat4 modelMatrix = _pointTransform; + glm::mat4 viewMatrix = data.camera.viewMatrix(); + glm::mat4 projectionMatrix = data.camera.projectionMatrix(); + + _pointsProgram->setUniform("model", modelMatrix); + _pointsProgram->setUniform("view", viewMatrix); + _pointsProgram->setUniform("projection", projectionMatrix); + + float emittanceFactor = _opacityCoefficient * static_cast(_volumeSize).x; + _pointsProgram->setUniform("emittanceFactor", emittanceFactor); + + glBindVertexArray(_pointsVao); + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDrawArrays(GL_POINTS, 0, _nPoints * _enabledPointsRatio); + glBindVertexArray(0); + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + OsEng.ref().renderEngine().postRaycast(*_pointsProgram); +} + +} diff --git a/modules/galaxy/rendering/renderablegalaxy.h b/modules/galaxy/rendering/renderablegalaxy.h new file mode 100644 index 0000000000..69b395a2dd --- /dev/null +++ b/modules/galaxy/rendering/renderablegalaxy.h @@ -0,0 +1,80 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __RENDERABLEGALAXY_H__ +#define __RENDERABLEGALAXY_H__ + +#include +#include +#include +#include +#include + +namespace openspace { + +struct RenderData; + +class RenderableGalaxy : public Renderable { +public: + RenderableGalaxy(const ghoul::Dictionary& dictionary); + ~RenderableGalaxy(); + + bool initialize() override; + bool deinitialize() override; + bool isReady() const override; + void render(const RenderData& data, RendererTasks& tasks) override; + void postRender(const RenderData& data) override; + void update(const UpdateData& data) override; + +private: + float safeLength(const glm::vec3& vector); + + glm::vec3 _volumeSize; + glm::vec3 _pointScaling; + properties::FloatProperty _stepSize; + properties::FloatProperty _pointStepSize; + properties::Vec3Property _translation; + properties::Vec3Property _rotation; + properties::FloatProperty _enabledPointsRatio; + + std::string _volumeFilename; + glm::ivec3 _volumeDimensions; + std::string _pointsFilename; + + std::unique_ptr _raycaster; + std::unique_ptr>> _volume; + std::unique_ptr _texture; + glm::mat4 _pointTransform; + glm::vec3 _aspect; + float _opacityCoefficient; + + std::unique_ptr _pointsProgram; + size_t _nPoints; + GLuint _pointsVao; + GLuint _positionVbo; + GLuint _colorVbo; +}; +} + +#endif // __RENDERABLEGALAXY_H__ diff --git a/modules/galaxy/shaders/galaxyraycast.glsl b/modules/galaxy/shaders/galaxyraycast.glsl new file mode 100644 index 0000000000..7bdf9d9dd3 --- /dev/null +++ b/modules/galaxy/shaders/galaxyraycast.glsl @@ -0,0 +1,97 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +uniform float maxStepSize#{id} = 0.1; +uniform vec3 aspect#{id} = vec3(1.0); +uniform float opacityCoefficient#{id} = 1.0; + +uniform sampler3D galaxyTexture#{id}; + +void sample#{id}(vec3 samplePos, + vec3 dir, + inout vec3 accumulatedColor, + inout vec3 accumulatedAlpha, + inout float maxStepSize) { + + vec3 aspect = aspect#{id}; + maxStepSize = maxStepSize#{id} / length(dir/aspect); + + vec4 sampledColor = texture(galaxyTexture#{id}, samplePos.xyz); + + float STEP_SIZE = maxStepSize#{id}; + + vec3 alphaTint = vec3(0.3, 0.54, 0.85); + //alphaTint = vec3(0.0, 0.5, 1.0); + + sampledColor = sampledColor*sampledColor; + sampledColor.a = pow(sampledColor.a, 0.7); + //sampledColor.rgba = min(vec4(1.0), sampledColor.rgba); + + //sampledColor.a = clamp(sampledColor.a * 10000000000.0, 0.0, 1.0); + //sampledColor.a = exp(-sampledColor.a); + // + + //sampledColor.rgb = pow(sampledColor.rgb, vec3(10.0)); + //sampledColor.a = pow(sampledColor.a, 10.0); + //sampledColor.a = pow(sampledColor.a, 100000000.0); + sampledColor.rgb *= 500.0; + sampledColor.a = sampledColor.a * 0.3; //1.0; + + + //float emissionCoefficient = 80; + //float absorptionCoefficient = 1; +// sampledColor = clamp(sampledColor, 0.0, 1.0); + + //backColor = vec3(1.0) - pow(vec3(1.0) - backColor, vec3(STEP_SIZE)); + /*if (sampledColor.a > 1.0) { + sampledColor.a = 1.0; + //accumulatedColor = vec3(1.0, 0.0, 0.0); + //accumulatedAlpha = vec3(1.0, 1.0, 1.0); + //return; + }*/ + //sampledColor.a = 1.2; + + //sampledColor.a *= 0.00001; + + vec3 backColor = sampledColor.rgb; + vec3 backAlpha = sampledColor.a * alphaTint; + + backColor *= STEP_SIZE * opacityCoefficient#{id}; + backAlpha *= STEP_SIZE * opacityCoefficient#{id}; + + backColor = clamp(backColor, 0.0, 1.0); + backAlpha = clamp(backAlpha, 0.0, 1.0); + + vec3 oneMinusFrontAlpha = vec3(1.0) - accumulatedAlpha; + accumulatedColor += oneMinusFrontAlpha * backColor; + accumulatedAlpha += oneMinusFrontAlpha * backAlpha; + + // acc+= 1.0; + + //accumulatedColor = vec3(opacityCoefficient#{id}); +} + +float stepSize#{id}(vec3 samplePos, vec3 dir) { + return maxStepSize#{id} * length(dir * 1.0/aspect#{id}); +} diff --git a/modules/galaxy/shaders/points.fs b/modules/galaxy/shaders/points.fs new file mode 100644 index 0000000000..74548099fe --- /dev/null +++ b/modules/galaxy/shaders/points.fs @@ -0,0 +1,47 @@ +/***************************************************************************************** + * * + * 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. * + ****************************************************************************************/ + +uniform float emittanceFactor; + +in vec3 vsPosition; +in vec3 vsColor; + +#include "fragment.glsl" +#include "PowerScaling/powerScaling_fs.hglsl" + +Fragment getFragment() { + vec4 color = vec4(vsColor, 1.0); + + Fragment frag; + float depth = pscDepth(vec4(vsPosition, 0.0)); + + float coefficient = exp(1.38 * log(emittanceFactor) - 2*log(depth)); + + frag.color = vec4(vsColor.rgb * coefficient, 1.0); + + + frag.depth = depth; + + return frag; +} diff --git a/modules/galaxy/shaders/points.vs b/modules/galaxy/shaders/points.vs new file mode 100644 index 0000000000..2e1170fdcd --- /dev/null +++ b/modules/galaxy/shaders/points.vs @@ -0,0 +1,53 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +in vec3 inPosition; +in vec3 inColor; + +out vec3 vsPosition; +out vec3 vsColor; + + +#include "PowerScaling/powerScaling_vs.hglsl" + +void main() { + vec4 p = vec4(inPosition, 1.0); + + vec4 worldPosition = model * p; + worldPosition.w = 0.0; + vec4 position = worldPosition; //pscTransform(worldPosition, model); + + + position = pscTransform(position, mat4(1.0)); + vsPosition = position.xyz; + position = projection * view * position; + gl_Position = z_normalization(position); + vsColor = inColor; +} diff --git a/modules/galaxy/shaders/raycasterbounds.fs b/modules/galaxy/shaders/raycasterbounds.fs new file mode 100644 index 0000000000..a335c00b51 --- /dev/null +++ b/modules/galaxy/shaders/raycasterbounds.fs @@ -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. * + ****************************************************************************************/ + +in vec3 vPosition; +in vec4 worldPosition; + +uniform uint blendMode; + +#include "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +Fragment getFragment() { + vec4 fragColor = vec4((vPosition+0.5), 1.0); + vec4 position = worldPosition; + float depth = pscDepth(position); + + Fragment frag; + frag.color = fragColor; + frag.depth = depth; + frag.blend = blendMode; + return frag; +} diff --git a/modules/galaxy/shaders/raycasterbounds.vs b/modules/galaxy/shaders/raycasterbounds.vs new file mode 100644 index 0000000000..a304a22d03 --- /dev/null +++ b/modules/galaxy/shaders/raycasterbounds.vs @@ -0,0 +1,49 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec4 vertPosition; + +uniform mat4 viewProjection; +uniform mat4 modelTransform; + +out vec3 vPosition; +out vec4 worldPosition; + +#include "PowerScaling/powerScaling_vs.hglsl" + +void main() { + vPosition = vertPosition.xyz; + + worldPosition = modelTransform * vec4(vertPosition.xyz, 1.0); + worldPosition.w = 0.0; + vec4 position = pscTransform(worldPosition, mat4(1.0)); + + + + // project the position to view space + gl_Position = z_normalization(viewProjection * position); + //gl_Position.z = 1.0; +} diff --git a/modules/iswa/util/iswamanager.h b/modules/iswa/util/iswamanager.h index b3ca5a7ef0..7707fa4a14 100644 --- a/modules/iswa/util/iswamanager.h +++ b/modules/iswa/util/iswamanager.h @@ -31,7 +31,9 @@ #include #include #include +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED #include +#endif #include #include #include diff --git a/modules/multiresvolume/include.cmake b/modules/multiresvolume/include.cmake index 163c5a64bf..3ccace7c97 100644 --- a/modules/multiresvolume/include.cmake +++ b/modules/multiresvolume/include.cmake @@ -1,4 +1 @@ set (DEFAULT_MODULE ON) -set (OPENSPACE_DEPENDENCIES - volume -) \ No newline at end of file diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp index 24def3475e..1d08f19e18 100644 --- a/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp +++ b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp @@ -127,6 +127,33 @@ void MultiresVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl: program.setUniform("atlasSize_" + id, atlasSize); } +bool MultiresVolumeRaycaster::cameraIsInside(const RenderData& data, glm::vec3& localPosition) { + // Camera rig position in world coordinates. + glm::vec4 rigWorldPos = glm::vec4(data.camera.position().vec3(), 1.0); + //rigWorldPos /= data.camera.scaling().x * pow(10.0, data.camera.scaling().y); + glm::mat4 invSgctMatrix = glm::inverse(data.camera.viewMatrix()); + + // Camera position in world coordinates. + glm::vec4 camWorldPos = rigWorldPos; + glm::vec3 objPos = data.position.vec3(); + + glm::mat4 modelTransform = glm::translate(_modelTransform, objPos); + + float divisor = 1.0; + for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { + if (abs(modelTransform[i][j] > divisor)) divisor = modelTransform[i][j]; + } + + glm::mat4 scaledModelTransform = modelTransform / divisor; + + glm::vec4 modelPos = (glm::inverse(scaledModelTransform) / divisor) * camWorldPos; + + + localPosition = (modelPos.xyz() + glm::vec3(0.5)); + return (localPosition.x > 0 && localPosition.y > 0 && localPosition.z > 0 && localPosition.x < 1 && localPosition.y < 1 && localPosition.z < 1); + +} + void MultiresVolumeRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { // For example: release texture units } diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.h b/modules/multiresvolume/rendering/multiresvolumeraycaster.h index b2241fd0fe..1c48cc1828 100644 --- a/modules/multiresvolume/rendering/multiresvolumeraycaster.h +++ b/modules/multiresvolume/rendering/multiresvolumeraycaster.h @@ -66,6 +66,7 @@ public: void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + bool cameraIsInside(const RenderData& data, glm::vec3& localPosition) override; std::string getBoundsVsPath() const override; std::string getBoundsFsPath() const override; diff --git a/modules/multiresvolume/rendering/renderablemultiresvolume.cpp b/modules/multiresvolume/rendering/renderablemultiresvolume.cpp index 4a5ffacf32..0db6385d55 100644 --- a/modules/multiresvolume/rendering/renderablemultiresvolume.cpp +++ b/modules/multiresvolume/rendering/renderablemultiresvolume.cpp @@ -68,6 +68,7 @@ namespace { const std::string _loggerCat = "RenderableMultiresVolume"; const std::string KeyDataSource = "Source"; + const std::string KeyErrorHistogramsSource = "ErrorHistogramsSource"; const std::string KeyHints = "Hints"; const std::string KeyTransferFunction = "TransferFunction"; @@ -124,6 +125,13 @@ RenderableMultiresVolume::RenderableMultiresVolume (const ghoul::Dictionary& dic return; } + _errorHistogramsPath = ""; + if (dictionary.getValue(KeyErrorHistogramsSource, _errorHistogramsPath)) { + _errorHistogramsPath = absPath(_errorHistogramsPath); + } + + + float scalingExponent, stepSizeCoefficient; glm::vec3 scaling, translation, rotation; @@ -143,6 +151,7 @@ RenderableMultiresVolume::RenderableMultiresVolume (const ghoul::Dictionary& dic _stepSizeCoefficient = stepSizeCoefficient; } + std::string startTimeString, endTimeString; bool hasTimeData = true; hasTimeData &= dictionary.getValue(KeyStartTime, startTimeString); @@ -354,7 +363,7 @@ bool RenderableMultiresVolume::initialize() { } }; - + onEnabledChange(onChange); return success; } @@ -384,11 +393,16 @@ bool RenderableMultiresVolume::initializeSelector() { cacheFilename = FileSys.cacheManager()->cachedFilename( cacheName.str(), "", ghoul::filesystem::CacheManager::Persistent::Yes); std::ifstream cacheFile(cacheFilename, std::ios::in | std::ios::binary); + std::string errorHistogramsPath = _errorHistogramsPath; if (cacheFile.is_open()) { // Read histograms from cache. cacheFile.close(); - LINFO("Loading histograms from " << cacheFilename); + LINFO("Loading histograms from cache: " << cacheFilename); success &= _errorHistogramManager->loadFromFile(cacheFilename); + } else if (_errorHistogramsPath != "") { + // Read histograms from scene data. + LINFO("Loading histograms from scene data: " << _errorHistogramsPath); + success &= _errorHistogramManager->loadFromFile(_errorHistogramsPath); } else { // Build histograms from tsp file. LWARNING("Failed to open " << cacheFilename); diff --git a/modules/multiresvolume/rendering/renderablemultiresvolume.h b/modules/multiresvolume/rendering/renderablemultiresvolume.h index 408f5eea0a..1f040edfe1 100644 --- a/modules/multiresvolume/rendering/renderablemultiresvolume.h +++ b/modules/multiresvolume/rendering/renderablemultiresvolume.h @@ -81,6 +81,9 @@ public: virtual void update(const UpdateData& data) override; virtual void render(const RenderData& data, RendererTasks& tasks); + + + //virtual void preResolve(ghoul::opengl::ProgramObject* program) override; //virtual std::string getHeaderPath() override; //virtual std::string getHelperPath() override; @@ -120,6 +123,7 @@ private: std::string _volumeName; std::string _transferFunctionPath; + std::string _errorHistogramsPath; std::shared_ptr _transferFunction; diff --git a/modules/multiresvolume/shaders/boundsVs.glsl b/modules/multiresvolume/shaders/boundsVs.glsl index ab1cd161f7..3345b7a597 100644 --- a/modules/multiresvolume/shaders/boundsVs.glsl +++ b/modules/multiresvolume/shaders/boundsVs.glsl @@ -35,13 +35,11 @@ out vec4 worldPosition; #include "PowerScaling/powerScaling_vs.hglsl" void main() { - vPosition = vertPosition.xyz; - worldPosition = modelTransform*vertPosition; - - vec4 position = pscTransform(worldPosition, mat4(1.0)); - - // project the position to view space - gl_Position = viewProjection * position; + vPosition = vertPosition.xyz; - gl_Position.z = 1.0; + worldPosition = vec4(vertPosition.xyz, 0.0); + vec4 position = pscTransform(worldPosition, modelTransform); + + // project the position to view space + gl_Position = z_normalization(viewProjection * position); } diff --git a/modules/multiresvolume/shaders/raycast.glsl b/modules/multiresvolume/shaders/raycast.glsl index 50265a24de..16c8d96d4f 100644 --- a/modules/multiresvolume/shaders/raycast.glsl +++ b/modules/multiresvolume/shaders/raycast.glsl @@ -73,7 +73,13 @@ float stepSize#{id}(vec3 samplePos, vec3 dir){ } } -vec4 sample#{id}(vec3 samplePos, vec3 dir, vec4 foregroundColor, inout float maxStepSize) { +void sample#{id}(vec3 samplePos, + vec3 dir, + inout vec3 accumulatedColor, + inout vec3 accumulatedAlpha, + inout float maxStepSize) { + + //vec4 sample#{id}(vec3 samplePos, vec3 dir, vec4 foregroundColor, inout float maxStepSize) { //return vec4(1.0, 1.0, 1.0, 1.0); if (true /*opacity_#{id} >= MULTIRES_OPACITY_THRESHOLD*/) { @@ -85,23 +91,30 @@ vec4 sample#{id}(vec3 samplePos, vec3 dir, vec4 foregroundColor, inout float max //sampleCoords = vec3(1.0,0.0, 0.0); float intensity = texture(textureAtlas_#{id}, sampleCoords).x; //intensity = sampleCoords; - + maxStepSize = stepSizeCoefficient_#{id}/float(maxNumBricksPerAxis_#{id})/float(paddedBrickDim_#{id}); //return vec4(vec3(intensity), 1.0); vec4 contribution = texture(transferFunction_#{id}, intensity); - + contribution.a = 1.0 - pow(1.0 - contribution.a, maxStepSize); //contribution = vec4(sampleCoords, 1.0); //vec4 contribution = vec4(vec3(intensity), 1.0); //contribution.a *= 0.3; //contribution = vec4(1.0, 1.0, 1.0, intensity * 1000000.0); //contribution = vec4(1.0, 1.0, 1.0, 1.0); - maxStepSize = stepSizeCoefficient_#{id}/float(maxNumBricksPerAxis_#{id})/float(paddedBrickDim_#{id}); + //contribution.a *= opacity_#{id}; //maxStepSize = 0.01; - return contribution; + + vec3 oneMinusFrontAlpha = vec3(1.0) - accumulatedAlpha; + accumulatedColor += oneMinusFrontAlpha * contribution.rgb * contribution.a; + accumulatedAlpha += oneMinusFrontAlpha * vec3(contribution.a); + + + //accumulatedAlpha = vec3(1.0-); + //return contribution; } else { maxStepSize = 2.0; - return vec4(0.0); + //return vec4(0.0); } } diff --git a/modules/newhorizons/CMakeLists.txt b/modules/newhorizons/CMakeLists.txt index 8f59851507..6ed7a3e3e0 100644 --- a/modules/newhorizons/CMakeLists.txt +++ b/modules/newhorizons/CMakeLists.txt @@ -37,6 +37,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/util/imagesequencer.h ${CMAKE_CURRENT_SOURCE_DIR}/util/instrumentdecoder.h ${CMAKE_CURRENT_SOURCE_DIR}/util/labelparser.h + ${CMAKE_CURRENT_SOURCE_DIR}/util/projectioncomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/util/scannerdecoder.h ${CMAKE_CURRENT_SOURCE_DIR}/util/sequenceparser.h ${CMAKE_CURRENT_SOURCE_DIR}/util/targetdecoder.h @@ -55,6 +56,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/util/imagesequencer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/instrumentdecoder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/labelparser.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/util/projectioncomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/scannerdecoder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/sequenceparser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/targetdecoder.cpp @@ -64,16 +66,16 @@ source_group("Source Files" FILES ${SOURCE_FILES}) set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/shaders/crawlingline_fs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/crawlingline_vs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fboPass_fs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fboPass_vs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fov_fs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fov_vs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/projectiveTexture_fs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/projectiveTexture_vs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/projectionPass_fs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/projectionPass_vs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/modelShader_fs.glsl - ${CMAKE_CURRENT_SOURCE_DIR}/shaders/modelShader_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderableModel_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderableModel_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderableModelProjection_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderableModelProjection_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderablePlanet_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderablePlanet_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderablePlanetProjection_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderablePlanetProjection_vs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/terminatorshadow_fs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/terminatorshadow_vs.glsl ) diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index 529a1438dd..df13bbcec7 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -1,45 +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. * -****************************************************************************************/ + * * + * 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. * + ****************************************************************************************/ -// open space includes #include +#include +#include +#include +#include + +#include #include #include -#include - -#include -#include -#include - -#include -#include -#include "imgui.h" - -#define _USE_MATH_DEFINES -#include -#include namespace { const std::string _loggerCat = "RenderableModelProjection"; @@ -51,22 +43,6 @@ namespace { const std::string keyTextureColor = "Textures.Color"; const std::string keyTextureProject = "Textures.Project"; const std::string keyTextureDefault = "Textures.Default"; - - const std::string keySequenceDir = "Projection.Sequence"; - const std::string keySequenceType = "Projection.SequenceType"; - const std::string keyProjObserver = "Projection.Observer"; - const std::string keyProjTarget = "Projection.Target"; - const std::string keyProjAberration = "Projection.Aberration"; - - const std::string keyInstrument = "Instrument.Name"; - const std::string keyInstrumentFovy = "Instrument.Fovy"; - const std::string keyInstrumentAspect = "Instrument.Aspect"; - const std::string keyInstrumentNear = "Instrument.Near"; - const std::string keyInstrumentFar = "Instrument.Far"; - - const std::string keyTranslation = "DataInputTranslation"; - const std::string sequenceTypeImage = "image-sequence"; - } namespace openspace { @@ -74,24 +50,12 @@ namespace openspace { RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _colorTexturePath("colorTexture", "Color Texture") - , _projectionTexturePath("projectionTexture", "RGB Texture") - , _rotationX("rotationX", "RotationX", 0, 0, 360) - , _rotationY("rotationY", "RotationY", 0, 0, 360) - , _rotationZ("rotationZ", "RotationZ", 0, 0, 360) + , _rotation("rotation", "Rotation", glm::vec3(0.f), glm::vec3(0.f), glm::vec3(360.f)) , _programObject(nullptr) , _fboProgramObject(nullptr) - , _texture(nullptr) + , _baseTexture(nullptr) , _geometry(nullptr) - //, _textureOriginal(nullptr) - , _textureProj(nullptr) - , _textureWhiteSquare(nullptr) - , _alpha(1.f) , _performShading("performShading", "Perform Shading", true) - , _performProjection("performProjection", "Perform Projections", true) - , _clearAllProjections("clearAllProjections", "Clear Projections", false) - , _frameCount(0) - , _programIsDirty(false) - , _clearingImage(absPath("${OPENSPACE_DATA}/scene/common/textures/clear.png")) { std::string name; bool success = dictionary.getValue(SceneGraphNode::KeyName, name); @@ -100,8 +64,11 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di ghoul::Dictionary geometryDictionary; success = dictionary.getValue(keyGeometry, geometryDictionary); if (success) { + using modelgeometry::ModelGeometry; geometryDictionary.setValue(SceneGraphNode::KeyName, name); - _geometry = modelgeometry::ModelGeometry::createFromDictionary(geometryDictionary); + _geometry = std::unique_ptr( + ModelGeometry::createFromDictionary(geometryDictionary) + ); } std::string texturePath = ""; @@ -109,20 +76,16 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di if (success) _colorTexturePath = absPath(texturePath); - success = dictionary.getValue(keyTextureProject, texturePath); - if (success) - _projectionTexturePath = absPath(texturePath); - success = dictionary.getValue(keyTextureDefault, texturePath); if (success) _defaultProjImage = absPath(texturePath); - addPropertySubOwner(_geometry); + addPropertySubOwner(_geometry.get()); + + addProperty(_projectionFading); addProperty(_colorTexturePath); - addProperty(_projectionTexturePath); - _colorTexturePath.onChange(std::bind(&RenderableModelProjection::loadTexture, this)); - _projectionTexturePath.onChange(std::bind(&RenderableModelProjection::loadProjectionTexture, this)); + _colorTexturePath.onChange(std::bind(&RenderableModelProjection::loadTextures, this)); dictionary.getValue(keySource, _source); dictionary.getValue(keyDestination, _destination); @@ -131,20 +94,7 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di setBody(_target); bool completeSuccess = true; - completeSuccess &= dictionary.getValue(keyInstrument, _instrumentID); - completeSuccess &= dictionary.getValue(keyProjObserver, _projectorID); - completeSuccess &= dictionary.getValue(keyProjTarget, _projecteeID); - completeSuccess &= dictionary.getValue(keyInstrumentFovy, _fovy); - completeSuccess &= dictionary.getValue(keyInstrumentAspect, _aspectRatio); - completeSuccess &= dictionary.getValue(keyInstrumentNear, _nearPlane); - completeSuccess &= dictionary.getValue(keyInstrumentFar, _farPlane); - ghoul_assert(completeSuccess, "All neccessary attributes not found in modfile"); - - std::string a = "NONE"; - bool s = dictionary.getValue(keyProjAberration, a); - _aberration = SpiceManager::AberrationCorrection(a); - completeSuccess &= s; - ghoul_assert(completeSuccess, "All neccessary attributes not found in modfile"); + completeSuccess &= initializeProjectionSettings(dictionary); openspace::SpiceManager::ref().addFrame(_target, _source); setBoundingSphere(pss(1.f, 9.f)); @@ -152,310 +102,154 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di addProperty(_performShading); addProperty(_performProjection); addProperty(_clearAllProjections); - addProperty(_rotationX); - addProperty(_rotationY); - addProperty(_rotationZ); - - SequenceParser* parser; - - bool foundSequence = dictionary.getValue(keySequenceDir, _sequenceSource); - if (foundSequence) { - _sequenceSource = absPath(_sequenceSource); - - foundSequence = dictionary.getValue(keySequenceType, _sequenceType); - ghoul_assert(foundSequence, "Did not find sequence"); - //Important: client must define translation-list in mod file IFF playbook - if (dictionary.hasKey(keyTranslation)) { - ghoul::Dictionary translationDictionary; - //get translation dictionary - dictionary.getValue(keyTranslation, translationDictionary); - if (_sequenceType == sequenceTypeImage) { - parser = new LabelParser(name, _sequenceSource, translationDictionary); - openspace::ImageSequencer::ref().runSequenceParser(parser); - - } - } - else { - LWARNING("No translation provided, please make sure all spice calls match playbook!"); - } - } + addProperty(_rotation); + success = initializeParser(dictionary); + ghoul_assert(success, ""); } bool RenderableModelProjection::isReady() const { bool ready = true; ready &= (_programObject != nullptr); - ready &= (_texture != nullptr); + ready &= (_baseTexture != nullptr); + ready &= (_projectionTexture != nullptr); return ready; } bool RenderableModelProjection::initialize() { bool completeSuccess = true; - if (_programObject == nullptr) { - RenderEngine& renderEngine = OsEng.renderEngine(); - _programObject = renderEngine.buildRenderProgram("ModelShader", - "${MODULE_NEWHORIZONS}/shaders/modelShader_vs.glsl", - "${MODULE_NEWHORIZONS}/shaders/modelShader_fs.glsl"); + RenderEngine& renderEngine = OsEng.renderEngine(); + _programObject = renderEngine.buildRenderProgram("ModelShader", + "${MODULE_NEWHORIZONS}/shaders/renderableModel_vs.glsl", + "${MODULE_NEWHORIZONS}/shaders/renderableModel_fs.glsl"); - if (!_programObject) - return false; - } - _programObject->setProgramObjectCallback([&](ghoul::opengl::ProgramObject*) { this->_programIsDirty = true; } ); + _fboProgramObject = ghoul::opengl::ProgramObject::Build("ProjectionPass", + "${MODULE_NEWHORIZONS}/shaders/renderableModelProjection_vs.glsl", + "${MODULE_NEWHORIZONS}/shaders/renderableModelProjection_fs.glsl"); + _fboProgramObject->setIgnoreUniformLocationError( + ghoul::opengl::ProgramObject::IgnoreError::Yes + ); - if (_fboProgramObject == nullptr) { - _fboProgramObject = ghoul::opengl::ProgramObject::Build("ProjectionPass", - "${MODULE_NEWHORIZONS}/shaders/projectionPass_vs.glsl", - "${MODULE_NEWHORIZONS}/shaders/projectionPass_fs.glsl"); - _fboProgramObject->setIgnoreUniformLocationError(ghoul::opengl::ProgramObject::IgnoreError::Yes); - if (!_fboProgramObject) - return false; - } - _fboProgramObject->setProgramObjectCallback([&](ghoul::opengl::ProgramObject*) { this->_programIsDirty = true; } ); + completeSuccess &= loadTextures(); - loadTexture(); - loadProjectionTexture(); - - completeSuccess &= (_texture != nullptr); - //completeSuccess &= (_textureOriginal != nullptr); - completeSuccess &= (_textureProj != nullptr); - completeSuccess &= (_textureWhiteSquare != nullptr); + completeSuccess &= ProjectionComponent::initialize(); completeSuccess &= _geometry->initialize(this); completeSuccess &= !_source.empty(); completeSuccess &= !_destination.empty(); - - - bool gotverts = _geometry->getVertices(&_geometryVertecies) && _geometry->getIndices(&_geometryIndeces); - if (!gotverts) - LWARNING("Lack of vertex data from geometry for image projection"); - - completeSuccess &= auxiliaryRendertarget(); - - return completeSuccess; -} - -bool RenderableModelProjection::auxiliaryRendertarget() { - bool completeSuccess = true; - // set FBO to texture to project to - - GLint defaultFBO; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); - - glGenFramebuffers(1, &_fboID); - glBindFramebuffer(GL_FRAMEBUFFER, _fboID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *_texture, 0); - // check FBO status - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) - completeSuccess &= false; - // switch back to window-system-provided framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); - - int vertexSize = sizeof(modelgeometry::ModelGeometry::Vertex); - - glGenVertexArrays(1, &_vaoID); - glGenBuffers(1, &_vbo); - glGenBuffers(1, &_ibo); - - glBindVertexArray(_vaoID); - glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData(GL_ARRAY_BUFFER, _geometryVertecies.size() * vertexSize, &_geometryVertecies[0], GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glEnableVertexAttribArray(2); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, vertexSize, - reinterpret_cast(offsetof(modelgeometry::ModelGeometry::Vertex, location))); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, vertexSize, - reinterpret_cast(offsetof(modelgeometry::ModelGeometry::Vertex, tex))); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, vertexSize, - reinterpret_cast(offsetof(modelgeometry::ModelGeometry::Vertex, normal))); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _geometryIndeces.size() * sizeof(int), &_geometryIndeces[0], GL_STATIC_DRAW); - - glBindVertexArray(0); - return completeSuccess; } bool RenderableModelProjection::deinitialize() { - if (_geometry) { + if (_geometry) _geometry->deinitialize(); - delete _geometry; - } _geometry = nullptr; - _texture = nullptr; - _textureProj = nullptr; - //_textureOriginal = nullptr; - _textureWhiteSquare = nullptr; + _baseTexture = nullptr; - glDeleteBuffers(1, &_vbo); + ProjectionComponent::deinitialize(); - RenderEngine& renderEngine = OsEng.renderEngine(); - if (_programObject) { - renderEngine.removeRenderProgram(_programObject); - _programObject = nullptr; - } + OsEng.renderEngine().removeRenderProgram(_programObject); + _programObject = nullptr; return true; } -void RenderableModelProjection::clearAllProjections() { - _texture = nullptr; - if (_colorTexturePath.value() != "") { - _texture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath))); - if (_texture) { - LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); - _texture->uploadTexture(); - _texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - } - } - - GLint defaultFBO; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); - glBindFramebuffer(GL_FRAMEBUFFER, _fboID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *_texture, 0); - // check FBO status - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - // switch back to window-system-provided framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); - - - //float tmp = _fadeProjection; - //_fadeProjection = 1.f; - //_projectionTexturePath = _clearingImage; - //imageProjectGPU(); - //_fadeProjection = tmp; - _clearAllProjections = false; -} - void RenderableModelProjection::render(const RenderData& data) { - if (!_programObject) - return; - if (!_textureProj) - return; - if (_clearAllProjections) clearAllProjections(); - _programObject->activate(); - _frameCount++; - _camScaling = data.camera.scaling(); _up = data.camera.lookUpVector(); if (_capture && _performProjection) project(); + _programObject->activate(); + attitudeParameters(_time); _imageTimes.clear(); - double time = openspace::Time::ref().currentTime(); - bool targetPositionCoverage = openspace::SpiceManager::ref().hasSpkCoverage(_target, time); - if (!targetPositionCoverage) { - int frame = _frameCount % 180; - - float fadingFactor = static_cast(sin((frame * M_PI) / 180)); - _alpha = 0.5f + fadingFactor * 0.5f; - } - else - _alpha = 1.0f; - - _programObject->setUniform("ProjectorMatrix", _projectorMatrix); - _programObject->setUniform("boresight", _boresight); _programObject->setUniform("_performShading", _performShading); _programObject->setUniform("sun_pos", _sunPosition.vec3()); - _viewProjection = data.camera.viewProjectionMatrix(); - _programObject->setUniform("ViewProjection", _viewProjection); + _programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); _programObject->setUniform("ModelTransform", _transform); + _programObject->setUniform("_projectionFading", _projectionFading); setPscUniforms(*_programObject, data.camera, data.position); _geometry->setUniforms(*_programObject); - textureBind(); + ghoul::opengl::TextureUnit unit[2]; + unit[0].activate(); + _baseTexture->bind(); + _programObject->setUniform("baseTexture", unit[0]); + + unit[1].activate(); + _projectionTexture->bind(); + _programObject->setUniform("projectionTexture", unit[1]); + _geometry->render(); - // disable shader _programObject->deactivate(); } void RenderableModelProjection::update(const UpdateData& data) { - if (_programIsDirty) { + if (_programObject->isDirty()) _programObject->rebuildFromFile(); + + if (_fboProgramObject->isDirty()) _fboProgramObject->rebuildFromFile(); - _programIsDirty = false; - } _time = data.time; if (openspace::ImageSequencer::ref().isReady() && _performProjection) { openspace::ImageSequencer::ref().updateSequencer(_time); - _capture = openspace::ImageSequencer::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID); + _capture = openspace::ImageSequencer::ref().getImagePaths( + _imageTimes, _projecteeID, _instrumentID + ); } // set spice-orientation in accordance to timestamp if (!_source.empty()) { - _stateMatrix = SpiceManager::ref().positionTransformMatrix(_source, _destination, _time); + _stateMatrix = SpiceManager::ref().positionTransformMatrix( + _source, _destination, _time + ); } - double lt; + double lt; glm::dvec3 p = - openspace::SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", {}, _time, lt); + openspace::SpiceManager::ref().targetPosition( + "SUN", _target, "GALACTIC", {}, _time, lt + ); _sunPosition = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); } -void RenderableModelProjection::imageProjectGPU() { - glDisable(GL_DEPTH_TEST); +void RenderableModelProjection::imageProjectGPU( + std::shared_ptr projectionTexture) +{ + ProjectionComponent::imageProjectBegin(); - // keep handle to the current bound FBO - GLint defaultFBO; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); - - GLint m_viewport[4]; - glGetIntegerv(GL_VIEWPORT, m_viewport); - glBindFramebuffer(GL_FRAMEBUFFER, _fboID); - // set blend eq - glEnable(GL_BLEND); - glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ZERO); - - glViewport(0, 0, static_cast(_texture->width()), static_cast(_texture->height())); _fboProgramObject->activate(); - ghoul::opengl::TextureUnit unitFboProject; - unitFboProject.activate(); - _textureProj->bind(); - _fboProgramObject->setUniform("projectTexture", unitFboProject); + ghoul::opengl::TextureUnit unitFbo; + unitFbo.activate(); + projectionTexture->bind(); + _fboProgramObject->setUniform("projectionTexture", unitFbo); - ghoul::opengl::TextureUnit unitFboCurrent; - unitFboCurrent.activate(); - _texture->bind(); - _fboProgramObject->setUniform("currentTexture", unitFboCurrent); _fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix); _fboProgramObject->setUniform("ModelTransform", _transform); _fboProgramObject->setUniform("_scaling", _camScaling); _fboProgramObject->setUniform("boresight", _boresight); _geometry->setUniforms(*_fboProgramObject); + _geometry->render(); - glBindVertexArray(_vaoID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); - glDrawElements(GL_TRIANGLES, static_cast(_geometryIndeces.size()), GL_UNSIGNED_INT, 0); - glBindVertexArray(0); - _fboProgramObject->deactivate(); - //glDisable(GL_BLEND); - //bind back to default - glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); - glViewport(m_viewport[0], m_viewport[1], - m_viewport[2], m_viewport[3]); - - glEnable(GL_DEPTH_TEST); + + ProjectionComponent::imageProjectEnd(); } void RenderableModelProjection::attitudeParameters(double time) { @@ -468,10 +262,21 @@ void RenderableModelProjection::attitudeParameters(double time) { } _transform = glm::mat4(1); - - glm::mat4 rotPropX = glm::rotate(_transform, glm::radians(static_cast(_rotationX)), glm::vec3(1, 0, 0)); - glm::mat4 rotPropY = glm::rotate(_transform, glm::radians(static_cast(_rotationY)), glm::vec3(0, 1, 0)); - glm::mat4 rotPropZ = glm::rotate(_transform, glm::radians(static_cast(_rotationZ)), glm::vec3(0, 0, 1)); + glm::mat4 rotPropX = glm::rotate( + _transform, + glm::radians(static_cast(_rotation.value().x)), + glm::vec3(1, 0, 0) + ); + glm::mat4 rotPropY = glm::rotate( + _transform, + glm::radians(static_cast(_rotation.value().y)), + glm::vec3(0, 1, 0) + ); + glm::mat4 rotPropZ = glm::rotate( + _transform, + glm::radians(static_cast(_rotation.value().z)), + glm::vec3(0, 0, 1) + ); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { @@ -496,95 +301,33 @@ void RenderableModelProjection::attitudeParameters(double time) { position[3] += (3 + _camScaling[1]); glm::vec3 cpos = position.vec3(); - _projectorMatrix = computeProjectorMatrix(cpos, boresight, _up); -} - -glm::mat4 RenderableModelProjection::computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up) { - //rotate boresight into correct alignment - _boresight = _instrumentMatrix*aim; - glm::vec3 uptmp(_instrumentMatrix*glm::dvec3(up)); - - // create view matrix - glm::vec3 e3 = glm::normalize(_boresight); - glm::vec3 e1 = glm::normalize(glm::cross(uptmp, e3)); - glm::vec3 e2 = glm::normalize(glm::cross(e3, e1)); - glm::mat4 projViewMatrix = glm::mat4(e1.x, e2.x, e3.x, 0.f, - e1.y, e2.y, e3.y, 0.f, - e1.z, e2.z, e3.z, 0.f, - -glm::dot(e1, loc), -glm::dot(e2, loc), -glm::dot(e3, loc), 1.f); - - // create perspective projection matrix - glm::mat4 projProjectionMatrix = glm::perspective(glm::radians(_fovy), _aspectRatio, _nearPlane, _farPlane); - // bias matrix - glm::mat4 projNormalizationMatrix = glm::mat4(0.5f, 0, 0, 0, - 0, 0.5f, 0, 0, - 0, 0, 0.5f, 0, - 0.5f, 0.5f, 0.5f, 1); - return projNormalizationMatrix*projProjectionMatrix*projViewMatrix; -} - - -void RenderableModelProjection::textureBind() { - ghoul::opengl::TextureUnit unit[2]; - unit[0].activate(); - _texture->bind(); - _programObject->setUniform("currentTexture", unit[0]); - unit[1].activate(); - _textureWhiteSquare->bind(); - _programObject->setUniform("projectedTexture", unit[1]); + _projectorMatrix = computeProjectorMatrix(cpos, boresight, _up, _instrumentMatrix, + _fovy, _aspectRatio, _nearPlane, _farPlane, _boresight + ); } void RenderableModelProjection::project() { for (auto img : _imageTimes) { - //std::thread t1(&RenderableModelProjection::attitudeParameters, this, img.startTime); - //t1.join(); attitudeParameters(img.startTime); - _projectionTexturePath = img.path; - imageProjectGPU(); //fbopass + imageProjectGPU(loadProjectionTexture(img.path)); } _capture = false; } -void RenderableModelProjection::loadTexture() { - _texture = nullptr; +bool RenderableModelProjection::loadTextures() { + _baseTexture = nullptr; if (_colorTexturePath.value() != "") { - _texture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath))); - if (_texture) { + _baseTexture = std::move( + ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath)) + ); + if (_baseTexture) { LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); - _texture->uploadTexture(); - _texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - } - } - //_textureOriginal = nullptr; - //if (_colorTexturePath.value() != "") { - // _textureOriginal = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath))); - // if (_textureOriginal) { - // LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); - // _textureOriginal->uploadTexture(); - // _textureOriginal->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - // } - //} - _textureWhiteSquare = nullptr; - if (_defaultProjImage != "") { - _textureWhiteSquare = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_defaultProjImage))); - if (_textureWhiteSquare) { - _textureWhiteSquare->uploadTexture(); - _textureWhiteSquare->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - } - } -} - -void RenderableModelProjection::loadProjectionTexture() { - _textureProj = nullptr; - if (_projectionTexturePath.value() != "") { - _textureProj = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_projectionTexturePath))); - if (_textureProj) { - _textureProj->uploadTexture(); - _textureProj->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); - _textureProj->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); + _baseTexture->uploadTexture(); + _baseTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); } } + return _baseTexture != nullptr; } } // namespace openspace diff --git a/modules/newhorizons/rendering/renderablemodelprojection.h b/modules/newhorizons/rendering/renderablemodelprojection.h index 926b61c597..de9508f445 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.h +++ b/modules/newhorizons/rendering/renderablemodelprojection.h @@ -1,152 +1,104 @@ /***************************************************************************************** -* * -* 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. * -****************************************************************************************/ + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #ifndef __RENDERABLEMODELPROJECTION_H__ #define __RENDERABLEMODELPROJECTION_H__ #include +#include +#include #include -#include #include #include +#include #include -#include -#include #include #include namespace openspace { - namespace modelgeometry { - class ModelGeometry; - } +namespace modelgeometry { + class ModelGeometry; +} - class RenderableModelProjection : public Renderable { - public: - RenderableModelProjection(const ghoul::Dictionary& dictionary); +class RenderableModelProjection : public Renderable, private ProjectionComponent { +public: + RenderableModelProjection(const ghoul::Dictionary& dictionary); - bool initialize() override; - bool deinitialize() override; + bool initialize() override; + bool deinitialize() override; - bool isReady() const override; + bool isReady() const override; - void render(const RenderData& data) override; - void update(const UpdateData& data) override; + void render(const RenderData& data) override; + void update(const UpdateData& data) override; +private: + bool loadTextures(); + void attitudeParameters(double time); + void imageProjectGPU(std::shared_ptr projectionTexture); - protected: - void loadTexture(); - void loadProjectionTexture(); + void project(); - private: - bool auxiliaryRendertarget(); - glm::mat4 computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up); - void attitudeParameters(double time); - void imageProjectGPU(); + properties::StringProperty _colorTexturePath; - void textureBind(); - void project(); - void clearAllProjections(); + properties::Vec3Property _rotation; - properties::StringProperty _colorTexturePath; - properties::BoolProperty _performProjection; - properties::BoolProperty _clearAllProjections; + std::unique_ptr _programObject; + std::unique_ptr _fboProgramObject; - properties::IntProperty _rotationX; - properties::IntProperty _rotationY; - properties::IntProperty _rotationZ; + std::unique_ptr _baseTexture; - std::unique_ptr _programObject; - std::unique_ptr _fboProgramObject; + std::unique_ptr _geometry; - std::unique_ptr _texture; - std::unique_ptr _textureOriginal; - std::unique_ptr _textureProj; - std::unique_ptr _textureWhiteSquare; + glm::dmat3 _stateMatrix; + glm::dmat3 _instrumentMatrix; - modelgeometry::ModelGeometry* _geometry; + std::string _defaultProjImage; + std::string _source; + std::string _destination; + std::string _target; - float _alpha; - glm::dmat3 _stateMatrix; - glm::dmat3 _instrumentMatrix; + // uniforms + glm::vec2 _camScaling; + glm::vec3 _up; + glm::mat4 _transform; + glm::mat4 _projectorMatrix; + glm::vec3 _boresight; - properties::StringProperty _projectionTexturePath; - std::string _defaultProjImage; - std::string _source; - std::string _destination; - std::string _target; + std::vector _imageTimes; + double _time; - // sequence loading - std::string _sequenceSource; - std::string _sequenceType; - - // projection mod info - std::string _instrumentID; - std::string _projectorID; - std::string _projecteeID; - SpiceManager::AberrationCorrection _aberration; - std::vector _potentialTargets; - float _fovy; - float _aspectRatio; - float _nearPlane; - float _farPlane; - - // uniforms - glm::vec2 _camScaling; - glm::vec3 _up; - glm::mat4 _transform; - glm::mat4 _viewProjection; - glm::mat4 _projectorMatrix; - glm::vec3 _boresight; - - // FBO stuff - GLuint _fboID; - GLuint _quad; - GLuint _vertexPositionBuffer; - - GLuint _vbo; - GLuint _ibo; - GLuint _vaoID; - std::vector _geometryVertecies; - std::vector _geometryIndeces; - - std::vector _imageTimes; - int _frameCount; - double _time; - - bool _capture; + bool _capture; - std::string _clearingImage; + psc _sunPosition; - psc _sunPosition; - - properties::BoolProperty _performShading; - bool _programIsDirty; - }; + properties::BoolProperty _performShading; +}; } // namespace openspace diff --git a/modules/newhorizons/rendering/renderableplanetprojection.cpp b/modules/newhorizons/rendering/renderableplanetprojection.cpp index 8b1f3c53fb..7a49f76a7e 100644 --- a/modules/newhorizons/rendering/renderableplanetprojection.cpp +++ b/modules/newhorizons/rendering/renderableplanetprojection.cpp @@ -22,106 +22,58 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -// open space includes #include #include +#include +#include +#include +#include -#include - +#include #include #include -//#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#define _USE_MATH_DEFINES -#include - +#include namespace { const std::string _loggerCat = "RenderablePlanetProjection"; - const std::string keyProjObserver = "Projection.Observer"; - const std::string keyProjTarget = "Projection.Target"; - const std::string keyProjAberration = "Projection.Aberration"; - const std::string keyInstrument = "Instrument.Name"; - const std::string keyInstrumentFovy = "Instrument.Fovy"; - const std::string keyInstrumentAspect = "Instrument.Aspect"; - const std::string keyInstrumentNear = "Instrument.Near"; - const std::string keyInstrumentFar = "Instrument.Far"; - const std::string keySequenceDir = "Projection.Sequence"; - const std::string keySequenceType = "Projection.SequenceType"; - const std::string keyPotentialTargets = "PotentialTargets"; - const std::string keyTranslation = "DataInputTranslation"; - - const std::string keyFrame = "Frame"; const std::string keyGeometry = "Geometry"; const std::string keyShading = "PerformShading"; const std::string keyBody = "Body"; const std::string _mainFrame = "GALACTIC"; - const std::string sequenceTypeImage = "image-sequence"; - const std::string sequenceTypePlaybook = "playbook"; - const std::string sequenceTypeHybrid = "hybrid"; - } namespace openspace { -//#define ORIGINAL_SEQUENCER - RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _colorTexturePath("planetTexture", "RGB Texture") , _heightMapTexturePath("heightMap", "Heightmap Texture") - , _normalMapTexturePath("normalMap", "Normalmap Texture") - , _projectionTexturePath("projectionTexture", "RGB Texture") , _rotation("rotation", "Rotation", 0, 0, 360) - //, _fadeProjection("fadeProjections", "Image Fading Factor", 0.f, 0.f, 1.f) - , _performProjection("performProjection", "Perform Projections", true) - , _clearAllProjections("clearAllProjections", "Clear Projections", false) , _heightExaggeration("heightExaggeration", "Height Exaggeration", 1.f, 0.f, 100.f) - , _enableNormalMapping("enableNormalMapping", "Enable Normal Mapping", true) + , _debugProjectionTextureRotation("debug.projectionTextureRotation", "Projection Texture Rotation", 0.f, 0.f, 360.f) , _programObject(nullptr) , _fboProgramObject(nullptr) - , _texture(nullptr) - , _textureOriginal(nullptr) - , _textureProj(nullptr) - , _textureWhiteSquare(nullptr) + , _baseTexture(nullptr) , _heightMapTexture(nullptr) - , _normalMapTexture(nullptr) - , _geometry(nullptr) , _capture(false) - , _hasHeightMap(false) - , _hasNormalMap(false) - , _clearingImage(absPath("${OPENSPACE_DATA}/scene/common/textures/clear.png")) { std::string name; bool success = dictionary.getValue(SceneGraphNode::KeyName, name); ghoul_assert(success, ""); - _defaultProjImage = absPath("textures/defaultProj.png"); - ghoul::Dictionary geometryDictionary; success = dictionary.getValue( keyGeometry, geometryDictionary); if (success) { geometryDictionary.setValue(SceneGraphNode::KeyName, name); - _geometry = planetgeometry::PlanetGeometry::createFromDictionary(geometryDictionary); + using planetgeometry::PlanetGeometry; + _geometry = std::unique_ptr( + PlanetGeometry::createFromDictionary(geometryDictionary) + ); } dictionary.getValue(keyFrame, _frame); @@ -129,38 +81,9 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& if (_target != "") setBody(_target); - bool b1 = dictionary.getValue(keyInstrument, _instrumentID); - bool b2 = dictionary.getValue(keyProjObserver, _projectorID); - bool b3 = dictionary.getValue(keyProjTarget, _projecteeID); - std::string a = "NONE"; - bool b4 = dictionary.getValue(keyProjAberration, a); - _aberration = SpiceManager::AberrationCorrection(a); - bool b5 = dictionary.getValue(keyInstrumentFovy, _fovy); - bool b6 = dictionary.getValue(keyInstrumentAspect, _aspectRatio); - bool b7 = dictionary.getValue(keyInstrumentNear, _nearPlane); - bool b8 = dictionary.getValue(keyInstrumentFar, _farPlane); - - ghoul_assert(b1, ""); - ghoul_assert(b2, ""); - ghoul_assert(b3, ""); - ghoul_assert(b4, ""); - ghoul_assert(b5, ""); - ghoul_assert(b6, ""); - ghoul_assert(b7, ""); - ghoul_assert(b8, ""); - - // @TODO copy-n-paste from renderablefov ---abock - ghoul::Dictionary potentialTargets; - success = dictionary.getValue(keyPotentialTargets, potentialTargets); + success = initializeProjectionSettings(dictionary); ghoul_assert(success, ""); - _potentialTargets.resize(potentialTargets.size()); - for (int i = 0; i < potentialTargets.size(); ++i) { - std::string target; - potentialTargets.getValue(std::to_string(i + 1), target); - _potentialTargets[i] = target; - } - // TODO: textures need to be replaced by a good system similar to the geometry as soon // as the requirements are fixed (ab) std::string texturePath = ""; @@ -168,239 +91,111 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& if (success){ _colorTexturePath = absPath(texturePath); } - success = dictionary.getValue("Textures.Project", texturePath); - if (success){ - _projectionTexturePath = absPath(texturePath); - } std::string heightMapPath = ""; success = dictionary.getValue("Textures.Height", heightMapPath); - if (success) { + if (success) _heightMapTexturePath = absPath(heightMapPath); - _hasHeightMap = true; - } - std::string normalMapPath = ""; - success = dictionary.getValue("Textures.NormalMap", normalMapPath); - if (success) { - _normalMapTexturePath = absPath(normalMapPath); - _hasNormalMap = true; - } - - addPropertySubOwner(_geometry); - addProperty(_rotation); - //addProperty(_fadeProjection); + addPropertySubOwner(_geometry.get()); addProperty(_performProjection); addProperty(_clearAllProjections); - addProperty(_colorTexturePath); - _colorTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this)); + _colorTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTextures, this)); addProperty(_heightMapTexturePath); - _heightMapTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this)); - - addProperty(_normalMapTexturePath); - _normalMapTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this)); - - addProperty(_projectionTexturePath); - _projectionTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadProjectionTexture, this)); + _heightMapTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTextures, this)); + addProperty(_projectionFading); addProperty(_heightExaggeration); - addProperty(_enableNormalMapping); + addProperty(_debugProjectionTextureRotation); - SequenceParser* parser; - - // std::string sequenceSource; - bool _foundSequence = dictionary.getValue(keySequenceDir, _sequenceSource); - if (_foundSequence) { - _sequenceSource = absPath(_sequenceSource); - - _foundSequence = dictionary.getValue(keySequenceType, _sequenceType); - //Important: client must define translation-list in mod file IFF playbook - if (dictionary.hasKey(keyTranslation)){ - ghoul::Dictionary translationDictionary; - //get translation dictionary - dictionary.getValue(keyTranslation, translationDictionary); - - if (_sequenceType == sequenceTypePlaybook) { - parser = new HongKangParser(name, - _sequenceSource, - _projectorID, - translationDictionary, - _potentialTargets); - openspace::ImageSequencer::ref().runSequenceParser(parser); - } - else if (_sequenceType == sequenceTypeImage) { - parser = new LabelParser(name, - _sequenceSource, - translationDictionary); - openspace::ImageSequencer::ref().runSequenceParser(parser); - } - else if (_sequenceType == sequenceTypeHybrid) { - //first read labels - parser = new LabelParser(name, - _sequenceSource, - translationDictionary); - openspace::ImageSequencer::ref().runSequenceParser(parser); - - std::string _eventFile; - bool foundEventFile = dictionary.getValue("Projection.EventFile", _eventFile); - if (foundEventFile){ - //then read playbook - _eventFile = absPath(_eventFile); - parser = new HongKangParser(name, - _eventFile, - _projectorID, - translationDictionary, - _potentialTargets); - openspace::ImageSequencer::ref().runSequenceParser(parser); - } - else{ - LWARNING("No eventfile has been provided, please check modfiles"); - } - } - } - else{ - LWARNING("No playbook translation provided, please make sure all spice calls match playbook!"); - } - } + success = initializeParser(dictionary); + ghoul_assert(success, ""); } -RenderablePlanetProjection::~RenderablePlanetProjection() { - deinitialize(); -} +RenderablePlanetProjection::~RenderablePlanetProjection() {} bool RenderablePlanetProjection::initialize() { bool completeSuccess = true; - if (_programObject == nullptr) { - // projection program - RenderEngine& renderEngine = OsEng.renderEngine(); - _programObject = renderEngine.buildRenderProgram("projectiveProgram", - "${MODULE_NEWHORIZONS}/shaders/projectiveTexture_vs.glsl", - "${MODULE_NEWHORIZONS}/shaders/projectiveTexture_fs.glsl" - ); - - if (!_programObject) - return false; - } + _programObject = OsEng.renderEngine().buildRenderProgram("projectiveProgram", + "${MODULE_NEWHORIZONS}/shaders/renderablePlanet_vs.glsl", + "${MODULE_NEWHORIZONS}/shaders/renderablePlanet_fs.glsl" + ); _fboProgramObject = ghoul::opengl::ProgramObject::Build("fboPassProgram", - "${MODULE_NEWHORIZONS}/shaders/fboPass_vs.glsl", - "${MODULE_NEWHORIZONS}/shaders/fboPass_fs.glsl" + "${MODULE_NEWHORIZONS}/shaders/renderablePlanetProjection_vs.glsl", + "${MODULE_NEWHORIZONS}/shaders/renderablePlanetProjection_fs.glsl" ); - - loadTexture(); - loadProjectionTexture(); - completeSuccess &= (_texture != nullptr); - completeSuccess &= (_textureOriginal != nullptr); - completeSuccess &= (_textureProj != nullptr); - completeSuccess &= (_textureWhiteSquare != nullptr); + + completeSuccess &= loadTextures(); + completeSuccess &= ProjectionComponent::initialize(); completeSuccess &= _geometry->initialize(this); - if (completeSuccess) - completeSuccess &= auxiliaryRendertarget(); + if (completeSuccess) { + //completeSuccess &= auxiliaryRendertarget(); + // SCREEN-QUAD + const GLfloat size = 1.f; + const GLfloat w = 1.f; + const GLfloat vertex_data[] = { + -size, -size, 0.f, w, 0.f, 0.f, + size, size, 0.f, w, 1.f, 1.f, + -size, size, 0.f, w, 0.f, 1.f, + -size, -size, 0.f, w, 0.f, 0.f, + size, -size, 0.f, w, 1.f, 0.f, + size, size, 0.f, w, 1.f, 1.f, + }; - return completeSuccess; -} + glGenVertexArrays(1, &_quad); + glBindVertexArray(_quad); + glGenBuffers(1, &_vertexPositionBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(0)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(sizeof(GLfloat) * 4)); -bool RenderablePlanetProjection::auxiliaryRendertarget() { - bool completeSuccess = true; - if (!_texture) return false; - - GLint defaultFBO; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); - - // setup FBO - glGenFramebuffers(1, &_fboID); - glBindFramebuffer(GL_FRAMEBUFFER, _fboID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *_texture, 0); - // check FBO status - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) - completeSuccess &= false; - // switch back to window-system-provided framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); - - // SCREEN-QUAD - const GLfloat size = 1.f; - const GLfloat w = 1.f; - const GLfloat vertex_data[] = { - -size, -size, 0.f, w, 0.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, - -size, size, 0.f, w, 0.f, 1.f, - -size, -size, 0.f, w, 0.f, 0.f, - size, -size, 0.f, w, 1.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, - }; - - glGenVertexArrays(1, &_quad); - glBindVertexArray(_quad); - glGenBuffers(1, &_vertexPositionBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(0)); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(sizeof(GLfloat) * 4)); - - glBindVertexArray(0); + glBindVertexArray(0); + } return completeSuccess; } bool RenderablePlanetProjection::deinitialize() { - _texture = nullptr; - _textureProj = nullptr; - _textureOriginal = nullptr; - _textureWhiteSquare = nullptr; - delete _geometry; + ProjectionComponent::deinitialize(); + _baseTexture = nullptr; _geometry = nullptr; - RenderEngine& renderEngine = OsEng.renderEngine(); - if (_programObject) { - renderEngine.removeRenderProgram(_programObject); - _programObject = nullptr; - } + glDeleteVertexArrays(1, &_quad); + glDeleteBuffers(1, &_vertexPositionBuffer); + + OsEng.renderEngine().removeRenderProgram(_programObject); + _programObject = nullptr; + + _fboProgramObject = nullptr; return true; } bool RenderablePlanetProjection::isReady() const { - return _geometry && _programObject && _texture && _textureWhiteSquare; + return _geometry && _programObject && _baseTexture && _projectionTexture; } -void RenderablePlanetProjection::imageProjectGPU() { - glDisable(GL_DEPTH_TEST); +void RenderablePlanetProjection::imageProjectGPU( + std::shared_ptr projectionTexture) +{ + imageProjectBegin(); - // keep handle to the current bound FBO - GLint defaultFBO; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); - - GLint m_viewport[4]; - glGetIntegerv(GL_VIEWPORT, m_viewport); - //counter = 0; - glBindFramebuffer(GL_FRAMEBUFFER, _fboID); - // set blend eq - glEnable(GL_BLEND); - glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ZERO); - - glViewport(0, 0, static_cast(_texture->width()), static_cast(_texture->height())); _fboProgramObject->activate(); ghoul::opengl::TextureUnit unitFbo; unitFbo.activate(); - _textureProj->bind(); - _fboProgramObject->setUniform("texture1" , unitFbo); + projectionTexture->bind(); + _fboProgramObject->setUniform("projectionTexture", unitFbo); - ghoul::opengl::TextureUnit unitFbo2; - unitFbo2.activate(); - _textureOriginal->bind(); - _fboProgramObject->setUniform("texture2", unitFbo2); - //_fboProgramObject->setUniform("projectionFading", _fadeProjection); - _fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix); _fboProgramObject->setUniform("ModelTransform" , _transform); _fboProgramObject->setUniform("_scaling" , _camScaling); @@ -426,49 +221,34 @@ void RenderablePlanetProjection::imageProjectGPU() { glBindVertexArray(_quad); glDrawArrays(GL_TRIANGLES, 0, 6); _fboProgramObject->deactivate(); - //glDisable(GL_BLEND); - //bind back to default - glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); - glViewport(m_viewport[0], m_viewport[1], - m_viewport[2], m_viewport[3]); - - glEnable(GL_DEPTH_TEST); -} - -glm::mat4 RenderablePlanetProjection::computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up) { - //rotate boresight into correct alignment - _boresight = _instrumentMatrix*aim; - glm::vec3 uptmp(_instrumentMatrix*glm::dvec3(up)); - - // create view matrix - glm::vec3 e3 = glm::normalize(_boresight); - glm::vec3 e1 = glm::normalize(glm::cross(uptmp, e3)); - glm::vec3 e2 = glm::normalize(glm::cross(e3, e1)); - glm::mat4 projViewMatrix = glm::mat4(e1.x, e2.x, e3.x, 0.f, - e1.y, e2.y, e3.y, 0.f, - e1.z, e2.z, e3.z, 0.f, - -glm::dot(e1, loc), -glm::dot(e2, loc), -glm::dot(e3, loc), 1.f); - // create perspective projection matrix - glm::mat4 projProjectionMatrix = glm::perspective(glm::radians(_fovy), _aspectRatio, _nearPlane, _farPlane); - // bias matrix - glm::mat4 projNormalizationMatrix = glm::mat4(0.5f, 0, 0, 0, - 0, 0.5f, 0, 0, - 0, 0, 0.5f, 0, - 0.5f, 0.5f, 0.5f, 1); - return projNormalizationMatrix*projProjectionMatrix*projViewMatrix; + imageProjectEnd(); } void RenderablePlanetProjection::attitudeParameters(double time) { // precomputations for shader _stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, _mainFrame, time); - _instrumentMatrix = SpiceManager::ref().positionTransformMatrix(_instrumentID, _mainFrame, time); + _instrumentMatrix = SpiceManager::ref().positionTransformMatrix( + _instrumentID, _mainFrame, time + ); _transform = glm::mat4(1); //90 deg rotation w.r.t spice req. - glm::mat4 rot = glm::rotate(_transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); - glm::mat4 roty = glm::rotate(_transform, static_cast(M_PI_2), glm::vec3(0, -1, 0)); - glm::mat4 rotProp = glm::rotate(_transform, static_cast(glm::radians(static_cast(_rotation))), glm::vec3(0, 1, 0)); + glm::mat4 rot = glm::rotate( + _transform, + static_cast(M_PI_2), + glm::vec3(1, 0, 0) + ); + glm::mat4 roty = glm::rotate( + _transform, + static_cast(M_PI_2), + glm::vec3(0, -1, 0) + ); + glm::mat4 rotProp = glm::rotate( + _transform, + static_cast(glm::radians(static_cast(_rotation))), + glm::vec3(0, 1, 0) + ); for (int i = 0; i < 3; i++){ for (int j = 0; j < 3; j++){ @@ -487,7 +267,10 @@ void RenderablePlanetProjection::attitudeParameters(double time) { return; } - glm::dvec3 p = SpiceManager::ref().targetPosition(_projectorID, _projecteeID, _mainFrame, _aberration, time, lightTime); + double lightTime; + glm::dvec3 p = SpiceManager::ref().targetPosition( + _projectorID, _projecteeID, _mainFrame, _aberration, time, lightTime + ); psc position = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); //change to KM and add psc camera scaling. @@ -495,90 +278,25 @@ void RenderablePlanetProjection::attitudeParameters(double time) { //position[3] += 3; glm::vec3 cpos = position.vec3(); - _projectorMatrix = computeProjectorMatrix(cpos, bs, _up); -} - - -void RenderablePlanetProjection::textureBind() { - ghoul::opengl::TextureUnit unit[4]; - unit[0].activate(); - _texture->bind(); - _programObject->setUniform("texture1", unit[0]); - unit[1].activate(); - _textureWhiteSquare->bind(); - _programObject->setUniform("texture2", unit[1]); - - if (_hasHeightMap) { - unit[2].activate(); - _heightMapTexture->bind(); - _programObject->setUniform("heightTex", unit[2]); - } - - if (_hasNormalMap) { - unit[3].activate(); - _normalMapTexture->bind(); - _programObject->setUniform("normalTex", unit[3]); - } - - -} - -void RenderablePlanetProjection::project(){ - // If high dt -> results in GPU queue overflow - // switching to using a simple queue to distribute - // images 1 image / frame -> projections appear slower - // but less viewable lagg for the sim overall. - - // Comment out if not using queue and prefer old method ------------- - // + in update() function - //if (!imageQueue.empty()){ - // Image& img = imageQueue.front(); - // RenderablePlanetProjection::attitudeParameters(img.startTime); - // // if image has new path - ie actual image, NOT placeholder - // if (_projectionTexturePath.value() != img.path){ - // // rebind and upload - // _projectionTexturePath = img.path; - // } - // imageProjectGPU(); // fbopass - // imageQueue.pop(); - //} - // ------------------------------------------------------------------ - - //---- Old method --- // - // @mm - for (const Image& img : _imageTimes) { - RenderablePlanetProjection::attitudeParameters(img.startTime); - if (_projectionTexturePath.value() != img.path){ - _projectionTexturePath = img.path; // path to current images - } - imageProjectGPU(); // fbopass - } - _capture = false; -} - -void RenderablePlanetProjection::clearAllProjections() { - //float tmp = _fadeProjection; - //_fadeProjection = 1.f; - _projectionTexturePath = _clearingImage; - imageProjectGPU(); - //_fadeProjection = tmp; - _clearAllProjections = false; + _projectorMatrix = computeProjectorMatrix(cpos, bs, _up, _instrumentMatrix, + _fovy, _aspectRatio, _nearPlane, _farPlane, _boresight + ); } void RenderablePlanetProjection::render(const RenderData& data) { - if (!_programObject) - return; - if (!_textureProj) - return; - if (_clearAllProjections) clearAllProjections(); _camScaling = data.camera.scaling(); _up = data.camera.lookUpVector(); - if (_capture && _performProjection) - project(); + if (_capture && _performProjection) { + for (const Image& img : _imageTimes) { + RenderablePlanetProjection::attitudeParameters(img.startTime); + imageProjectGPU(loadProjectionTexture(img.path)); + } + _capture = false; + } attitudeParameters(_time); _imageTimes.clear(); @@ -589,102 +307,66 @@ void RenderablePlanetProjection::render(const RenderData& data) { // Main renderpass _programObject->activate(); - // setup the data to the shader _programObject->setUniform("sun_pos", sun_pos.vec3()); - _programObject->setUniform("ProjectorMatrix", _projectorMatrix); _programObject->setUniform("ViewProjection" , data.camera.viewProjectionMatrix()); _programObject->setUniform("ModelTransform" , _transform); - _programObject->setUniform("boresight" , _boresight); - _programObject->setUniform("_hasHeightMap", _hasHeightMap); + _programObject->setUniform("_hasHeightMap", _heightMapTexture != nullptr); _programObject->setUniform("_heightExaggeration", _heightExaggeration); - _programObject->setUniform("_enableNormalMapping", _enableNormalMapping && _hasNormalMap); + _programObject->setUniform("_projectionFading", _projectionFading); + + //_programObject->setUniform("debug_projectionTextureRotation", glm::radians(_debugProjectionTextureRotation.value())); setPscUniforms(*_programObject.get(), data.camera, data.position); - textureBind(); + ghoul::opengl::TextureUnit unit[3]; + unit[0].activate(); + _baseTexture->bind(); + _programObject->setUniform("baseTexture", unit[0]); + + unit[1].activate(); + _projectionTexture->bind(); + _programObject->setUniform("projectionTexture", unit[1]); + + if (_heightMapTexture) { + unit[2].activate(); + _heightMapTexture->bind(); + _programObject->setUniform("heightTexture", unit[2]); + } - // render geometry _geometry->render(); - // disable shader _programObject->deactivate(); } void RenderablePlanetProjection::update(const UpdateData& data) { - //if (data.isTimeJump) { - if (_time >= Time::ref().currentTime()) { - // if jump back in time -> empty queue. - imageQueue = std::queue(); + if (_fboProgramObject->isDirty()) { + _fboProgramObject->rebuildFromFile(); } - //_time = data.time; + if (_programObject->isDirty()) + _programObject->rebuildFromFile(); + _time = Time::ref().currentTime(); _capture = false; if (openspace::ImageSequencer::ref().isReady() && _performProjection){ openspace::ImageSequencer::ref().updateSequencer(_time); - _capture = openspace::ImageSequencer::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID); + _capture = openspace::ImageSequencer::ref().getImagePaths( + _imageTimes, _projecteeID, _instrumentID + ); } - if (_fboProgramObject && _fboProgramObject->isDirty()) { - _fboProgramObject->rebuildFromFile(); - } - - // remove these lines if not using queue ------------------------ - // @mm - //_capture = true; - //for (auto img : _imageTimes){ - // imageQueue.push(img); - //} - //_imageTimes.clear(); - // -------------------------------------------------------------- - - if (_programObject->isDirty()) - _programObject->rebuildFromFile(); } -void RenderablePlanetProjection::loadProjectionTexture() { - _textureProj = nullptr; - if (_projectionTexturePath.value() != "") { - _textureProj = ghoul::io::TextureReader::ref().loadTexture(absPath(_projectionTexturePath)); - if (_textureProj) { - ghoul::opengl::convertTextureFormat(ghoul::opengl::Texture::Format::RGB, *_textureProj); - _textureProj->uploadTexture(); - // TODO: AnisotropicMipMap crashes on ATI cards ---abock - //_textureProj->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); - _textureProj->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - _textureProj->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); - } - } -} - -void RenderablePlanetProjection::loadTexture() { +bool RenderablePlanetProjection::loadTextures() { using ghoul::opengl::Texture; - _texture = nullptr; + _baseTexture = nullptr; if (_colorTexturePath.value() != "") { - _texture = ghoul::io::TextureReader::ref().loadTexture(_colorTexturePath); - if (_texture) { - ghoul::opengl::convertTextureFormat(Texture::Format::RGB, *_texture); - _texture->uploadTexture(); - _texture->setFilter(Texture::FilterMode::Linear); - } - } - _textureOriginal = nullptr; - if (_colorTexturePath.value() != "") { - _textureOriginal = ghoul::io::TextureReader::ref().loadTexture(_colorTexturePath); - if (_textureOriginal) { - ghoul::opengl::convertTextureFormat(Texture::Format::RGB, *_textureOriginal); - - _textureOriginal->uploadTexture(); - _textureOriginal->setFilter(Texture::FilterMode::Linear); - } - } - _textureWhiteSquare = nullptr; - if (_colorTexturePath.value() != "") { - _textureWhiteSquare = ghoul::io::TextureReader::ref().loadTexture(_defaultProjImage); - if (_textureWhiteSquare) { - _textureWhiteSquare->uploadTexture(); - _textureWhiteSquare->setFilter(Texture::FilterMode::Linear); + _baseTexture = ghoul::io::TextureReader::ref().loadTexture(_colorTexturePath); + if (_baseTexture) { + ghoul::opengl::convertTextureFormat(Texture::Format::RGB, *_baseTexture); + _baseTexture->uploadTexture(); + _baseTexture->setFilter(Texture::FilterMode::Linear); } } @@ -698,14 +380,8 @@ void RenderablePlanetProjection::loadTexture() { } } - _normalMapTexture = nullptr; - if (_normalMapTexturePath.value() != "") { - _normalMapTexture = ghoul::io::TextureReader::ref().loadTexture(_normalMapTexturePath); - if (_normalMapTexture) { - _normalMapTexture->uploadTexture(); - _normalMapTexture->setFilter(Texture::FilterMode::Linear); - } - } + return _baseTexture != nullptr; } + } // namespace openspace diff --git a/modules/newhorizons/rendering/renderableplanetprojection.h b/modules/newhorizons/rendering/renderableplanetprojection.h index 941664d9bb..404b0a452e 100644 --- a/modules/newhorizons/rendering/renderableplanetprojection.h +++ b/modules/newhorizons/rendering/renderableplanetprojection.h @@ -25,40 +25,25 @@ #ifndef __RENDERABLEPLANETPROJECTION_H__ #define __RENDERABLEPLANETPROJECTION_H__ -#include - -// open space includes #include +#include + #include -#include -#include -#include -#include - - #include #include #include -#include -#include - -// ghoul includes #include #include -#include - -#include namespace openspace { -namespace planetgeometry{ -class PlanetGeometry; +namespace planetgeometry { + class PlanetGeometry; } - -class RenderablePlanetProjection : public Renderable { +class RenderablePlanetProjection : public Renderable, private ProjectionComponent { public: RenderablePlanetProjection(const ghoul::Dictionary& dictionary); ~RenderablePlanetProjection(); @@ -67,105 +52,56 @@ public: bool deinitialize() override; bool isReady() const override; - void render(const RenderData& data) override; void update(const UpdateData& data) override; - ghoul::opengl::Texture* baseTexture() { return _texture.get(); }; + ghoul::opengl::Texture* baseTexture() { return _projectionTexture.get(); }; protected: - - void loadTexture(); - void loadProjectionTexture(); - bool auxiliaryRendertarget(); - glm::mat4 computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up); + bool loadTextures(); void attitudeParameters(double time); - void textureBind(); - void project(); - void clearAllProjections(); + private: - void imageProjectGPU(); + void imageProjectGPU(std::shared_ptr projectionTexture); - std::map _fileTranslation; - - properties::StringProperty _colorTexturePath; + properties::StringProperty _colorTexturePath; properties::StringProperty _heightMapTexturePath; - properties::StringProperty _normalMapTexturePath; - properties::StringProperty _projectionTexturePath; properties::IntProperty _rotation; - //properties::FloatProperty _fadeProjection; - properties::BoolProperty _performProjection; - properties::BoolProperty _clearAllProjections; std::unique_ptr _programObject; std::unique_ptr _fboProgramObject; - std::unique_ptr _texture; - std::unique_ptr _textureOriginal; - std::unique_ptr _textureProj; - std::unique_ptr _textureWhiteSquare; + std::unique_ptr _baseTexture; std::unique_ptr _heightMapTexture; - std::unique_ptr _normalMapTexture; properties::FloatProperty _heightExaggeration; - properties::BoolProperty _enableNormalMapping; + properties::FloatProperty _debugProjectionTextureRotation; - planetgeometry::PlanetGeometry* _geometry; + std::unique_ptr _geometry; - glm::vec2 _camScaling; - glm::vec3 _up; - glm::mat4 _transform; - glm::mat4 _projectorMatrix; - - //sequenceloading - std::string _sequenceSource; - std::string _sequenceType; - bool _foundSequence; - - // spice - std::string _instrumentID; - std::string _projectorID; - std::string _projecteeID; - SpiceManager::AberrationCorrection _aberration; - std::vector _potentialTargets; // @TODO copy-n-paste from renderablefov - - - float _fovy; - float _aspectRatio; - float _nearPlane; - float _farPlane; + glm::vec2 _camScaling; + glm::vec3 _up; + glm::mat4 _transform; + glm::mat4 _projectorMatrix; glm::dmat3 _stateMatrix; glm::dmat3 _instrumentMatrix; - glm::vec3 _boresight; + glm::vec3 _boresight; double _time; - double _previousTime; - double _previousCapture; - double lightTime; std::vector _imageTimes; - int _sequenceID; std::string _target; std::string _frame; - std::string _defaultProjImage; - std::string _clearingImage; - std::string _next; bool _capture; - // FBO stuff - GLuint _fboID; GLuint _quad; GLuint _vertexPositionBuffer; - bool _hasHeightMap; - bool _hasNormalMap; - - std::queue imageQueue; }; } // namespace openspace -#endif // __RENDERABLEPLANETPROJECTION_H__ \ No newline at end of file +#endif // __RENDERABLEPLANETPROJECTION_H__ diff --git a/modules/newhorizons/rendering/renderableshadowcylinder.cpp b/modules/newhorizons/rendering/renderableshadowcylinder.cpp index 21c85c2523..79ed65e57d 100644 --- a/modules/newhorizons/rendering/renderableshadowcylinder.cpp +++ b/modules/newhorizons/rendering/renderableshadowcylinder.cpp @@ -1,26 +1,26 @@ /***************************************************************************************** -* * -* 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. * -****************************************************************************************/ + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #include #include @@ -80,8 +80,7 @@ namespace openspace { ghoul_assert(success, ""); } -RenderableShadowCylinder::~RenderableShadowCylinder() { -} +RenderableShadowCylinder::~RenderableShadowCylinder() {} bool RenderableShadowCylinder::isReady() const { bool ready = true; @@ -103,6 +102,8 @@ bool RenderableShadowCylinder::initialize() { if (!_shader) return false; + + return completeSuccess; } diff --git a/modules/newhorizons/shaders/projectiveTexture_fs.glsl b/modules/newhorizons/shaders/projectiveTexture_fs.glsl deleted file mode 100644 index 8a5613a1dc..0000000000 --- a/modules/newhorizons/shaders/projectiveTexture_fs.glsl +++ /dev/null @@ -1,116 +0,0 @@ -/***************************************************************************************** - * * - * 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. * - ****************************************************************************************/ - -uniform vec4 campos; -uniform vec4 objpos; -//uniform vec3 camdir; // add this for specular - - -uniform float time; -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D heightTex; -uniform sampler2D normalTex; - -uniform bool _enableNormalMapping; - -in vec2 vs_st; -in vec4 vs_normal; -in vec4 vs_position; - -in vec4 ProjTexCoord; - -uniform vec3 boresight; -uniform vec3 sun_pos; - -#include "PowerScaling/powerScaling_fs.hglsl" -#include "fragment.glsl" - -Fragment getFragment() { - vec4 position = vs_position; - float depth = pscDepth(position); - vec4 diffuse = texture(texture1, vs_st); - // vec4 diffuse = texture(heightTex, vs_st); - - // directional lighting - vec3 origin = vec3(0.0); - vec4 spec = vec4(0.0); - - // vec3 n = normalize(texture(normalTex, vs_st).xyz); - - vec3 n = normalize(vs_normal.xyz); - // n = vec3(0); - // vec3 n = vec3(0); - - if (_enableNormalMapping) { - n = n + normalize(texture(normalTex, vs_st).xyz); - } - //vec3 e = normalize(camdir); - vec3 l_pos = sun_pos; // sun. - vec3 l_dir = normalize(l_pos-objpos.xyz); - float terminatorBright = 0.4; - float intensity = min(max(5*dot(n,l_dir), terminatorBright), 1); - - float shine = 0.0001; - - vec4 specular = vec4(0.1); - vec4 ambient = vec4(0.f,0.f,0.f,1); - /* Specular - if(intensity > 0.f){ - // halfway vector - vec3 h = normalize(l_dir + e); - // specular factor - float intSpec = max(dot(h,n),0.0); - spec = specular * pow(intSpec, shine); - } - */ - //diffuse = max(intensity * diffuse, ambient); - - // PROJECTIVE TEXTURE - vec4 projTexColor = textureProj(texture2, ProjTexCoord); - vec4 shaded = max(intensity * diffuse, ambient); - if (ProjTexCoord[0] > 0.0 || - ProjTexCoord[1] > 0.0 || - ProjTexCoord[0] < ProjTexCoord[2] || - ProjTexCoord[1] < ProjTexCoord[2]){ - diffuse = shaded; - } else if (dot(n,boresight) < 0 && - (projTexColor.w != 0)) {// frontfacing - diffuse = projTexColor;//*0.5f + 0.5f*shaded; - } else { - diffuse = shaded; - } - - Fragment frag; - frag.color = diffuse; -// frag.color = vec4(normalize(vs_position.xyz), 1.0); - - // frag.color = vec4(vec3(texture(heightTex, vs_st).r), 1.0); - // frag.color = texture(heightTex, vs_st); -// frag.color = vec4(n, 1.0); - // frag.color = test; - frag.depth = depth; - //frag.color = vec4(vs_st, 0.0, 1.0); - return frag; -} diff --git a/modules/newhorizons/shaders/projectionPass_fs.glsl b/modules/newhorizons/shaders/renderableModelProjection_fs.glsl similarity index 91% rename from modules/newhorizons/shaders/projectionPass_fs.glsl rename to modules/newhorizons/shaders/renderableModelProjection_fs.glsl index 383b4ca854..9b3c4975b7 100644 --- a/modules/newhorizons/shaders/projectionPass_fs.glsl +++ b/modules/newhorizons/shaders/renderableModelProjection_fs.glsl @@ -24,23 +24,20 @@ #version __CONTEXT__ -uniform sampler2D projectTexture; -uniform sampler2D currentTexture; - -uniform mat4 ProjectorMatrix; -uniform mat4 ModelTransform; -uniform vec2 _scaling; -uniform vec3 boresight; - +#include "PowerScaling/powerScaling_vs.hglsl" in vec4 vs_position; -in vec4 ProjTexCoord; -in vec2 vs_uv; in vec4 vs_normal; +in vec2 vs_uv; +in vec4 ProjTexCoord; out vec4 color; -#include "PowerScaling/powerScaling_vs.hglsl" +uniform sampler2D projectionTexture; + +uniform mat4 ModelTransform; +uniform vec2 _scaling; +uniform vec3 boresight; bool inRange(float x, float a, float b) { return (x >= a && x <= b); @@ -57,12 +54,9 @@ void main() { projected.y /= projected.w; //invert gl coordinates projected.x = 1 - projected.x; - // projected.y = 1 - projected.y; if((inRange(projected.x, 0, 1) && inRange(projected.y, 0, 1)) && (dot(n, boresight) < 0)) { - color = texture(projectTexture, projected.xy); - } else { - color = texture(currentTexture, uv); + color = texture(projectionTexture, projected.xy); + color.a = 1.0; } - -} \ No newline at end of file +} diff --git a/modules/newhorizons/shaders/projectionPass_vs.glsl b/modules/newhorizons/shaders/renderableModelProjection_vs.glsl similarity index 100% rename from modules/newhorizons/shaders/projectionPass_vs.glsl rename to modules/newhorizons/shaders/renderableModelProjection_vs.glsl index 0fed1ba6ee..583c841193 100644 --- a/modules/newhorizons/shaders/projectionPass_vs.glsl +++ b/modules/newhorizons/shaders/renderableModelProjection_vs.glsl @@ -24,22 +24,22 @@ #version __CONTEXT__ -uniform mat4 ProjectorMatrix; -uniform mat4 ModelTransform; -uniform vec2 _scaling; +#include "PowerScaling/powerScaling_vs.hglsl" layout(location = 0) in vec4 in_position; layout(location = 1) in vec2 in_st; layout(location = 2) in vec3 in_normal; -uniform vec3 boresight; - out vec4 vs_position; -out vec4 ProjTexCoord; -out vec2 vs_uv; out vec4 vs_normal; +out vec2 vs_uv; +out vec4 ProjTexCoord; -#include "PowerScaling/powerScaling_vs.hglsl" +uniform mat4 ProjectorMatrix; +uniform mat4 ModelTransform; +uniform vec2 _scaling; + +uniform vec3 boresight; void main() { vs_position = in_position; diff --git a/modules/newhorizons/shaders/modelShader_fs.glsl b/modules/newhorizons/shaders/renderableModel_fs.glsl similarity index 78% rename from modules/newhorizons/shaders/modelShader_fs.glsl rename to modules/newhorizons/shaders/renderableModel_fs.glsl index b0f338ffee..14fbe4ecd0 100644 --- a/modules/newhorizons/shaders/modelShader_fs.glsl +++ b/modules/newhorizons/shaders/renderableModel_fs.glsl @@ -22,30 +22,26 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +in vec4 vs_position; +in vec4 vs_normal; +in vec2 vs_st; + uniform vec4 campos; uniform vec4 objpos; uniform vec3 camdir; -uniform float time; -uniform sampler2D currentTexture; -uniform sampler2D projectedTexture; +uniform sampler2D baseTexture; +uniform sampler2D projectionTexture; uniform bool _performShading; - -in vec2 vs_st; -in vec4 vs_normal; -in vec4 vs_position; - -in vec4 ProjTexCoord; -uniform vec3 boresight; +uniform float _projectionFading; uniform vec3 sun_pos; -#include "PowerScaling/powerScaling_fs.hglsl" -#include "fragment.glsl" - Fragment getFragment() { vec4 position = vs_position; float depth = pscDepth(position); - vec4 diffuse = texture(currentTexture, vs_st); // directional lighting vec3 origin = vec3(0.0); @@ -58,34 +54,32 @@ Fragment getFragment() { float intensity = 1; if (_performShading) { - float terminatorBright = 0.4; - intensity = min(max(5*dot(n,l_dir), terminatorBright), 1); + const float terminatorBrightness = 0.4; + intensity = min(max(5*dot(n,l_dir), terminatorBrightness), 1.0); } float shine = 0.0001; vec4 specular = vec4(0.1); - vec4 ambient = vec4(0.f,0.f,0.f,1); + vec4 ambient = vec4(vec3(0.0), 1.0); //Specular - if (intensity > 0.f) { + if (intensity > 0.0) { vec3 h = normalize(l_dir + e); float intSpec = max(dot(h,n),0.0); spec = specular * pow(intSpec, shine); } - vec4 projTexColor = textureProj(projectedTexture, ProjTexCoord); - vec4 shaded = max(intensity * diffuse, ambient); - if (ProjTexCoord[0] > 0.0 || ProjTexCoord[1] > 0.0 || - ProjTexCoord[0] < ProjTexCoord[2] || - ProjTexCoord[1] < ProjTexCoord[2]) { - diffuse = shaded; - } else if (dot(n, boresight) < 0 && projTexColor.w != 0) {// frontfacing - diffuse = projTexColor; - } else { - diffuse = shaded; + vec4 textureColor = texture(baseTexture, vs_st); + vec4 projectionColor = texture(projectionTexture, vs_st); + if (projectionColor.a != 0.0) { + textureColor.rgb = mix( + textureColor.rgb, + projectionColor.rgb, + min(_projectionFading, projectionColor.a) + ); } Fragment frag; - frag.color = diffuse; + frag.color = max(intensity * textureColor, ambient); frag.depth = depth; return frag; } diff --git a/modules/newhorizons/shaders/modelShader_vs.glsl b/modules/newhorizons/shaders/renderableModel_vs.glsl similarity index 93% rename from modules/newhorizons/shaders/modelShader_vs.glsl rename to modules/newhorizons/shaders/renderableModel_vs.glsl index 74eacac727..3e5778d8a4 100644 --- a/modules/newhorizons/shaders/modelShader_vs.glsl +++ b/modules/newhorizons/shaders/renderableModel_vs.glsl @@ -24,26 +24,21 @@ #version __CONTEXT__ -uniform mat4 ViewProjection; -uniform mat4 ModelTransform; -uniform mat4 ProjectorMatrix; +#include "PowerScaling/powerScaling_vs.hglsl" layout(location = 0) in vec4 in_position; layout(location = 1) in vec2 in_st; layout(location = 2) in vec3 in_normal; -uniform vec3 boresight; +out vec4 vs_position; +out vec4 vs_normal; +out vec2 vs_st; + +uniform mat4 ViewProjection; +uniform mat4 ModelTransform; uniform float _magnification; -out vec2 vs_st; -out vec4 vs_normal; -out vec4 vs_position; -out float s; -out vec4 ProjTexCoord; - - -#include "PowerScaling/powerScaling_vs.hglsl" void main() { vec4 pos = in_position; pos.w += _magnification; @@ -56,8 +51,6 @@ void main() { vec4 position = pscTransform(tmp, ModelTransform); vs_position = tmp; - vec4 raw_pos = psc_to_meter(pos, scaling); - ProjTexCoord = ProjectorMatrix * ModelTransform * raw_pos; position = ViewProjection * position; gl_Position = z_normalization(position); } diff --git a/modules/newhorizons/shaders/fboPass_fs.glsl b/modules/newhorizons/shaders/renderablePlanetProjection_fs.glsl similarity index 80% rename from modules/newhorizons/shaders/fboPass_fs.glsl rename to modules/newhorizons/shaders/renderablePlanetProjection_fs.glsl index 8c2ba35b04..c9772d724a 100644 --- a/modules/newhorizons/shaders/fboPass_fs.glsl +++ b/modules/newhorizons/shaders/renderablePlanetProjection_fs.glsl @@ -24,22 +24,22 @@ #version __CONTEXT__ -uniform sampler2D texture1; -uniform sampler2D texture2; +#include "PowerScaling/powerScaling_vs.hglsl" + +in vec4 vs_position; +out vec4 color; + +uniform sampler2D projectionTexture; + uniform mat4 ProjectorMatrix; uniform mat4 ModelTransform; + uniform vec2 _scaling; uniform vec4 _radius; uniform int _segments; -uniform float projectionFading; - -in vec4 vs_position; - uniform vec3 boresight; -out vec4 color; - #define M_PI 3.14159265358979323846 vec4 uvToModel(vec2 uv, vec4 radius, float segments){ @@ -58,38 +58,31 @@ vec4 uvToModel(vec2 uv, vec4 radius, float segments){ return vec4(0.0); } -#include "PowerScaling/powerScaling_vs.hglsl" - bool inRange(float x, float a, float b){ return (x >= a && x <= b); } void main() { - vec2 uv = (vs_position.xy + vec2(1.0)) / vec2(2.0); - - vec4 vertex = uvToModel(uv, _radius, _segments); - - vec4 raw_pos = psc_to_meter(vertex, _scaling); - vec4 projected = ProjectorMatrix * ModelTransform * raw_pos; - - projected.x /= projected.w; - projected.y /= projected.w; - - vec3 normal = normalize((ModelTransform*vec4(vertex.xyz,0)).xyz); - - vec3 v_b = normalize(boresight); - - if((inRange(projected.x, 0, 1) && + vec2 uv = (vs_position.xy + vec2(1.0)) / vec2(2.0); + + vec4 vertex = uvToModel(uv, _radius, _segments); + + vec4 raw_pos = psc_to_meter(vertex, _scaling); + vec4 projected = ProjectorMatrix * ModelTransform * raw_pos; + + projected.x /= projected.w; + projected.y /= projected.w; + + vec3 normal = normalize((ModelTransform*vec4(vertex.xyz,0)).xyz); + + vec3 v_b = normalize(boresight); + + if((inRange(projected.x, 0, 1) && inRange(projected.y, 0, 1)) && dot(v_b, normal) < 0 ) - { + { // The 1-x is in this texture call because of flipped textures // to be fixed soon ---abock - color = texture(texture1, vec2(projected.x, 1-projected.y)); - }else{ - color = texture(texture2, uv); - color.a = projectionFading; - } - - // color.a = 0.1f;//1.f - abs(uv.x - 0.55) / (0.6 - 0.5); // blending + color = texture(projectionTexture, vec2(projected.x, 1-projected.y)); + } } \ No newline at end of file diff --git a/modules/newhorizons/shaders/fboPass_vs.glsl b/modules/newhorizons/shaders/renderablePlanetProjection_vs.glsl similarity index 94% rename from modules/newhorizons/shaders/fboPass_vs.glsl rename to modules/newhorizons/shaders/renderablePlanetProjection_vs.glsl index c75d6ac106..6db9f30f55 100644 --- a/modules/newhorizons/shaders/fboPass_vs.glsl +++ b/modules/newhorizons/shaders/renderablePlanetProjection_vs.glsl @@ -24,21 +24,13 @@ #version __CONTEXT__ -uniform mat4 ProjectorMatrix; -uniform mat4 ModelTransform; -uniform vec2 _scaling; +#include "PowerScaling/powerScaling_vs.hglsl" layout(location = 0) in vec4 in_position; -uniform vec3 boresight; -uniform vec2 radius; - out vec4 vs_position; -#include "PowerScaling/powerScaling_vs.hglsl" - void main() { vs_position = in_position; gl_Position = vec4(in_position.xy, 0.0, 1.0); - } diff --git a/modules/newhorizons/shaders/renderablePlanet_fs.glsl b/modules/newhorizons/shaders/renderablePlanet_fs.glsl new file mode 100644 index 0000000000..7b99e5c08c --- /dev/null +++ b/modules/newhorizons/shaders/renderablePlanet_fs.glsl @@ -0,0 +1,76 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +in vec4 vs_position; +in vec4 vs_normal; +in vec2 vs_st; + +uniform sampler2D baseTexture; +uniform sampler2D projectionTexture; + +uniform float _projectionFading; + +uniform vec4 objpos; +uniform vec3 sun_pos; + +Fragment getFragment() { + vec4 position = vs_position; + float depth = pscDepth(position); + + // directional lighting + vec3 origin = vec3(0.0); + vec4 spec = vec4(0.0); + + vec3 n = normalize(vs_normal.xyz); + + vec3 l_pos = sun_pos; // sun. + vec3 l_dir = normalize(l_pos-objpos.xyz); + float terminatorBrightness = 0.4; + float intensity = min(max(5*dot(n,l_dir), terminatorBrightness), 1); + + float shine = 0.0001; + + vec4 specular = vec4(0.1); + vec4 ambient = vec4(0.f,0.f,0.f,1); + + vec4 textureColor = texture(baseTexture, vs_st); + vec4 projectionColor = texture(projectionTexture, vs_st); + if (projectionColor.a != 0.0) { + textureColor.rgb = mix( + textureColor.rgb, + projectionColor.rgb, + min(_projectionFading, projectionColor.a) + ); + } + + + Fragment frag; + frag.color = max(intensity * textureColor, ambient); + frag.depth = depth; + + return frag; +} diff --git a/modules/newhorizons/shaders/projectiveTexture_vs.glsl b/modules/newhorizons/shaders/renderablePlanet_vs.glsl similarity index 86% rename from modules/newhorizons/shaders/projectiveTexture_vs.glsl rename to modules/newhorizons/shaders/renderablePlanet_vs.glsl index fbf40345e0..6e2812d655 100644 --- a/modules/newhorizons/shaders/projectiveTexture_vs.glsl +++ b/modules/newhorizons/shaders/renderablePlanet_vs.glsl @@ -27,37 +27,24 @@ #include "PowerScaling/powerScaling_vs.hglsl" layout(location = 0) in vec4 in_position; -//in vec3 in_position; layout(location = 1) in vec2 in_st; layout(location = 2) in vec3 in_normal; -uniform vec3 boresight; - -out vec2 vs_st; -out vec4 vs_normal; out vec4 vs_position; -out float s; -out vec4 ProjTexCoord; +out vec4 vs_normal; +out vec2 vs_st; -uniform mat4 ViewProjection; uniform mat4 ModelTransform; - -//texture projection matrix - +uniform mat4 ViewProjection; uniform mat4 ProjectorMatrix; uniform bool _hasHeightMap; uniform float _heightExaggeration; -uniform sampler2D heightTex; - +uniform sampler2D heightTexture; void main() { - // Radius = 0.71492 *10^8; - // set variables vs_st = in_st; - //vs_stp = in_position.xyz; - // vs_position = in_position; - vec4 tmp = in_position; + vec4 tmp = in_position; // this is wrong for the normal. // The normal transform is the transposed inverse of the model transform @@ -65,19 +52,15 @@ void main() { if (_hasHeightMap) { - float height = texture(heightTex, in_st).r; - // float height = 0.00005; + float height = texture(heightTexture, in_st).r; vec3 displacementDirection = (normalize(tmp.xyz)); - float displacementFactor = height * _heightExaggeration / 2500.0; + float displacementFactor = height * _heightExaggeration / 750.0; tmp.xyz = tmp.xyz + displacementDirection * displacementFactor; } vec4 position = pscTransform(tmp, ModelTransform); vs_position = tmp; - vec4 raw_pos = psc_to_meter(tmp, scaling); - ProjTexCoord = ProjectorMatrix * ModelTransform * raw_pos; - position = ViewProjection * position; gl_Position = z_normalization(position); diff --git a/modules/newhorizons/util/hongkangparser.cpp b/modules/newhorizons/util/hongkangparser.cpp index ca32d28388..e41446d449 100644 --- a/modules/newhorizons/util/hongkangparser.cpp +++ b/modules/newhorizons/util/hongkangparser.cpp @@ -313,6 +313,7 @@ void HongKangParser::createImage(Image& image, double startTime, double stopTime } image.target = targ; image.projected = false; + image.isPlaceholder = true; } double HongKangParser::getETfromMet(std::string line){ diff --git a/modules/newhorizons/util/imagesequencer.cpp b/modules/newhorizons/util/imagesequencer.cpp index 57ba88d127..95843925e5 100644 --- a/modules/newhorizons/util/imagesequencer.cpp +++ b/modules/newhorizons/util/imagesequencer.cpp @@ -22,7 +22,6 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -// open space includes #include #include #include @@ -164,8 +163,7 @@ const Image ImageSequencer::getLatestImageForInstrument(const std::string _instr if (it != _latestImages.end()) return _latestImages[_instrumentID]; else { - Image dummyImage = { 0, 0, "", std::vector(), "", false }; - return dummyImage; + return Image(); } } @@ -193,15 +191,16 @@ std::map ImageSequencer::getActiveInstruments(){ // return entire map, seen in GUI. return _switchingMap; } -bool ImageSequencer::instrumentActive(std::string instrumentID){ - for (auto i : _instrumentTimes){ + +bool ImageSequencer::instrumentActive(std::string instrumentID) { + for (const auto& i : _instrumentTimes) { //check if this instrument is in range - if (i.second.inRange(_currentTime)){ + if (i.second.inRange(_currentTime)) { //if so, then get the corresponding spiceID std::vector spiceIDs = _fileTranslation[i.first]->getTranslation(); //check which specific subinstrument is firing - for (auto s : spiceIDs){ - if (s == instrumentID){ + for (auto s : spiceIDs) { + if (s == instrumentID) { return true; } } @@ -211,7 +210,7 @@ bool ImageSequencer::instrumentActive(std::string instrumentID){ } float ImageSequencer::instrumentActiveTime(const std::string& instrumentID) const { - for (auto i : _instrumentTimes){ + for (const auto& i : _instrumentTimes){ //check if this instrument is in range if (i.second.inRange(_currentTime)){ //if so, then get the corresponding spiceID @@ -262,7 +261,8 @@ bool ImageSequencer::getImagePaths(std::vector& captures, if (curr->startTime >= prev->startTime){ std::copy_if(prev, curr, back_inserter(captureTimes), [instrumentRequest](const Image& i) { - return i.activeInstruments[0] == instrumentRequest; + bool correctInstrument = i.activeInstruments[0] == instrumentRequest; + return correctInstrument; }); //std::reverse(captureTimes.begin(), captureTimes.end()); @@ -270,13 +270,41 @@ bool ImageSequencer::getImagePaths(std::vector& captures, if (!captures.empty()) _latestImages[captures.back().activeInstruments.front()] = captures.back(); + std::vector toDelete; + for (auto it = captures.begin(); it != captures.end(); ++it) { + if (it->isPlaceholder) { + double beforeDist = std::numeric_limits::max(); + if (it != captures.begin()) { + auto before = std::prev(it); + beforeDist = abs(before->startTime - it->startTime); + } + + double nextDist = std::numeric_limits::max(); + if (it != captures.end() - 1) { + auto next = std::next(it); + nextDist = abs(next->startTime - it->startTime); + } + + if (beforeDist < 1.0 || nextDist < 1.0) { + toDelete.push_back(std::distance(captures.begin(), it)); + } + } + } + + for (size_t i = 0; i < toDelete.size(); ++i) { + // We have to subtract i here as we already have deleted i value + // before this and we need to adjust the location + int v = toDelete[i] - i; + captures.erase(captures.begin() + v); + } + return true; } } } return false; } -void ImageSequencer::sortData(){ +void ImageSequencer::sortData() { auto targetComparer = [](const std::pair &a, const std::pair &b)->bool{ return a.first < b.first; @@ -292,6 +320,14 @@ void ImageSequencer::sortData(){ std::sort(_subsetMap[sub.first]._subset.begin(), _subsetMap[sub.first]._subset.end(), imageComparer); } + + std::sort( + _instrumentTimes.begin(), + _instrumentTimes.end(), + [](const std::pair& a, const std::pair& b) { + return a.second._min < b.second._min; + } + ); } void ImageSequencer::runSequenceParser(SequenceParser* parser){ diff --git a/modules/newhorizons/util/projectioncomponent.cpp b/modules/newhorizons/util/projectioncomponent.cpp new file mode 100644 index 0000000000..6f9004afa3 --- /dev/null +++ b/modules/newhorizons/util/projectioncomponent.cpp @@ -0,0 +1,346 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace { + const std::string keyPotentialTargets = "PotentialTargets"; + + const std::string keyInstrument = "Instrument.Name"; + const std::string keyInstrumentFovy = "Instrument.Fovy"; + const std::string keyInstrumentAspect = "Instrument.Aspect"; + const std::string keyInstrumentNear = "Instrument.Near"; + const std::string keyInstrumentFar = "Instrument.Far"; + + const std::string keyProjObserver = "Projection.Observer"; + const std::string keyProjTarget = "Projection.Target"; + const std::string keyProjAberration = "Projection.Aberration"; + + const std::string keySequenceDir = "Projection.Sequence"; + const std::string keySequenceType = "Projection.SequenceType"; + const std::string keyTranslation = "DataInputTranslation"; + + const std::string sequenceTypeImage = "image-sequence"; + const std::string sequenceTypePlaybook = "playbook"; + const std::string sequenceTypeHybrid = "hybrid"; + + const std::string placeholderFile = + "${OPENSPACE_DATA}/scene/common/textures/placeholder.png"; + + const std::string _loggerCat = "ProjectionComponent"; +} + +namespace openspace { + +using ghoul::Dictionary; + +ProjectionComponent::ProjectionComponent() + : _performProjection("performProjection", "Perform Projections", true) + , _clearAllProjections("clearAllProjections", "Clear Projections", false) + , _projectionFading("projectionFading", "Projection Fading", 1.f, 0.f, 1.f) + , _projectionTexture(nullptr) +{} + +bool ProjectionComponent::initialize() { + bool a = generateProjectionLayerTexture(); + bool b = auxiliaryRendertarget(); + + using std::unique_ptr; + using ghoul::opengl::Texture; + using ghoul::io::TextureReader; + + unique_ptr texture = TextureReader::ref().loadTexture(absPath(placeholderFile)); + if (texture) { + texture->uploadTexture(); + // TODO: AnisotropicMipMap crashes on ATI cards ---abock + //_textureProj->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + texture->setFilter(Texture::FilterMode::Linear); + texture->setWrapping(Texture::WrappingMode::ClampToBorder); + } + _placeholderTexture = std::move(texture); + + return a && b; +} + +bool ProjectionComponent::deinitialize() { + _projectionTexture = nullptr; + + glDeleteFramebuffers(1, &_fboID); + + return true; +} + +bool ProjectionComponent::initializeProjectionSettings(const Dictionary& dictionary) { + bool completeSuccess = true; + completeSuccess &= dictionary.getValue(keyInstrument, _instrumentID); + completeSuccess &= dictionary.getValue(keyProjObserver, _projectorID); + completeSuccess &= dictionary.getValue(keyProjTarget, _projecteeID); + completeSuccess &= dictionary.getValue(keyInstrumentFovy, _fovy); + completeSuccess &= dictionary.getValue(keyInstrumentAspect, _aspectRatio); + completeSuccess &= dictionary.getValue(keyInstrumentNear, _nearPlane); + completeSuccess &= dictionary.getValue(keyInstrumentFar, _farPlane); + ghoul_assert(completeSuccess, "All neccessary attributes not found in modfile"); + + std::string a = "NONE"; + bool s = dictionary.getValue(keyProjAberration, a); + _aberration = SpiceManager::AberrationCorrection(a); + completeSuccess &= s; + ghoul_assert(completeSuccess, "All neccessary attributes not found in modfile"); + + + if (dictionary.hasKeyAndValue(keyPotentialTargets)) { + ghoul::Dictionary potentialTargets = dictionary.value( + keyPotentialTargets + ); + + _potentialTargets.resize(potentialTargets.size()); + for (int i = 0; i < potentialTargets.size(); ++i) { + std::string target; + potentialTargets.getValue(std::to_string(i + 1), target); + _potentialTargets[i] = target; + } + } + return completeSuccess; +} + +bool ProjectionComponent::initializeParser(const ghoul::Dictionary& dictionary) { + bool completeSuccess = true; + + std::string name; + dictionary.getValue(SceneGraphNode::KeyName, name); + + SequenceParser* parser; + + std::string sequenceSource; + std::string sequenceType; + bool foundSequence = dictionary.getValue(keySequenceDir, sequenceSource); + if (foundSequence) { + sequenceSource = absPath(sequenceSource); + + foundSequence = dictionary.getValue(keySequenceType, sequenceType); + //Important: client must define translation-list in mod file IFF playbook + if (dictionary.hasKey(keyTranslation)) { + ghoul::Dictionary translationDictionary; + //get translation dictionary + dictionary.getValue(keyTranslation, translationDictionary); + + if (sequenceType == sequenceTypePlaybook) { + parser = new HongKangParser(name, + sequenceSource, + _projectorID, + translationDictionary, + _potentialTargets); + openspace::ImageSequencer::ref().runSequenceParser(parser); + } + else if (sequenceType == sequenceTypeImage) { + parser = new LabelParser(name, + sequenceSource, + translationDictionary); + openspace::ImageSequencer::ref().runSequenceParser(parser); + } + else if (sequenceType == sequenceTypeHybrid) { + //first read labels + parser = new LabelParser(name, + sequenceSource, + translationDictionary); + openspace::ImageSequencer::ref().runSequenceParser(parser); + + std::string _eventFile; + bool foundEventFile = dictionary.getValue("Projection.EventFile", _eventFile); + if (foundEventFile) { + //then read playbook + _eventFile = absPath(_eventFile); + parser = new HongKangParser(name, + _eventFile, + _projectorID, + translationDictionary, + _potentialTargets); + openspace::ImageSequencer::ref().runSequenceParser(parser); + } + else { + LWARNING("No eventfile has been provided, please check modfiles"); + } + } + } + else { + LWARNING("No playbook translation provided, please make sure all spice calls match playbook!"); + } + } + + return completeSuccess; +} + +void ProjectionComponent::imageProjectBegin() { + // keep handle to the current bound FBO + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO); + + glGetIntegerv(GL_VIEWPORT, _viewport); + glBindFramebuffer(GL_FRAMEBUFFER, _fboID); + + glViewport( + 0, 0, + static_cast(_projectionTexture->width()), + static_cast(_projectionTexture->height()) + ); +} + +void ProjectionComponent::imageProjectEnd() { + glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); + glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]); +} + +bool ProjectionComponent::auxiliaryRendertarget() { + bool completeSuccess = true; + + GLint defaultFBO; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + + // setup FBO + glGenFramebuffers(1, &_fboID); + glBindFramebuffer(GL_FRAMEBUFFER, _fboID); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + *_projectionTexture, + 0 + ); + // check FBO status + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + completeSuccess &= false; + // switch back to window-system-provided framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + + return completeSuccess; +} + +glm::mat4 ProjectionComponent::computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, + const glm::vec3 up, + const glm::dmat3& instrumentMatrix, + float fieldOfViewY, + float aspectRatio, + float nearPlane, float farPlane, + glm::vec3& boreSight) +{ + //rotate boresight into correct alignment + boreSight = instrumentMatrix*aim; + glm::vec3 uptmp(instrumentMatrix*glm::dvec3(up)); + + // create view matrix + glm::vec3 e3 = glm::normalize(boreSight); + glm::vec3 e1 = glm::normalize(glm::cross(uptmp, e3)); + glm::vec3 e2 = glm::normalize(glm::cross(e3, e1)); + glm::mat4 projViewMatrix = glm::mat4(e1.x, e2.x, e3.x, 0.f, + e1.y, e2.y, e3.y, 0.f, + e1.z, e2.z, e3.z, 0.f, + -glm::dot(e1, loc), -glm::dot(e2, loc), -glm::dot(e3, loc), 1.f); + // create perspective projection matrix + glm::mat4 projProjectionMatrix = glm::perspective(glm::radians(fieldOfViewY), aspectRatio, nearPlane, farPlane); + // bias matrix + glm::mat4 projNormalizationMatrix = glm::mat4(0.5f, 0, 0, 0, + 0, 0.5f, 0, 0, + 0, 0, 0.5f, 0, + 0.5f, 0.5f, 0.5f, 1); + return projNormalizationMatrix*projProjectionMatrix*projViewMatrix; +} + +void ProjectionComponent::clearAllProjections() { + // keep handle to the current bound FBO + GLint defaultFBO; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + + GLint m_viewport[4]; + glGetIntegerv(GL_VIEWPORT, m_viewport); + //counter = 0; + glBindFramebuffer(GL_FRAMEBUFFER, _fboID); + + glViewport(0, 0, static_cast(_projectionTexture->width()), static_cast(_projectionTexture->height())); + + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + + //bind back to default + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + glViewport(m_viewport[0], m_viewport[1], + m_viewport[2], m_viewport[3]); + + _clearAllProjections = false; +} + +std::shared_ptr ProjectionComponent::loadProjectionTexture( + const std::string& texturePath, + bool isPlaceholder) +{ + using std::unique_ptr; + using ghoul::opengl::Texture; + using ghoul::io::TextureReader; + + + if (isPlaceholder) + return _placeholderTexture; + + + unique_ptr texture = TextureReader::ref().loadTexture(absPath(texturePath)); + if (texture) { + if (texture->format() == Texture::Format::Red) + ghoul::opengl::convertTextureFormat(ghoul::opengl::Texture::Format::RGB, *texture); + texture->uploadTexture(); + // TODO: AnisotropicMipMap crashes on ATI cards ---abock + //_textureProj->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + texture->setFilter(Texture::FilterMode::Linear); + texture->setWrapping(Texture::WrappingMode::ClampToBorder); + } + return std::move(texture); +} + +bool ProjectionComponent::generateProjectionLayerTexture() { + int maxSize = OpenGLCap.max2DTextureSize() / 2; + + LINFO( + "Creating projection texture of size '" << maxSize << ", " << maxSize / 2 << "'" + ); + _projectionTexture = std::make_unique ( + glm::uvec3(maxSize, maxSize / 2, 1), + ghoul::opengl::Texture::Format::RGBA + ); + if (_projectionTexture) + _projectionTexture->uploadTexture(); + + return _projectionTexture != nullptr; + +} + +} // namespace openspace diff --git a/modules/newhorizons/util/projectioncomponent.h b/modules/newhorizons/util/projectioncomponent.h new file mode 100644 index 0000000000..88ec3c5ce6 --- /dev/null +++ b/modules/newhorizons/util/projectioncomponent.h @@ -0,0 +1,98 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __PROJECTIONCOMPONENT_H__ +#define __PROJECTIONCOMPONENT_H__ + +#include +#include + +#include +#include + +namespace openspace { + +class ProjectionComponent { +public: + ProjectionComponent(); + +protected: + bool initialize(); + bool deinitialize(); + + bool initializeProjectionSettings(const ghoul::Dictionary& dictionary); + bool initializeParser(const ghoul::Dictionary& dictionary); + + void imageProjectBegin(); + void imageProjectEnd(); + + bool generateProjectionLayerTexture(); + bool auxiliaryRendertarget(); + + std::shared_ptr loadProjectionTexture( + const std::string& texturePath, + bool isPlaceholder = false + ); + + glm::mat4 computeProjectorMatrix( + const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up, + const glm::dmat3& instrumentMatrix, + float fieldOfViewY, + float aspectRatio, + float nearPlane, + float farPlane, + glm::vec3& boreSight + ); + + void clearAllProjections(); + + + properties::BoolProperty _performProjection; + properties::BoolProperty _clearAllProjections; + properties::FloatProperty _projectionFading; + + std::unique_ptr _projectionTexture; + + std::shared_ptr _placeholderTexture; + + std::string _instrumentID; + std::string _projectorID; + std::string _projecteeID; + SpiceManager::AberrationCorrection _aberration; + std::vector _potentialTargets; + float _fovy; + float _aspectRatio; + float _nearPlane; + float _farPlane; + + + GLuint _fboID; + + GLint _defaultFBO; + GLint _viewport[4]; +}; + +} // namespace openspace + +#endif // __PROJECTIONCOMPONENT_H__ diff --git a/modules/newhorizons/util/sequenceparser.h b/modules/newhorizons/util/sequenceparser.h index 9bb1606393..7bf232608e 100644 --- a/modules/newhorizons/util/sequenceparser.h +++ b/modules/newhorizons/util/sequenceparser.h @@ -36,12 +36,13 @@ namespace openspace { class Decoder; struct Image { - double startTime; - double stopTime; + double startTime = 0.0; + double stopTime = 0.0; std::string path; std::vector activeInstruments; std::string target; - bool projected; + bool isPlaceholder = false; + bool projected = false; }; struct TimeRange { @@ -53,7 +54,7 @@ struct TimeRange { bool inRange(double min, double max){ return (min >= _min && max <= _max); } - bool inRange(double val){ + bool inRange(double val) const { return (val >= _min && val <= _max); } double _min; diff --git a/modules/onscreengui/include/gui.h b/modules/onscreengui/include/gui.h index 10b3f4452d..7bd37b0f85 100644 --- a/modules/onscreengui/include/gui.h +++ b/modules/onscreengui/include/gui.h @@ -60,7 +60,7 @@ public: // bool keyCallback(int key, int action); bool charCallback(unsigned int character, KeyModifier modifier); - void startFrame(float deltaTime, const glm::vec2& windowSize, const glm::vec2& mousePos, uint32_t mouseButtons); + void startFrame(float deltaTime, const glm::vec2& windowSize, const glm::vec2& mousePosCorrectionFactor, const glm::vec2& mousePos, uint32_t mouseButtons); void endFrame(); void renderMainWindow(); diff --git a/modules/onscreengui/include/guiperformancecomponent.h b/modules/onscreengui/include/guiperformancecomponent.h index e2f31f9f45..882c277fe4 100644 --- a/modules/onscreengui/include/guiperformancecomponent.h +++ b/modules/onscreengui/include/guiperformancecomponent.h @@ -43,7 +43,10 @@ public: protected: ghoul::SharedMemory* _performanceMemory = nullptr; - float _minMaxValues[2]; + int _sortingSelection; + + bool _sceneGraphIsEnabled; + bool _functionsIsEnabled; }; } // namespace gui diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index a954288048..4353468086 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -273,6 +273,7 @@ void GUI::deinitializeGL() { } void GUI::startFrame(float deltaTime, const glm::vec2& windowSize, + const glm::vec2& mousePosCorrectionFactor, const glm::vec2& mousePos, uint32_t mouseButtonsPressed) { @@ -280,11 +281,14 @@ void GUI::startFrame(float deltaTime, const glm::vec2& windowSize, ImGuiIO& io = ImGui::GetIO(); io.DisplaySize = ImVec2(windowSize.x, windowSize.y); io.DeltaTime = deltaTime; -#ifdef __APPLE__ - io.MousePos = ImVec2(mousePos.x * 2, mousePos.y * 2); -#else - io.MousePos = ImVec2(mousePos.x, mousePos.y); -#endif + + io.MousePos = ImVec2(mousePos.x * mousePosCorrectionFactor.x, mousePos.y * mousePosCorrectionFactor.y); + +//#ifdef __APPLE__ +// io.MousePos = ImVec2(mousePos.x * 2, mousePos.y * 2); +//#else +// io.MousePos = ImVec2(mousePos.x, mousePos.y); +//#endif io.MouseDown[0] = mouseButtonsPressed & (1 << 0); io.MouseDown[1] = mouseButtonsPressed & (1 << 1); diff --git a/modules/onscreengui/src/guiiswacomponent.cpp b/modules/onscreengui/src/guiiswacomponent.cpp index eac62a75bf..e5fd4c33fb 100644 --- a/modules/onscreengui/src/guiiswacomponent.cpp +++ b/modules/onscreengui/src/guiiswacomponent.cpp @@ -116,6 +116,7 @@ void GuiIswaComponent::render() { } } +#ifdef OPENSPACE_MODULE_ISWA_ENABLED if(ImGui::CollapsingHeader("Cdf files")){ auto cdfInfo = IswaManager::ref().cdfInformation(); @@ -151,6 +152,7 @@ void GuiIswaComponent::render() { } } } +#endif for (const auto& p : _propertiesByOwner) { if (ImGui::CollapsingHeader(p.first.c_str())) { @@ -209,6 +211,7 @@ void GuiIswaComponent::render() { } +#ifdef OPENSPACE_MODULE_ISWA_ENABLED if (ImGui::CollapsingHeader("iSWA screen space cygntes")) { auto map = IswaManager::ref().cygnetInformation(); @@ -237,7 +240,8 @@ void GuiIswaComponent::render() { } } - +#endif + ImGui::End(); } diff --git a/modules/onscreengui/src/guiperformancecomponent.cpp b/modules/onscreengui/src/guiperformancecomponent.cpp index e12c639288..0bd4511ab3 100644 --- a/modules/onscreengui/src/guiperformancecomponent.cpp +++ b/modules/onscreengui/src/guiperformancecomponent.cpp @@ -25,10 +25,17 @@ #include #include +#include +#include #include + #include + #include +#include + #include +#include namespace { const std::string _loggerCat = "GuiPerformanceComponent"; @@ -38,8 +45,10 @@ namespace openspace { namespace gui { void GuiPerformanceComponent::initialize() { - _minMaxValues[0] = 100.f; - _minMaxValues[1] = 250.f; + _sortingSelection = -1; + + _sceneGraphIsEnabled = false; + _functionsIsEnabled = false; } void GuiPerformanceComponent::deinitialize() { @@ -48,61 +57,208 @@ void GuiPerformanceComponent::deinitialize() { } void GuiPerformanceComponent::render() { - // Copy and paste from renderengine.cpp::storePerformanceMeasurements method -// const int8_t Version = 0; - const int nValues = 250; - const int lengthName = 256; - const int maxValues = 256; - - struct PerformanceLayout { - int8_t version; - int32_t nValuesPerEntry; - int32_t nEntries; - int32_t maxNameLength; - int32_t maxEntries; - - struct PerformanceLayoutEntry { - char name[lengthName]; - float renderTime[nValues]; - float updateRenderable[nValues]; - float updateEphemeris[nValues]; - - int32_t currentRenderTime; - int32_t currentUpdateRenderable; - int32_t currentUpdateEphemeris; - }; - - PerformanceLayoutEntry entries[maxValues]; - }; + using namespace performance; ImGui::Begin("Performance", &_isEnabled); if (OsEng.renderEngine().doesPerformanceMeasurements() && - ghoul::SharedMemory::exists(RenderEngine::PerformanceMeasurementSharedData)) + ghoul::SharedMemory::exists(PerformanceManager::PerformanceMeasurementSharedData)) { - ImGui::SliderFloat2("Min values, max Value", _minMaxValues, 0.f, 10000.f); - _minMaxValues[1] = fmaxf(_minMaxValues[0], _minMaxValues[1]); + ImGui::Checkbox("SceneGraph", &_sceneGraphIsEnabled); + ImGui::Checkbox("Functions", &_functionsIsEnabled); + ImGui::Spacing(); + + if (ImGui::Button("Reset measurements")) { + OsEng.renderEngine().performanceManager()->resetPerformanceMeasurements(); + } + + if (_sceneGraphIsEnabled) { + ImGui::Begin("SceneGraph", &_sceneGraphIsEnabled); + + // The indices correspond to the index into the average array further below + ImGui::Text("Sorting"); + ImGui::RadioButton("No Sorting", &_sortingSelection, -1); + ImGui::RadioButton("UpdateEphemeris", &_sortingSelection, 0); + ImGui::RadioButton("UpdateRender", &_sortingSelection, 1); + ImGui::RadioButton("RenderTime", &_sortingSelection, 2); - if (!_performanceMemory) - _performanceMemory = new ghoul::SharedMemory(RenderEngine::PerformanceMeasurementSharedData); + if (!_performanceMemory) + _performanceMemory = new ghoul::SharedMemory(PerformanceManager::PerformanceMeasurementSharedData); + void* ptr = _performanceMemory->memory(); - void* ptr = _performanceMemory->memory(); - PerformanceLayout* layout = reinterpret_cast(ptr); + PerformanceLayout* layout = reinterpret_cast(ptr); - for (int i = 0; i < layout->nEntries; ++i) { - const PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; + std::vector indices(layout->nScaleGraphEntries); + std::iota(indices.begin(), indices.end(), 0); - if (ImGui::CollapsingHeader(entry.name)) { - std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[entry.currentUpdateEphemeris - 1]) + "us"; - ImGui::PlotLines("UpdateEphemeris", &entry.updateEphemeris[0], layout->nValuesPerEntry, 0, updateEphemerisTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); + // Ordering: + // updateEphemeris + // UpdateRender + // RenderTime + std::vector> averages(layout->nScaleGraphEntries, { 0.f, 0.f, 0.f }); + + std::vector, 3>> minMax( + layout->nScaleGraphEntries + ); + + for (int i = 0; i < layout->nScaleGraphEntries; ++i) { + const PerformanceLayout::SceneGraphPerformanceLayout& entry = layout->sceneGraphEntries[i]; - std::string updateRenderableTime = std::to_string(entry.updateRenderable[entry.currentUpdateRenderable - 1]) + "us"; - ImGui::PlotLines("UpdateRender", &entry.updateRenderable[0], layout->nValuesPerEntry, 0, updateRenderableTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); + int v[3] = { 0, 0, 0 }; + + for (int j = 0; j < PerformanceLayout::NumberValues; ++j) { + averages[i][0] += entry.updateEphemeris[j]; + if (entry.updateEphemeris[j] != 0.f) + ++(v[0]); + averages[i][1] += entry.updateRenderable[j]; + if (entry.updateRenderable[j] != 0.f) + ++(v[1]); + averages[i][2] += entry.renderTime[j]; + if (entry.renderTime[j] != 0.f) + ++(v[2]); + } + + if (v[0] != 0) + averages[i][0] /= static_cast(v[0]); + if (v[1] != 0) + averages[i][1] /= static_cast(v[1]); + if (v[2] != 0) + averages[i][2] /= static_cast(v[2]); + + auto minmaxEphemeris = std::minmax_element( + std::begin(entry.updateEphemeris), + std::end(entry.updateEphemeris) + ); + minMax[i][0] = std::make_pair( + *(minmaxEphemeris.first), + *(minmaxEphemeris.second) + ); + + + auto minmaxUpdateRenderable = std::minmax_element( + std::begin(entry.updateRenderable), + std::end(entry.updateRenderable) + ); + minMax[i][1] = std::make_pair( + *(minmaxUpdateRenderable.first), + *(minmaxUpdateRenderable.second) + ); + + + auto minmaxRendering = std::minmax_element( + std::begin(entry.renderTime), + std::end(entry.renderTime) + ); + minMax[i][2] = std::make_pair( + *(minmaxRendering.first), + *(minmaxRendering.second) + ); + - std::string renderTime = std::to_string(entry.renderTime[entry.currentRenderTime - 1]) + "us"; - ImGui::PlotLines("RenderTime", &entry.renderTime[0], layout->nValuesPerEntry, 0, renderTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); } + + if (_sortingSelection != -1) { + int sortIndex = _sortingSelection; + + std::sort( + indices.begin(), + indices.end(), + [sortIndex, &averages](size_t a, size_t b) { + return averages[a][sortIndex] > averages[b][sortIndex]; + } + ); + + } + + for (int i = 0; i < layout->nScaleGraphEntries; ++i) { + const PerformanceLayout::SceneGraphPerformanceLayout& entry = layout->sceneGraphEntries[indices[i]]; + + if (ImGui::CollapsingHeader(entry.name)) { + std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[PerformanceLayout::NumberValues - 1]) + "us"; + ; + ImGui::PlotLines( + fmt::format("UpdateEphemeris\nAverage: {}us", averages[indices[i]][0]).c_str(), + &entry.updateEphemeris[0], + PerformanceLayout::NumberValues, + 0, + updateEphemerisTime.c_str(), + minMax[indices[i]][0].first, + minMax[indices[i]][0].second, + ImVec2(0, 40) + ); + + std::string updateRenderableTime = std::to_string(entry.updateRenderable[PerformanceLayout::NumberValues - 1]) + "us"; + ImGui::PlotLines( + fmt::format("UpdateRender\nAverage: {}us", averages[indices[i]][1]).c_str(), + &entry.updateRenderable[0], + PerformanceLayout::NumberValues, + 0, + updateRenderableTime.c_str(), + minMax[indices[i]][1].first, + minMax[indices[i]][1].second, + ImVec2(0, 40) + ); + + std::string renderTime = std::to_string(entry.renderTime[PerformanceLayout::NumberValues - 1]) + "us"; + ImGui::PlotLines( + fmt::format("RenderTime\nAverage: {}us", averages[indices[i]][2]).c_str(), + &entry.renderTime[0], + PerformanceLayout::NumberValues, + 0, + renderTime.c_str(), + minMax[indices[i]][2].first, + minMax[indices[i]][2].second, + ImVec2(0, 40) + ); + } + } + ImGui::End(); + } + + if (_functionsIsEnabled) { + ImGui::Begin("Functions", &_functionsIsEnabled); + using namespace performance; + + if (!_performanceMemory) + _performanceMemory = new ghoul::SharedMemory(PerformanceManager::PerformanceMeasurementSharedData); + + void* ptr = _performanceMemory->memory(); + + PerformanceLayout* layout = reinterpret_cast(ptr); + + for (int i = 0; i < layout->nFunctionEntries; ++i) { + const PerformanceLayout::FunctionPerformanceLayout& entry = layout->functionEntries[i]; + + float avg = 0.f; + int count = 0; + for (int j = 0; j < PerformanceLayout::NumberValues; ++j) { + avg += layout->functionEntries[i].time[j]; + if (layout->functionEntries[i].time[j] != 0.f) + ++count; + } + avg /= count; + + auto minmax = std::minmax_element( + std::begin(layout->functionEntries[i].time), + std::end(layout->functionEntries[i].time) + ); + + const PerformanceLayout::FunctionPerformanceLayout& f = layout->functionEntries[i]; + + std::string renderTime = std::to_string(entry.time[PerformanceLayout::NumberValues - 1]) + "us"; + ImGui::PlotLines( + fmt::format("{}\nAverage: {}us", entry.name, avg).c_str(), + &entry.time[0], + PerformanceLayout::NumberValues, + 0, + renderTime.c_str(), + *(minmax.first), + *(minmax.second), + ImVec2(0, 40) + ); + } + ImGui::End(); } } else { @@ -113,6 +269,5 @@ void GuiPerformanceComponent::render() { ImGui::End(); } - } // namespace gui } // namespace openspace diff --git a/scripts/bind_keys.lua b/scripts/bind_keys.lua index f8496274ef..be68aeff20 100644 --- a/scripts/bind_keys.lua +++ b/scripts/bind_keys.lua @@ -1,107 +1,18 @@ --[[ OpenSpace keybinding script ]]-- --- This script sets the default keybindings and is executed at startup + +-- Load the common helper functions +dofile(openspace.absPath('${SCRIPTS}/common.lua')) openspace.clearKeys() -openspace.bindKey("F1", "openspace.gui.toggle()") -openspace.bindKey("F2", "openspace.setPerformanceMeasurement(true)") -openspace.bindKey("F3", "openspace.setPerformanceMeasurement(false)") -openspace.bindKey("F5", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun'); openspace.printInfo('Changing Viewpoint to Sun-in-center');"); -openspace.bindKey("F6", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Jupiter'); openspace.printInfo('Changing Viewpoint to Jupiter-in-center');"); -openspace.bindKey("F7", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto'); openspace.printInfo('Changing Viewpoint to Pluto-in-center');"); +helper.setCommonKeys() +helper.setDeltaTimeKeys({ + 1, 5, 10, 20, 40, 60, 120, 360, 720, 1440, + 2880, 5760, 11520, 23040, 46080, 92160, 184320, 368640, 737280, 1474560, + 2949120, 5898240, 11796480, 23592960, 47185920, 94371840, 188743680, 377487360 +}) -openspace.bindKey("PRINT_SCREEN", "openspace.takeScreenshot()") - -openspace.bindKey("SPACE", "openspace.time.togglePause()") - --- Bookmarks for the New Horizons encounter -openspace.bindKey("1", "openspace.time.setDeltaTime(1)") -openspace.bindKey("2", "openspace.time.setDeltaTime(5)") -openspace.bindKey("3", "openspace.time.setDeltaTime(10)") -openspace.bindKey("4", "openspace.time.setDeltaTime(20)") -openspace.bindKey("5", "openspace.time.setDeltaTime(40)") -openspace.bindKey("6", "openspace.time.setDeltaTime(60)") -openspace.bindKey("7", "openspace.time.setDeltaTime(120)") -openspace.bindKey("8", "openspace.time.setDeltaTime(360)") -openspace.bindKey("9", "openspace.time.setDeltaTime(540)") -openspace.bindKey("0", "openspace.time.setDeltaTime(1200)") - ---[[openspace.bindKey("2", "openspace.time.setDeltaTime(30)") -openspace.bindKey("3", "openspace.time.setDeltaTime(180)") -- 3m -openspace.bindKey("4", "openspace.time.setDeltaTime(900)") -- 15m -openspace.bindKey("5", "openspace.time.setDeltaTime(3600)") -- 1h -openspace.bindKey("6", "openspace.time.setDeltaTime(14400)") -- 3h -openspace.bindKey("7", "openspace.time.setDeltaTime(43200)") -- 12h -openspace.bindKey("8", "openspace.time.setDeltaTime(86400)") -- 1d -openspace.bindKey("9", "openspace.time.setDeltaTime(172800)") -- 2d - -openspace.bindKey("v", "openspace.time.setTime('2014 AUG 22 03:45:00'); openspace.time.setDeltaTime(1);") -openspace.bindKey("b", "openspace.time.setTime('2014 SEP 02 11:30:30'); openspace.time.setDeltaTime(1);") -openspace.bindKey("n", "openspace.time.setTime('2014 SEP 14 17:55:00'); openspace.time.setDeltaTime(1);") - -openspace.bindKey("i", "local b = openspace.getPropertyValue('ImagePlaneRosetta.renderable.enabled'); openspace.setPropertyValue('ImagePlaneRosetta.renderable.enabled', not b)") ---]] - -openspace.bindKey("F8", "openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") - --- Quickfix backjumps in pluto sequence -openspace.bindKey("F9", "openspace.time.setTime('2015-07-14T09:00:00.00'); openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") -openspace.bindKey("F10", "openspace.time.setTime('2015-07-14T10:00:00.00'); openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") -openspace.bindKey("F11", "openspace.time.setTime('2015-07-14T11:17:00.00'); openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") -openspace.bindKey("F12", "openspace.time.setTime('2015-07-14T12:45:00.00'); openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") - -openspace.bindKey("r", "local b = openspace.getPropertyValue('PlutoProjection.renderable.fk'); openspace.setPropertyValue('PlutoProjection.renderable.fk', not b)") - -openspace.bindKey("a", "openspace.setPropertyValue('Interaction.origin', 'NewHorizons')") -openspace.bindKey("s", "openspace.setPropertyValue('Interaction.origin', 'PlutoProjection')") -openspace.bindKey("d", "openspace.setPropertyValue('Interaction.origin', 'Charon')") -openspace.bindKey("z", "openspace.setPropertyValue('Interaction.origin', 'JupiterProjection')") -openspace.bindKey("x", "openspace.setPropertyValue('Interaction.origin', 'Europa')") - - -openspace.bindKey("g", "openspace.time.setTime('2007-02-28T11:40:00.00'); openspace.time.setDeltaTime(1);") -openspace.bindKey("v", "openspace.time.setTime('2015-03-15T11:00:00.00'); openspace.time.setDeltaTime(0);") -openspace.bindKey("h", "openspace.time.setTime('2015-07-14T10:00:00.00'); openspace.time.setDeltaTime(1); openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto');openspace.setPropertyValue('Interaction.origin', 'PlutoProjection'); openspace.printInfo('Changing Viewpoint to Pluto-in-center');") - -openspace.bindKey("i", "local b = openspace.getPropertyValue('PlutoTexture.renderable.enabled'); openspace.setPropertyValue('PlutoTexture.renderable.enabled', not b)") - -openspace.bindKey("q", "local b = openspace.getPropertyValue('SunMarker.renderable.enabled'); openspace.setPropertyValue('SunMarker.renderable.enabled', not b)") -openspace.bindKey("e", "local b = openspace.getPropertyValue('EarthMarker.renderable.enabled'); openspace.setPropertyValue('EarthMarker.renderable.enabled', not b)") - -openspace.bindKey("o", "local b = openspace.getPropertyValue('PlutoTrail.renderable.enabled'); openspace.setPropertyValue('PlutoTrail.renderable.enabled', not b)") - -openspace.bindKey("k", "local b = openspace.getPropertyValue('HydraText.renderable.enabled'); openspace.setPropertyValue('HydraText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('CharonText.renderable.enabled'); openspace.setPropertyValue('CharonText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('NixText.renderable.enabled'); openspace.setPropertyValue('NixText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('KerberosText.renderable.enabled'); openspace.setPropertyValue('KerberosText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('StyxText.renderable.enabled'); openspace.setPropertyValue('StyxText.renderable.enabled', not b)") -openspace.bindKey("j", "local b = openspace.getPropertyValue('PlutoText.renderable.enabled'); openspace.setPropertyValue('PlutoText.renderable.enabled', not b)") - -openspace.bindKey("l", "local b = openspace.getPropertyValue('Labels.renderable.performFading'); openspace.setPropertyValue('Labels.renderable.performFading', not b)") - -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_LORRI.renderable.solidDraw'); openspace.setPropertyValue('NH_LORRI.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_LEISA.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_LEISA.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_PAN1.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_PAN1.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_PAN2.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_PAN2.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_RED.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_RED.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_BLUE.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_BLUE.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_FT.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_FT.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_METHANE.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_METHANE.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_NIR.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_NIR.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_ALICE_AIRGLOW.renderable.solidDraw'); openspace.setPropertyValue('NH_ALICE_AIRGLOW.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_ALICE_SOC.renderable.solidDraw'); openspace.setPropertyValue('NH_ALICE_SOC.renderable.solidDraw', not b)") - -openspace.bindKey("t", "local b = openspace.getPropertyValue('PlutoShadow.renderable.enabled'); openspace.setPropertyValue('PlutoShadow.renderable.enabled', not b)") -openspace.bindKey("t", "local b = openspace.getPropertyValue('CharonShadow.renderable.enabled'); openspace.setPropertyValue('CharonShadow.renderable.enabled', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('JupiterProjection.renderable.performProjection'); openspace.setPropertyValue('JupiterProjection.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Io.renderable.performProjection'); openspace.setPropertyValue('Io.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Ganymede.renderable.performProjection'); openspace.setPropertyValue('Ganymede.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Europa.renderable.performProjection'); openspace.setPropertyValue('Europa.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Callisto.renderable.performProjection'); openspace.setPropertyValue('Callisto.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('PlutoProjection.renderable.performProjection'); openspace.setPropertyValue('PlutoProjection.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Charon.renderable.performProjection'); openspace.setPropertyValue('Charon.renderable.performProjection', not b)") +openspace.bindKey("q", helper.renderable.toggle('SunMarker')) +openspace.bindKey("e", helper.renderable.toggle('EarthMarker')) +openspace.bindKey("x", helper.renderable.toggle('Constellation Bounds')) openspace.bindKey("c", "openspace.parallel.setAddress('130.236.142.51');openspace.parallel.setPassword('newhorizons-20150714');openspace.parallel.connect();") - - -openspace.bindKey("COMMA", "openspace.setRenderer('Framebuffer');") -openspace.bindKey("PERIOD", "openspace.setRenderer('ABuffer');") \ No newline at end of file diff --git a/scripts/bind_keys_newhorizons.lua b/scripts/bind_keys_newhorizons.lua index e20d5cf4b8..7d82119ab0 100644 --- a/scripts/bind_keys_newhorizons.lua +++ b/scripts/bind_keys_newhorizons.lua @@ -1,29 +1,25 @@ --[[ OpenSpace keybinding script ]]-- --- This script sets the default keybindings and is executed at startup + +-- Load the common helper functions +dofile(openspace.absPath('${SCRIPTS}/common.lua')) openspace.clearKeys() -openspace.bindKey("F1", "openspace.gui.toggle()") -openspace.bindKey("F2", "openspace.setPerformanceMeasurement(true)") -openspace.bindKey("F3", "openspace.setPerformanceMeasurement(false)") -openspace.bindKey("F5", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun'); openspace.printInfo('Changing Viewpoint to Sun-in-center');"); -openspace.bindKey("F6", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Jupiter'); openspace.printInfo('Changing Viewpoint to Jupiter-in-center');"); -openspace.bindKey("F7", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto'); openspace.printInfo('Changing Viewpoint to Pluto-in-center');"); +helper.setCommonKeys() -openspace.bindKey("PRINT_SCREEN", "openspace.takeScreenshot()") +helper.setDeltaTimeKeys({ + 1, 5, 10, 20, 40, 60, 120, 360, 540, 1080, + 2160, 4320, 8640 +}) -openspace.bindKey("SPACE", "openspace.time.togglePause()") +openspace.bindKey("a", "openspace.setPropertyValue('Interaction.origin', 'NewHorizons')") +openspace.bindKey("s", "openspace.setPropertyValue('Interaction.origin', 'PlutoProjection')") +openspace.bindKey("d", "openspace.setPropertyValue('Interaction.origin', 'Charon')") +openspace.bindKey("z", "openspace.setPropertyValue('Interaction.origin', 'JupiterProjection')") +openspace.bindKey("x", "openspace.setPropertyValue('Interaction.origin', 'Europa')") --- Bookmarks for the New Horizons encounter -openspace.bindKey("1", "openspace.time.setDeltaTime(1)") -openspace.bindKey("2", "openspace.time.setDeltaTime(5)") -openspace.bindKey("3", "openspace.time.setDeltaTime(10)") -openspace.bindKey("4", "openspace.time.setDeltaTime(20)") -openspace.bindKey("5", "openspace.time.setDeltaTime(40)") -openspace.bindKey("6", "openspace.time.setDeltaTime(60)") -openspace.bindKey("7", "openspace.time.setDeltaTime(120)") -openspace.bindKey("8", "openspace.time.setDeltaTime(360)") -openspace.bindKey("9", "openspace.time.setDeltaTime(540)") -openspace.bindKey("9", "openspace.time.setDeltaTime(1080)") +openspace.bindKey("F5", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun'); openspace.printInfo('Changing Viewpoint to Sun');"); +openspace.bindKey("F6", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Jupiter'); openspace.printInfo('Changing Viewpoint to Jupiter');"); +openspace.bindKey("F7", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto'); openspace.printInfo('Changing Viewpoint to Pluto');"); openspace.bindKey("F8", "openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") @@ -33,59 +29,46 @@ openspace.bindKey("F10", "openspace.time.setTime('2015-07-14T10:00:00.00'); open openspace.bindKey("F11", "openspace.time.setTime('2015-07-14T11:17:00.00'); openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") openspace.bindKey("F12", "openspace.time.setTime('2015-07-14T12:45:00.00'); openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") -openspace.bindKey("r", "local b = openspace.getPropertyValue('PlutoProjection.renderable.fk'); openspace.setPropertyValue('PlutoProjection.renderable.fk', not b)") +openspace.bindKey("r", helper.property.invert('PlutoProjection.renderable.fk')) -openspace.bindKey("a", "openspace.setPropertyValue('Interaction.origin', 'NewHorizons')") -openspace.bindKey("s", "openspace.setPropertyValue('Interaction.origin', 'PlutoProjection')") -openspace.bindKey("d", "openspace.setPropertyValue('Interaction.origin', 'Charon')") -openspace.bindKey("z", "openspace.setPropertyValue('Interaction.origin', 'JupiterProjection')") -openspace.bindKey("x", "openspace.setPropertyValue('Interaction.origin', 'Europa')") +openspace.bindKey("KP_8", helper.property.increment('PlutoProjection.renderable.heightExaggeration', 2)) +openspace.bindKey("KP_2", helper.property.decrement('PlutoProjection.renderable.heightExaggeration', 2)) + +openspace.bindKey("KP_9", helper.property.increment('Charon.renderable.heightExaggeration', 2)) +openspace.bindKey("KP_3", helper.property.decrement('Charon.renderable.heightExaggeration', 2)) openspace.bindKey("g", "openspace.time.setTime('2007-02-28T11:40:00.00'); openspace.time.setDeltaTime(1);") openspace.bindKey("h", "openspace.time.setTime('2015-07-14T10:00:00.00'); openspace.time.setDeltaTime(1); openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto');openspace.setPropertyValue('Interaction.origin', 'PlutoProjection'); openspace.printInfo('Changing Viewpoint to Pluto-in-center');") -openspace.bindKey("i", "local b = openspace.getPropertyValue('PlutoTexture.renderable.enabled'); openspace.setPropertyValue('PlutoTexture.renderable.enabled', not b)") +openspace.bindKey("q", helper.property.invert('SunMarker.renderable.enabled')) +openspace.bindKey("e", helper.property.invert('EarthMarker.renderable.enabled')) +openspace.bindKey("o", helper.property.invert('PlutoTrail.renderable.enabled')) -openspace.bindKey("q", "local b = openspace.getPropertyValue('SunMarker.renderable.enabled'); openspace.setPropertyValue('SunMarker.renderable.enabled', not b)") -openspace.bindKey("e", "local b = openspace.getPropertyValue('EarthMarker.renderable.enabled'); openspace.setPropertyValue('EarthMarker.renderable.enabled', not b)") +openspace.bindKey("k", + helper.renderable.toggle('HydraText') .. helper.renderable.toggle('NixText') .. helper.renderable.toggle('KerberosText') .. helper.renderable.toggle('StyxText') +) +openspace.bindKey("j", helper.renderable.toggle('PlutoText')) -openspace.bindKey("o", "local b = openspace.getPropertyValue('PlutoTrail.renderable.enabled'); openspace.setPropertyValue('PlutoTrail.renderable.enabled', not b)") +openspace.bindKey("l", helper.property.invert('Labels.renderable.performFading')) -openspace.bindKey("k", "local b = openspace.getPropertyValue('HydraText.renderable.enabled'); openspace.setPropertyValue('HydraText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('CharonText.renderable.enabled'); openspace.setPropertyValue('CharonText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('NixText.renderable.enabled'); openspace.setPropertyValue('NixText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('KerberosText.renderable.enabled'); openspace.setPropertyValue('KerberosText.renderable.enabled', not b)") -openspace.bindKey("k", "local b = openspace.getPropertyValue('StyxText.renderable.enabled'); openspace.setPropertyValue('StyxText.renderable.enabled', not b)") -openspace.bindKey("j", "local b = openspace.getPropertyValue('PlutoText.renderable.enabled'); openspace.setPropertyValue('PlutoText.renderable.enabled', not b)") +openspace.bindKey("m", + helper.property.invert('NH_LORRI.renderable.solidDraw') .. helper.property.invert('NH_RALPH_LEISA.renderable.solidDraw') .. + helper.property.invert('NH_RALPH_MVIC_PAN1.renderable.solidDraw') .. helper.property.invert('NH_RALPH_MVIC_PAN2.renderable.solidDraw') .. + helper.property.invert('NH_RALPH_MVIC_RED.renderable.solidDraw') .. helper.property.invert('NH_RALPH_MVIC_BLUE.renderable.solidDraw') .. + helper.property.invert('NH_RALPH_MVIC_FT.renderable.solidDraw') .. helper.property.invert('NH_RALPH_MVIC_METHANE.renderable.solidDraw') .. + helper.property.invert('NH_RALPH_MVIC_NIR.renderable.solidDraw') .. helper.property.invert('NH_ALICE_AIRGLOW.renderable.solidDraw') .. + helper.property.invert('NH_ALICE_SOC.renderable.solidDraw') +) -openspace.bindKey("l", "local b = openspace.getPropertyValue('Labels.renderable.performFading'); openspace.setPropertyValue('Labels.renderable.performFading', not b)") +openspace.bindKey("t", helper.renderable.toggle('PlutoShadow') .. helper.renderable.toggle('CharonShadow')) -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_LORRI.renderable.solidDraw'); openspace.setPropertyValue('NH_LORRI.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_LEISA.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_LEISA.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_PAN1.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_PAN1.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_PAN2.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_PAN2.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_RED.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_RED.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_BLUE.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_BLUE.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_FT.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_FT.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_METHANE.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_METHANE.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_NIR.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_NIR.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_ALICE_AIRGLOW.renderable.solidDraw'); openspace.setPropertyValue('NH_ALICE_AIRGLOW.renderable.solidDraw', not b)") -openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_ALICE_SOC.renderable.solidDraw'); openspace.setPropertyValue('NH_ALICE_SOC.renderable.solidDraw', not b)") - -openspace.bindKey("t", "local b = openspace.getPropertyValue('PlutoShadow.renderable.enabled'); openspace.setPropertyValue('PlutoShadow.renderable.enabled', not b)") -openspace.bindKey("t", "local b = openspace.getPropertyValue('CharonShadow.renderable.enabled'); openspace.setPropertyValue('CharonShadow.renderable.enabled', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('JupiterProjection.renderable.performProjection'); openspace.setPropertyValue('JupiterProjection.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Io.renderable.performProjection'); openspace.setPropertyValue('Io.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Ganymede.renderable.performProjection'); openspace.setPropertyValue('Ganymede.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Europa.renderable.performProjection'); openspace.setPropertyValue('Europa.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Callisto.renderable.performProjection'); openspace.setPropertyValue('Callisto.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('PlutoProjection.renderable.performProjection'); openspace.setPropertyValue('PlutoProjection.renderable.performProjection', not b)") -openspace.bindKey("p", "local b = openspace.getPropertyValue('Charon.renderable.performProjection'); openspace.setPropertyValue('Charon.renderable.performProjection', not b)") +openspace.bindKey("p", + helper.property.invert('JupiterProjection.renderable.performProjection') .. helper.property.invert('Io.renderable.performProjection') .. + helper.property.invert('Ganymede.renderable.performProjection') .. helper.property.invert('Europa.renderable.performProjection') .. + helper.property.invert('Callisto.renderable.performProjection') .. helper.property.invert('PlutoProjection.renderable.performProjection') .. + helper.property.invert('Charon.renderable.performProjection') +) openspace.bindKey("c", "openspace.parallel.setAddress('130.236.142.51');openspace.parallel.setPassword('newhorizons-20150714');openspace.parallel.connect();") - - -openspace.bindKey("COMMA", "openspace.setRenderer('Framebuffer');") -openspace.bindKey("PERIOD", "openspace.setRenderer('ABuffer');") \ No newline at end of file diff --git a/scripts/bind_keys_rosetta.lua b/scripts/bind_keys_rosetta.lua index 3c353c3b16..d6184966bc 100644 --- a/scripts/bind_keys_rosetta.lua +++ b/scripts/bind_keys_rosetta.lua @@ -1,45 +1,26 @@ --[[ OpenSpace keybinding script ]]-- -- This script sets the default keybindings and is executed at startup +-- Load the common helper functions +dofile(openspace.absPath('${SCRIPTS}/common.lua')) + openspace.clearKeys() -openspace.bindKey("F1", "openspace.gui.toggle()") -openspace.bindKey("F2", "openspace.setPerformanceMeasurement(true)") -openspace.bindKey("F3", "openspace.setPerformanceMeasurement(false)") -openspace.bindKey("F5", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun'); openspace.printInfo('Changing Viewpoint to Sun-in-center');"); -openspace.bindKey("F6", "openspace.setPropertyValue('Interaction.coordinateSystem', '67P'); openspace.printInfo('Changing Viewpoint to 67P-in-center');"); +helper.setCommonKeys() -openspace.bindKey("PRINT_SCREEN", "openspace.takeScreenshot()") - -openspace.bindKey("SPACE", "openspace.time.togglePause()") - --- Bookmarks for the New Horizons encounter -openspace.bindKey("1", "openspace.time.setDeltaTime(1)") -openspace.bindKey("2", "openspace.time.setDeltaTime(5)") -openspace.bindKey("3", "openspace.time.setDeltaTime(10)") -openspace.bindKey("4", "openspace.time.setDeltaTime(20)") -openspace.bindKey("5", "openspace.time.setDeltaTime(40)") -openspace.bindKey("6", "openspace.time.setDeltaTime(90)") -openspace.bindKey("7", "openspace.time.setDeltaTime(360)") -openspace.bindKey("8", "openspace.time.setDeltaTime(720)") -openspace.bindKey("9", "openspace.time.setDeltaTime(2880)") -openspace.bindKey("0", "openspace.time.setDeltaTime(14400)") -openspace.bindKey("SHIFT+1", "openspace.time.setDeltaTime(28800)") -openspace.bindKey("SHIFT+2", "openspace.time.setDeltaTime(57600)") -openspace.bindKey("SHIFT+3", "openspace.time.setDeltaTime(115200)") -openspace.bindKey("SHIFT+4", "openspace.time.setDeltaTime(230400)") -openspace.bindKey("SHIFT+5", "openspace.time.setDeltaTime(460800)") - -openspace.bindKey("i", "local b = openspace.getPropertyValue('ImagePlaneRosetta.renderable.enabled'); openspace.setPropertyValue('ImagePlaneRosetta.renderable.enabled', not b)") - -openspace.bindKey("F8", "openspace.setPropertyValue('PlutoProjection.renderable.clearAllProjections', true); openspace.setPropertyValue('Charon.renderable.clearAllProjections', true);") +helper.setDeltaTimeKeys({ + 1, 5, 10, 20, 40, 90, 360, 720, 2880, 14400, + 28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600 +}) openspace.bindKey("a", "openspace.setPropertyValue('Interaction.origin', '67P')") openspace.bindKey("s", "openspace.setPropertyValue('Interaction.origin', 'Rosetta')") -openspace.bindKey("q", "local b = openspace.getPropertyValue('SunMarker.renderable.enabled'); openspace.setPropertyValue('SunMarker.renderable.enabled', not b)") -openspace.bindKey("e", "local b = openspace.getPropertyValue('EarthMarker.renderable.enabled'); openspace.setPropertyValue('EarthMarker.renderable.enabled', not b)") +-- openspace.bindKey("F5", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun'); openspace.printInfo('Changing Viewpoint to Sun');"); +openspace.bindKey("F6", "openspace.setPropertyValue('Interaction.coordinateSystem', '67P'); openspace.printInfo('Changing Viewpoint to 67P');"); +openspace.bindKey("F8", "openspace.setPropertyValue('67P.renderable.clearAllProjections', true);"); + +openspace.bindKey("i", helper.renderable.toggle('ImagePlaneRosetta')) +openspace.bindKey("q", helper.renderable.toggle('SunMarker')) +openspace.bindKey("e", helper.renderable.toggle('EarthMarker')) openspace.bindKey("c", "openspace.parallel.setAddress('130.236.142.51');openspace.parallel.setPassword('newhorizons-20150714');openspace.parallel.connect();") - -openspace.bindKey("COMMA", "openspace.setRenderer('Framebuffer');") -openspace.bindKey("PERIOD", "openspace.setRenderer('ABuffer');") \ No newline at end of file diff --git a/scripts/common.lua b/scripts/common.lua new file mode 100644 index 0000000000..cef02c1794 --- /dev/null +++ b/scripts/common.lua @@ -0,0 +1,61 @@ +--[[ Commonly used OpenSpace configuration functions ]]-- + +helper = {} +helper.renderable = {} +helper.property = {} + +-- Function that sets the most common key bindings that are common to most (all?) +-- scenes +helper.setCommonKeys = function() + openspace.bindKey("F1", "openspace.gui.toggle()") + openspace.bindKey("F2", "openspace.setPerformanceMeasurement(true)") + openspace.bindKey("F3", "openspace.setPerformanceMeasurement(false)") + + openspace.bindKey("PRINT_SCREEN", "openspace.takeScreenshot()") + openspace.bindKey("SPACE", "openspace.time.togglePause()") + + openspace.bindKey("COMMA", "openspace.setRenderer('Framebuffer');") + openspace.bindKey("PERIOD", "openspace.setRenderer('ABuffer');") +end + +helper.setDeltaTimeKeys = function(t) + local Keys = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + 'Shift+1', 'Shift+2', 'Shift+3', 'Shift+4', 'Shift+5', 'Shift+6', 'Shift+7', 'Shift+8', 'Shift+9', 'Shift+0', + 'Ctrl+1', 'Ctrl+2', 'Ctrl+3', 'Ctrl+4', 'Ctrl+5', 'Ctrl+6', 'Ctrl+7', 'Ctrl+8', 'Ctrl+9', 'Ctrl+0', + 'Alt+1', 'Alt+2', 'Alt+3', 'Alt+4', 'Alt+5', 'Alt+6', 'Alt+7', 'Alt+8', 'Alt+9', 'Alt+0' + } + + if #t > #Keys then + openspace.printError("Error settings delta time keys: Too many delta times (" .. #t .. ")") + return + end + + for i, v in ipairs(t) do + openspace.bindKey(Keys[i], 'openspace.time.setDeltaTime(' .. v .. ")") + end +end + +-- Function that returns the string that inverts the fully qualified boolean property 'property' +helper.property.invert = function(property) + local escaped_property = "'" .. property .. "'" + return "openspace.setPropertyValue(" .. escaped_property .. ", not openspace.getPropertyValue(" .. escaped_property .. "));" +end + +-- Function that returns the string that increments the 'property' by the 'value' +helper.property.increment = function(property, value) + local v = value or 1 + local escaped_property = "'" .. property .. "'" + return "openspace.setPropertyValue(" .. escaped_property .. ", openspace.getPropertyValue(" .. escaped_property .. ") + " .. v .. ")" +end + +-- Function that returns the string that decrements the 'property' by the 'value' +helper.property.decrement = function(property, value) + return helper.property.increment(property, -value) +end + +-- Function that returns the string that enables/disables the renderable 'renderable' +helper.renderable.toggle = function(renderable) + return helper.property.invert(renderable .. ".renderable.enabled") +end + diff --git a/shaders/PowerScaling/powerScalingMath.hglsl b/shaders/PowerScaling/powerScalingMath.hglsl index b14e15db60..035b21a958 100644 --- a/shaders/PowerScaling/powerScalingMath.hglsl +++ b/shaders/PowerScaling/powerScalingMath.hglsl @@ -76,15 +76,7 @@ vec2 psc_subtraction(vec2 v1, vec2 v2) { vec4 z_normalization(vec4 v_in) { vec4 v_out = v_in; - if(v_out.z > 0.0) { - v_out.z = 1; - } else if(v_out.z < 0.0) { - v_out.z = 1; - } else { - float tmp = max(max(abs(v_out.x), abs(v_out.y)),0); - if(tmp == 0.0) - v_out.s = FLT_MAX; - } + v_out.z = 0; return v_out; } diff --git a/shaders/PowerScaling/powerScaling_fs.hglsl b/shaders/PowerScaling/powerScaling_fs.hglsl index 855c98707a..ba2442ebcf 100644 --- a/shaders/PowerScaling/powerScaling_fs.hglsl +++ b/shaders/PowerScaling/powerScaling_fs.hglsl @@ -53,7 +53,11 @@ float pscDepth(vec4 position) { // For now: simply convert power scaled coordinates to a linear scale. // TODO: get rid of power scaled coordinates and use scale graph instead. // return (position.w + log(abs(position.z) + 1/pow(k, position.w))/log(k)) / 27.0; - return safeLength(pscToLinear(position)); + if (position.z < 0) { + return safeLength(pscToLinear(position)); + } else { + return -safeLength(pscToLinear(position)); + } } diff --git a/shaders/abuffer/abufferresources.glsl b/shaders/abuffer/abufferresources.glsl index 60abbe48f9..4241885318 100644 --- a/shaders/abuffer/abufferresources.glsl +++ b/shaders/abuffer/abufferresources.glsl @@ -29,6 +29,7 @@ #define MAX_LAYERS #{rendererData.maxLayers} ABufferFragment fragments[MAX_LAYERS]; +uint fragmentIndices[MAX_LAYERS]; layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; @@ -56,10 +57,30 @@ uint loadFragments() { while (currentIndex != NULL_POINTER && nFrags < MAX_LAYERS) { ABufferFragment frag = loadFragment(currentIndex); fragments[nFrags] = frag; + fragmentIndices[nFrags] = currentIndex; currentIndex = _next_(frag); nFrags++; } return nFrags; } +/** + * Store the current contents of the fragments array back into the abuffer. + */ +void storeFragments(uint nFrags) { + if (nFrags == 0) + return; + uint maxFragIndex = nFrags - 1; + for (int i = 0; i < maxFragIndex; i++) { + _next_(fragments[i], fragmentIndices[i+1]); + storeFragment(fragmentIndices[i], fragments[i]); + } + _next_(fragments[maxFragIndex], NULL_POINTER); + storeFragment(fragmentIndices[maxFragIndex], fragments[maxFragIndex]); + +} + + + + #endif diff --git a/shaders/abuffer/boundsabuffer.frag b/shaders/abuffer/boundsabuffer.frag index d5718c2913..3523037570 100644 --- a/shaders/abuffer/boundsabuffer.frag +++ b/shaders/abuffer/boundsabuffer.frag @@ -37,6 +37,11 @@ void main() { int sampleMask = gl_SampleMaskIn[0]; + if (frag.depth < 0) { + // discard; + } + + uint newHead = atomicCounterIncrement(atomicCounterBuffer); uint prevHead = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), newHead); diff --git a/shaders/abuffer/postrenderabuffer.frag b/shaders/abuffer/postrenderabuffer.frag new file mode 100644 index 0000000000..53136ea591 --- /dev/null +++ b/shaders/abuffer/postrenderabuffer.frag @@ -0,0 +1,130 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include "fragment.glsl" +#include <#{fragmentPath}> +#include "abufferfragment.glsl" +#include "abufferresources.glsl" +#include "PowerScaling/powerScalingMath.hglsl" +#include "rand.glsl" +#include "resolveconstants.glsl" + +#include "resolvehelpers.glsl" + +#define RAYCASTING_ENABLED #{resolveData.raycastingEnabled} +uniform float blackoutFactor; +uniform sampler2DMS mainColorTexture; +uniform sampler2DMS mainDepthTexture; + +out vec4 _out_color_; + +void main() { + + Fragment newFrag = getFragment(); + int sampleMask = gl_SampleMaskIn[0]; + + float fboDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), 0).x); + vec4 fboRgba = texelFetch(mainColorTexture, ivec2(gl_FragCoord), 0); + + if (newFrag.depth > fboDepth) { + discard; + } + + //newFrag.color *= countSamples(sampleMask) / nAaSamples; +/* + vec3 accumulatedColor = vec3(0.0); + + // One alpha channel per color channel to allow for + // absorption of different wavelengths. + // Always within the interval [0, 1] + vec3 accumulatedAlpha = vec3(0.0); + + + uint nFrags = loadFragments(); + uint raycasterMask; +#if RAYCASTING_ENABLED + bool insideAnyRaycaster = initRaycasterMask(raycasterMask); +#endif + + +#if RAYCASTING_ENABLED + retrieveRaycasterData(nFrags); + + if (insideAnyRaycaster) { + //raycast to the first fragment + float startDepth = 0; + float endDepth = min(_depth_(fragments[0]), newFrag.depth); + raycast(endDepth - startDepth, raycasterMask, accumulatedColor, accumulatedAlpha); + } +#endif + + for (uint i = 0; i < nFrags; i++) { + ABufferFragment frag = fragments[i]; + + if (_depth_(frag) > newFrag.depth) { + break; + } + + int type = _type_(frag); + uint blend = _blend_(frag); + + if (type == 0) { // geometry fragment + vec4 color = _color_(frag); + if (blend == BLEND_MODE_NORMAL) { + accumulatedColor += (1 - accumulatedAlpha) * color.rgb * color.a; + accumulatedAlpha += (1 - accumulatedAlpha) * color.aaa; + } else if (blend == BLEND_MODE_ADDITIVE) { + accumulatedColor += (1 - accumulatedAlpha) * color.rgb; + } + } +#if RAYCASTING_ENABLED + else if (type > 0) { // enter volume + int raycasterId = type - 1; + // only enter volume if a valid scale was detected + if (raycasterData[raycasterId].scale > 0) { + raycasterMask |= (1 << (raycasterId)); + } + } else { // exit volume + int raycasterId = -type - 1; + raycasterMask &= INT_MAX - (1 << (raycasterId)); + } + // Ray cast to next fragment + if (i + 1 < nFrags && raycasterMask != 0) { + float startDepth = _depth_(fragments[i]); + float endDepth = min(_depth_(fragments[i + 1]), newFrag.depth); + raycast(endDepth - startDepth, raycasterMask, accumulatedColor, accumulatedAlpha); + } +#endif + } +*/ + + + vec4 newColor = newFrag.color; + vec3 contribution = newColor.rgb * blackoutFactor; + + _out_color_ = vec4(contribution, 1.0); + // _out_color_ = vec4(1.0); + +} + diff --git a/shaders/abuffer/raycasterdata.glsl b/shaders/abuffer/raycasterdata.glsl index 5f0b945365..d4f960d08b 100644 --- a/shaders/abuffer/raycasterdata.glsl +++ b/shaders/abuffer/raycasterdata.glsl @@ -31,6 +31,8 @@ struct RaycasterData { float scale; float previousJitterDistance; uint blend; -} +}; +RaycasterData raycasterData[N_RAYCASTERS]; + #endif diff --git a/shaders/abuffer/renderabuffer.frag b/shaders/abuffer/renderabuffer.frag index 6c05208a3b..d3abc97ddf 100644 --- a/shaders/abuffer/renderabuffer.frag +++ b/shaders/abuffer/renderabuffer.frag @@ -31,24 +31,38 @@ out vec4 _out_color_; void main() { Fragment frag = getFragment(); - int sampleMask = gl_SampleMaskIn[0]; - uint newHead = atomicCounterIncrement(atomicCounterBuffer); - if (newHead >= #{rendererData.maxTotalFragments}) { - discard; // ABuffer is full! + if (frag.depth < 0) { +// discard; } - uint prevHead = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), newHead); - - ABufferFragment aBufferFrag; - _color_(aBufferFrag, frag.color); - _depth_(aBufferFrag, frag.depth); - _blend_(aBufferFrag, frag.blend); + + //frag.forceFboRendering = true; + // todo: calculate full sample mask from nAaSamples instead of hardcoded 255. + if (!frag.forceFboRendering && (frag.color.a < 1.0 || sampleMask != 255)) { + uint newHead = atomicCounterIncrement(atomicCounterBuffer); + if (newHead >= #{rendererData.maxTotalFragments}) { + discard; // ABuffer is full! + } + uint prevHead = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), newHead); - _type_(aBufferFrag, 0); // 0 = geometry type - _msaa_(aBufferFrag, gl_SampleMaskIn[0]); - _next_(aBufferFrag, prevHead); + ABufferFragment aBufferFrag; + _color_(aBufferFrag, frag.color); + _depth_(aBufferFrag, frag.depth); + _blend_(aBufferFrag, frag.blend); + + _type_(aBufferFrag, 0); // 0 = geometry type + _msaa_(aBufferFrag, gl_SampleMaskIn[0]); + _next_(aBufferFrag, prevHead); + + storeFragment(newHead, aBufferFrag); + discard; + } else { + _out_color_ = frag.color; + gl_FragDepth = normalizeFloat(frag.depth); + } + + //gl_FragDepth = 1; - storeFragment(newHead, aBufferFrag); - discard; } + diff --git a/shaders/abuffer/resolveabuffer.frag b/shaders/abuffer/resolveabuffer.frag index 93329d3b65..38cb3269a5 100644 --- a/shaders/abuffer/resolveabuffer.frag +++ b/shaders/abuffer/resolveabuffer.frag @@ -24,6 +24,8 @@ #version __CONTEXT__ + +#include "resolveconstants.glsl" #include "abufferfragment.glsl" #include "abufferresources.glsl" #include "fragment.glsl" @@ -34,200 +36,67 @@ layout (location = 0) out vec4 finalColor; uniform float blackoutFactor; -uniform int nAaSamples; +uniform sampler2DMS mainColorTexture; +uniform sampler2DMS mainDepthTexture; +uniform float gamma = 1.0; -#define RAYCASTING_ENABLED #{raycastingEnabled} -#define N_RAYCASTERS #{nRaycasters} -#define ALPHA_LIMIT 0.99 -#define RAYCAST_MAX_STEPS 10000 -#define INT_MAX 2147483647 +#include "resolvehelpers.glsl" -///////////////////////// -#if RAYCASTING_ENABLED -#include "raycasterdata.glsl" - -RaycasterData raycasterData[N_RAYCASTERS]; -// Include all ray caster helpers -#for id, helperPath in helperPaths -#include <#{helperPath}> -#endfor - -// Include all ray casters -#for id, raycaster in raycasters -#include <#{raycaster.raycastPath}> -#endfor - -#endif -///////////////////////// - -void sortFragments(uint nFrags) { - ABufferFragment tmp; - uint i, j; - - // Insertion sort - for(i = 1; i < nFrags; ++i) { - tmp = fragments[i]; - for(j = i; j > 0 && _depth_(tmp) < _depth_(fragments[j-1]); --j) { - fragments[j] = fragments[j-1]; - } - fragments[j] = tmp; - } -} - -uint countSamples(uint mask) { - return ((mask >> 0) & 1) - + ((mask >> 1) & 1) - + ((mask >> 2) & 1) - + ((mask >> 3) & 1) - + ((mask >> 4) & 1) - + ((mask >> 5) & 1) - + ((mask >> 6) & 1) - + ((mask >> 7) & 1); -} - -uint reduceFragments(uint nFrags) { - uint outputIndex = 0; - for (uint inputIndex = 0; inputIndex < nFrags; inputIndex++, outputIndex++) { - - ABufferFragment frag = fragments[inputIndex]; - uint accumulatedMask = _msaa_(fragments[inputIndex]); - uint newMask = _msaa_(fragments[inputIndex]); - int type = _type_(fragments[inputIndex]); - - // Accumulate sample mask - for (uint j = inputIndex + 1; - j < nFrags && ((newMask = _msaa_(fragments[j])) & accumulatedMask) == 0 && _type_(fragments[j]) == type; - j++) { - accumulatedMask |= newMask; - inputIndex = j; - } - uint nSamples = countSamples(accumulatedMask); - vec4 color = _color_(fragments[inputIndex]); // TODO: Possibly weigh all samples together? - - // Adjust the alpha by the ratio of accumulated samples - float alpha = float(nSamples) / float(nAaSamples); - color.a *= alpha; - - ABufferFragment outputFragment = fragments[inputIndex]; - _color_(outputFragment, color); - - fragments[outputIndex] = outputFragment; - } - - // return number of outputted fragments - return outputIndex; -} - -#if RAYCASTING_ENABLED - -/** - * Iterate through list of sorted fragments, - * and retrieve raycasting position, direction, scale - */ -void retrieveRaycasterData(uint nFrags) { - float entryDepths[N_RAYCASTERS]; - for (int i = 0; i < N_RAYCASTERS; i++) { - entryDepths[i] = -1; - } - for (int i = 0; i < nFrags; i++) { - int type = _type_(fragments[i]); // - 1; - vec3 position = _position_(fragments[i]); - float depth = _depth_(fragments[i]); - uint blend = _blend_(fragments[i]); - if (type > 0) { // enter raycaster - int raycasterId = type - 1; - if (entryDepths[raycasterId] < 0) { // first entry - raycasterData[raycasterId].position = position; - raycasterData[raycasterId].previousJitterDistance = 0; - raycasterData[raycasterId].blend = blend; - entryDepths[raycasterId] = depth; - raycasterData[raycasterId].scale = -1; - } - } else if (type < 0) { // exit raycaster - int raycasterId = -type - 1; - vec3 localDirection = position - raycasterData[raycasterId].position; - raycasterData[raycasterId].direction = safeNormalize(localDirection); - raycasterData[raycasterId].scale = safeLength(localDirection) / (depth - entryDepths[raycasterId]); - } - } -} - -/** - * Perform raycasting - */ -void raycast(float raycastDepth, uint raycasterMask, inout vec4 finalColor) { - float nextStepSize = raycastDepth; - float currentStepSize = 0.0; - float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0 - -#for index, raycaster in raycasters - if ((raycasterMask & #{raycaster.bitmask}) != 0) { - RaycasterData data = raycasterData[#{index}]; - float maxStepSizeLocal = stepSize#{raycaster.id}(data.position, data.direction); - float maxStepSize = maxStepSizeLocal / data.scale; - nextStepSize = min(nextStepSize, maxStepSize); - } -#endfor - - float currentDepth = 0.0; - - for (int steps = 0; finalColor.a < ALPHA_LIMIT && steps < RAYCAST_MAX_STEPS; ++steps) { - bool exceededDepth = currentDepth + nextStepSize * jitterFactor > raycastDepth; - bool shortStepSize = nextStepSize < raycastDepth / 10000000000.0; - - if (exceededDepth || shortStepSize) { - break; - } - - currentStepSize = nextStepSize; - currentDepth += currentStepSize; - nextStepSize = raycastDepth - currentDepth; - -#for index, raycaster in raycasters - - if ((raycasterMask & #{raycaster.bitmask}) != 0) { - RaycasterData data = raycasterData[#{raycaster.id}]; - float stepSizeLocal = currentStepSize * data.scale; - float jitteredStepSizeLocal = stepSizeLocal * jitterFactor; - - vec3 jitteredPosition = data.position + data.direction*jitteredStepSizeLocal; - raycasterData[#{raycaster.id}].position += data.direction * stepSizeLocal; - - float maxStepSizeLocal; - - vec4 raycasterContribution = sample#{raycaster.id}(jitteredPosition, data.direction, finalColor, maxStepSizeLocal); - float sampleDistance = jitteredStepSizeLocal + data.previousJitterDistance; - uint blend = raycasterData[#{raycaster.id}].blend; - - if (blend == BLEND_MODE_NORMAL) { - normalBlendStep(finalColor, raycasterContribution, sampleDistance); - } else if (blend == BLEND_MODE_ADDITIVE) { - additiveBlendStep(finalColor, raycasterContribution, sampleDistance); - } - - raycasterData[#{raycaster.id}].previousJitterDistance = stepSizeLocal - jitteredStepSizeLocal; - float maxStepSize = maxStepSizeLocal/data.scale; - nextStepSize = min(nextStepSize, maxStepSize); - } -#endfor - } -} -#endif // RAYCASTING_ENABLED void main() { - finalColor = vec4(0.0); + // TODO: disable multisampling for main fbo. + float fboDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), 0).x); + vec4 fboRgba = texelFetch(mainColorTexture, ivec2(gl_FragCoord), 0); + + // RGB color values, premultiplied with alpha channels. + vec3 accumulatedColor = vec3(0.0); + + // One alpha channel per color channel to allow for + // absorption of different wavelengths. + // Always within the interval [0, 1] + vec3 accumulatedAlpha = vec3(0.0); uint nOriginalFrags = loadFragments(); uint raycasterMask = 0; + uint nFilteredFrags = nOriginalFrags; - sortFragments(nOriginalFrags); + // discard all fragments in abuffer with higher depth value than the fbo + nFilteredFrags = depthFilterFragments(nOriginalFrags, fboDepth); - uint nFrags = reduceFragments(nOriginalFrags); -#if RAYCASTING_ENABLED - retrieveRaycasterData(nFrags); + // sort remaining fragments from front to back + sortFragments(nFilteredFrags); + + // merge fragments whose sample masks don't igntersect + // to get the correct alpha for fragments on borders between triangles + uint nFrags = mergeFragments(nFilteredFrags); + + + + +#if STORE_SORTED + //storeFragments(nFrags); #endif +#if RAYCASTING_ENABLED + + + retrieveRaycasterData(nFrags); +#if RAYCASTING_ENABLED + bool insideAnyRaycaster = initRaycasterMask(raycasterMask); +#endif + //debugColor = vec4(raycasterData[0].direction, 1.0); + + if (insideAnyRaycaster) { + //raycast to the first fragment +// discard; + float startDepth = 0; + float endDepth = min(_depth_(fragments[0]), fboDepth); + raycast(endDepth - startDepth, raycasterMask, accumulatedColor, accumulatedAlpha); + //accumulatedColor = vec3(1.0); + } +#endif + for (uint i = 0; i < nFrags; i++) { ABufferFragment frag = fragments[i]; @@ -236,15 +105,22 @@ void main() { if (type == 0) { // geometry fragment vec4 color = _color_(frag); + color.rgb = pow(color.rgb, vec3(gamma)); + if (blend == BLEND_MODE_NORMAL) { - normalBlend(finalColor, color); + accumulatedColor += (1 - accumulatedAlpha) * color.rgb * color.a; + accumulatedAlpha += (1 - accumulatedAlpha) * color.aaa; + + //normalBlend(finalColor, color); } else if (blend == BLEND_MODE_ADDITIVE) { - additiveBlend(finalColor, color); + accumulatedColor += (1 - accumulatedAlpha) * color.rgb; + //additiveBlend(finalColor, color); } } #if RAYCASTING_ENABLED else if (type > 0) { // enter volume int raycasterId = type - 1; + //accumulatedColor += (1 - accumulatedAlpha) * _position_(frag); // only enter volume if a valid scale was detected if (raycasterData[raycasterId].scale > 0) { raycasterMask |= (1 << (raycasterId)); @@ -252,19 +128,54 @@ void main() { } else { // exit volume int raycasterId = -type - 1; raycasterMask &= INT_MAX - (1 << (raycasterId)); + //accumulatedColor = vec3(1.0); + //accumulatedColor += (1 - accumulatedAlpha) * _position_(frag); } // Ray cast to next fragment if (i + 1 < nFrags && raycasterMask != 0) { float startDepth = _depth_(fragments[i]); - float endDepth = _depth_(fragments[i + 1]); - raycast(endDepth - startDepth, raycasterMask, finalColor); + float endDepth = min(_depth_(fragments[i + 1]), fboDepth); + if (endDepth < startDepth) { + break; + } + + raycast(endDepth - startDepth, raycasterMask, accumulatedColor, accumulatedAlpha); + } #endif } - // finalColor is expressed with premultiplied alpha - finalColor.rgb *= blackoutFactor; - // Render everything on a black background - finalColor.a = 1.0; + accumulatedAlpha = clamp(accumulatedAlpha, 0.0, 1.0); + //maccumulatedAlpha = vec3(0.0); + accumulatedColor += (1 - accumulatedAlpha) * pow(fboRgba.rgb, vec3(gamma)); + + finalColor = vec4(accumulatedColor.rgb, 1.0); + + // Gamma correction. + finalColor.rgb = pow(finalColor.rgb, vec3(1.0 / gamma)); + // Black out factor. + + + finalColor = vec4(finalColor.rgb * blackoutFactor, 1.0); + + //finalColor = vec4(vec3(fboRgba.a), 1.0); + //finalColor = fboRgba; + //finalColor = vec4(0.0); + + //finalColor = vec4(0.0, acc/1000.0, acc/1000.0, 1.0); + //finalColor = vec4(acc/1000.0, 0.0, 0.0, 01.0); + //finalColor = vec4(vec3(float(nFrags) / 10), 1.0); + //finalColor = vec4(vec3(float(_depth_(fragments[0])) / 10), 1.0); + + + //finalColor = vec4(vec3(nFilteredFrags - nFrags) * 0.2, 1.0); + //finalColor = vec4(vec3(nFilteredFrags) * 0.2, 1.0); + //finalColor = vec4(vec3(nFrags) * 0.05, 1.0); + + //finalColor = vec4(raycasterData[0].position, 1.0); + //finalColor = debugColor; + //finalColor = vec4(gamma * 0.5); + //finalColor = vec4(fboRgba); } + diff --git a/shaders/abuffer/resolveconstants.glsl b/shaders/abuffer/resolveconstants.glsl new file mode 100644 index 0000000000..78e9fcd8f0 --- /dev/null +++ b/shaders/abuffer/resolveconstants.glsl @@ -0,0 +1,7 @@ +#define RAYCASTING_ENABLED #{resolveData.raycastingEnabled} +#define STORE_SORTED false //#{resolveData.storeSorted} +#define N_RAYCASTERS #{resolveData.nRaycasters} +#define ALPHA_LIMIT 0.9 +#define RAYCAST_MAX_STEPS 1000 +#define INT_MAX 2147483647 +#define GAMMA 2.2 \ No newline at end of file diff --git a/shaders/abuffer/resolvehelpers.glsl b/shaders/abuffer/resolvehelpers.glsl new file mode 100644 index 0000000000..b464550d7c --- /dev/null +++ b/shaders/abuffer/resolvehelpers.glsl @@ -0,0 +1,270 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef _RESOLVEHELPERS_GLSL_ +#define _RESOLVEHELPERS_GLSL_ + + +float acc = 0; + +#if RAYCASTING_ENABLED +#include "raycasterdata.glsl" + + + + +// Include all ray caster helpers +#for id, helperPath in resolveData.helperPaths +#include <#{helperPath}> +#endfor + + +// Include all ray casters +#for id, raycaster in resolveData.raycasters +#include <#{raycaster.raycastPath}> +#endfor + +#for index in 1..#{resolveData.nRaycasters} +uniform bool insideRaycaster#{index}; +uniform vec3 cameraPosInRaycaster#{index} +#endfor + + +#endif + + + + +uniform int nAaSamples; + +void sortFragments(uint nFrags) { + ABufferFragment tmp; + uint i, j; + + // Insertion sort + for(i = 1; i < nFrags; ++i) { + tmp = fragments[i]; + for(j = i; j > 0 && _depth_(tmp) < _depth_(fragments[j-1]); --j) { + fragments[j] = fragments[j-1]; + } + fragments[j] = tmp; + } +} + +uint countSamples(uint mask) { + return ((mask >> 0) & 1) + + ((mask >> 1) & 1) + + ((mask >> 2) & 1) + + ((mask >> 3) & 1) + + ((mask >> 4) & 1) + + ((mask >> 5) & 1) + + ((mask >> 6) & 1) + + ((mask >> 7) & 1); +} + +uint depthFilterFragments(uint nFrags, float depthThreshold) { + uint j = 0; + for (uint i = 0; i < nFrags; i++) { + if (_type_(fragments[i]) != 0 || _depth_(fragments[i]) < depthThreshold) { + fragments[j] = fragments[i]; + j++; + } + } + return j; +} + + +uint mergeFragments(uint nFrags) { + uint outputIndex = 0; + for (uint inputIndex = 0; inputIndex < nFrags; inputIndex++, outputIndex++) { + + ABufferFragment frag = fragments[inputIndex]; + uint accumulatedMask = _msaa_(fragments[inputIndex]); + uint newMask = _msaa_(fragments[inputIndex]); + int type = _type_(fragments[inputIndex]); + + // Accumulate sample mask + for (uint j = inputIndex + 1; +//abs(_depth_(fragments[j]) - _depth_(fragments[inputIndex])) < 0.000000001; //&& +j < nFrags && ((newMask = _msaa_(fragments[j])) & accumulatedMask) == 0 && _type_(fragments[j]) == type; + j++) { + accumulatedMask |= newMask; + inputIndex = j; + } + uint nSamples = countSamples(accumulatedMask); + ABufferFragment outputFragment = fragments[inputIndex]; + if (type == 0) { + vec4 color = _color_(fragments[inputIndex]); // TODO: Possibly weigh all samples together? + // Adjust the alpha by the ratio of accumulated samples + float alpha = float(nSamples) / float(nAaSamples); + color.a *= alpha; + _color_(outputFragment, color); + } + fragments[outputIndex] = outputFragment; + } + + // return number of outputted fragments + return outputIndex; +} + +#if RAYCASTING_ENABLED + +/** + * Iterate through list of sorted fragments, + * and retrieve raycasting position, direction, scale + */ +void retrieveRaycasterData(uint nFrags) { + float entryDepths[N_RAYCASTERS]; +#for i in 1..#{resolveData.nRaycasters} + { + int j = #{i} - 1; + entryDepths[j] = -1; + raycasterData[j].scale = -1; + bool inside = insideRaycaster#{i}; + if (inside) { + entryDepths[j] = 0; + raycasterData[j].position = cameraPosInRaycaster#{i}; + raycasterData[j].previousJitterDistance = 0; + } + } +#endfor + + for (int i = 0; i < nFrags; i++) { + int type = _type_(fragments[i]); // - 1; + vec3 position = _position_(fragments[i]); + float depth = _depth_(fragments[i]); + uint blend = _blend_(fragments[i]); + if (type > 0) { // enter raycaster + int raycasterId = type - 1; + if (entryDepths[raycasterId] < 0) { // first entry + raycasterData[raycasterId].position = position; + raycasterData[raycasterId].previousJitterDistance = 0; + entryDepths[raycasterId] = depth; + raycasterData[raycasterId].scale = -1; + } + } else if (type < 0) { // exit raycaster + int raycasterId = -type - 1; + vec3 localDirection = position - raycasterData[raycasterId].position; + + raycasterData[raycasterId].direction = safeNormalize(localDirection); + raycasterData[raycasterId].scale = safeLength(localDirection) / (depth - entryDepths[raycasterId]); + raycasterData[raycasterId].blend = blend; + } + } +} + + +/** + * Perform raycasting + */ +void raycast(float raycastDepth, uint raycasterMask, inout vec3 accumulatedColor, inout vec3 accumulatedAlpha) { + float nextStepSize = raycastDepth; + float currentStepSize = 0.0; + float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0 + +#for index, raycaster in resolveData.raycasters + if ((raycasterMask & #{raycaster.bitmask}) != 0) { + RaycasterData data = raycasterData[#{index}]; + float maxStepSizeLocal = stepSize#{raycaster.id}(data.position, data.direction); + float maxStepSize = maxStepSizeLocal / data.scale; + nextStepSize = min(nextStepSize, maxStepSize); + } +#endfor + + float currentDepth = 0.0; + for (int steps = 0; + (accumulatedAlpha.x < ALPHA_LIMIT || + accumulatedAlpha.y < ALPHA_LIMIT || + accumulatedAlpha.z < ALPHA_LIMIT) && + steps < RAYCAST_MAX_STEPS; + ++steps) { + bool exceededDepth = currentDepth + nextStepSize * jitterFactor > raycastDepth; + bool shortStepSize = nextStepSize < raycastDepth / 10000000000.0; + + if (exceededDepth || shortStepSize) { + break; + } + + currentStepSize = nextStepSize; + currentDepth += currentStepSize; + nextStepSize = raycastDepth - currentDepth; + +#for index, raycaster in resolveData.raycasters + if ((raycasterMask & #{raycaster.bitmask}) != 0) { + RaycasterData data = raycasterData[#{raycaster.id}]; + float stepSizeLocal = currentStepSize * data.scale; + float jitteredStepSizeLocal = stepSizeLocal * jitterFactor; + + vec3 jitteredPosition = data.position + data.direction*jitteredStepSizeLocal; + raycasterData[#{raycaster.id}].position += data.direction * stepSizeLocal; + + float maxStepSizeLocal; + + acc += 1.0; + sample#{raycaster.id}(jitteredPosition, + data.direction, + accumulatedColor, + accumulatedAlpha, + maxStepSizeLocal); + + + float sampleDistance = jitteredStepSizeLocal + data.previousJitterDistance; + uint blend = raycasterData[#{raycaster.id}].blend; + + /* + if (blend == BLEND_MODE_NORMAL) { + normalBlendStep(finalColor, raycasterContribution, sampleDistance); + } else if (blend == BLEND_MODE_ADDITIVE) { + additiveBlendStep(finalColor, raycasterContribution, sampleDistance); + }*/ + //finalColor = raycasterContribution; + + raycasterData[#{raycaster.id}].previousJitterDistance = stepSizeLocal - jitteredStepSizeLocal; + float maxStepSize = maxStepSizeLocal/data.scale; + nextStepSize = min(nextStepSize, maxStepSize); + } +#endfor + } +} + +bool initRaycasterMask(inout uint raycasterMask) { + bool insideAnyRaycaster = false; + raycasterMask = 0; +#for i in 1..#{resolveData.nRaycasters} + { + int j = #{i} - 1; + if (insideRaycaster#{i} && raycasterData[j].scale > 0) { + raycasterMask |= (1 << j); + insideAnyRaycaster = true; + } + } +#endfor + return insideAnyRaycaster; +} + + + +#endif // RAYCASTING_ENABLED + +#endif // _RESOLVEHELPERS_GLSL_ diff --git a/shaders/fragment.glsl b/shaders/fragment.glsl index 5064fb4e95..c409fbd073 100644 --- a/shaders/fragment.glsl +++ b/shaders/fragment.glsl @@ -32,6 +32,7 @@ struct Fragment { vec4 color; float depth; uint blend; + bool forceFboRendering; }; #endif diff --git a/shaders/framebuffer/postrenderframebuffer.frag b/shaders/framebuffer/postrenderframebuffer.frag new file mode 100644 index 0000000000..98905b9952 --- /dev/null +++ b/shaders/framebuffer/postrenderframebuffer.frag @@ -0,0 +1,34 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include "PowerScaling/powerScalingMath.hglsl" +#include <#{fragmentPath}> + +out vec4 _out_color_; + +void main() { + Fragment f = getFragment(); + _out_color_ = f.color; + gl_FragDepth = normalizeFloat(f.depth); +} diff --git a/shaders/framebuffer/raycastframebuffer.frag b/shaders/framebuffer/raycastframebuffer.frag index 9be8afe46d..0eab935531 100644 --- a/shaders/framebuffer/raycastframebuffer.frag +++ b/shaders/framebuffer/raycastframebuffer.frag @@ -28,11 +28,16 @@ uniform sampler2D exitColorTexture; uniform sampler2D exitDepthTexture; uniform sampler2DMS mainDepthTexture; +uniform bool insideRaycaster; +uniform vec3 cameraPosInRaycaster; + + #include "blending.glsl" #include "rand.glsl" #include "PowerScaling/powerScalingMath.hglsl" #include <#{fragmentPath}> + #for id, helperPath in helperPaths #include <#{helperPath}> #endfor @@ -68,10 +73,18 @@ void main() { float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0 - // fetch entry point from rendered fragment - Fragment f = getFragment(); - vec3 entryPos = f.color.xyz; - float entryDepth = f.depth; + vec3 entryPos; + float entryDepth; + + if (insideRaycaster) { + entryPos = cameraPosInRaycaster; + entryDepth = 0; + } else { + // fetch entry point from rendered fragment + Fragment f = getFragment(); + entryPos = f.color.xyz; + entryDepth = f.depth; + } vec3 position = entryPos; vec3 diff = exitPos - entryPos; @@ -99,7 +112,6 @@ void main() { } - finalColor = vec4(0.0); float currentDepth = 0.0; // todo: shorten depth if geometry is intersecting! float nextStepSize = stepSize#{id}(position, direction); @@ -112,7 +124,11 @@ void main() { int sampleIndex = 0; float opacityDecay = 1.0 / nAaSamples; - for (steps = 0; finalColor.a < ALPHA_LIMIT && steps < RAYCAST_MAX_STEPS; ++steps) { + vec3 accumulatedColor = vec3(0.0); + vec3 accumulatedAlpha = vec3(0.0); + + + for (steps = 0; (accumulatedAlpha.r < ALPHA_LIMIT || accumulatedAlpha.g < ALPHA_LIMIT || accumulatedAlpha.b < ALPHA_LIMIT) && steps < RAYCAST_MAX_STEPS; ++steps) { while (sampleIndex < nAaSamples && currentDepth + nextStepSize * jitterFactor > raycastDepths[sampleIndex]) { @@ -132,11 +148,13 @@ void main() { vec3 jitteredPosition = position + direction*jitteredStepSize; position += direction * currentStepSize; - vec4 raycasterContribution = sample#{id}(jitteredPosition, direction, finalColor, nextStepSize); + + sample#{id}(jitteredPosition, direction, accumulatedColor, accumulatedAlpha, nextStepSize); float sampleDistance = aaOpacity * (jitteredStepSize + previousJitterDistance); - blendStep(finalColor, raycasterContribution, sampleDistance); + //blendStep(finalColor, raycasterContribution, sampleDistance); + //finalColor previousJitterDistance = currentStepSize - jitteredStepSize; @@ -146,6 +164,8 @@ void main() { } + finalColor = vec4(accumulatedColor, (accumulatedAlpha.r + accumulatedAlpha.g + accumulatedAlpha.b) / 3); + finalColor.rgb /= finalColor.a; gl_FragDepth = normalizeFloat(entryDepth); } diff --git a/shaders/framebuffer/renderframebuffer.frag b/shaders/framebuffer/renderframebuffer.frag index 88540a28c9..98905b9952 100644 --- a/shaders/framebuffer/renderframebuffer.frag +++ b/shaders/framebuffer/renderframebuffer.frag @@ -22,6 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include "PowerScaling/powerScalingMath.hglsl" #include <#{fragmentPath}> out vec4 _out_color_; diff --git a/shaders/postRender.frag b/shaders/postRender.frag new file mode 100644 index 0000000000..d290bd70c7 --- /dev/null +++ b/shaders/postRender.frag @@ -0,0 +1,2 @@ +#version __CONTEXT__ +#include <#{rendererData.postFragmentRendererPath}> \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a9992e1af..1d7d1a7670 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/engine/downloadmanager.cpp ${OPENSPACE_BASE_DIR}/src/engine/logfactory.cpp ${OPENSPACE_BASE_DIR}/src/engine/moduleengine.cpp + ${OPENSPACE_BASE_DIR}/src/engine/moduleengine_lua.inl ${OPENSPACE_BASE_DIR}/src/engine/openspaceengine.cpp ${OPENSPACE_BASE_DIR}/src/engine/wrapper/sgctwindowwrapper.cpp ${OPENSPACE_BASE_DIR}/src/engine/wrapper/windowwrapper.cpp @@ -49,6 +50,9 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/network/networkengine.cpp ${OPENSPACE_BASE_DIR}/src/network/parallelconnection.cpp ${OPENSPACE_BASE_DIR}/src/network/parallelconnection_lua.inl + ${OPENSPACE_BASE_DIR}/src/performance/performancemeasurement.cpp + ${OPENSPACE_BASE_DIR}/src/performance/performancelayout.cpp + ${OPENSPACE_BASE_DIR}/src/performance/performancemanager.cpp ${OPENSPACE_BASE_DIR}/src/properties/matrixproperty.cpp ${OPENSPACE_BASE_DIR}/src/properties/optionproperty.cpp ${OPENSPACE_BASE_DIR}/src/properties/property.cpp @@ -118,6 +122,9 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/network/networkengine.h ${OPENSPACE_BASE_DIR}/include/openspace/network/parallelconnection.h ${OPENSPACE_BASE_DIR}/include/openspace/network/messagestructures.h + ${OPENSPACE_BASE_DIR}/include/openspace/performance/performancemeasurement.h + ${OPENSPACE_BASE_DIR}/include/openspace/performance/performancelayout.h + ${OPENSPACE_BASE_DIR}/include/openspace/performance/performancemanager.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/matrixproperty.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/numericalproperty.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/numericalproperty.inl diff --git a/src/engine/moduleengine.cpp b/src/engine/moduleengine.cpp index f78cdf6314..ed14d9a74e 100644 --- a/src/engine/moduleengine.cpp +++ b/src/engine/moduleengine.cpp @@ -31,6 +31,8 @@ #include +#include "moduleengine_lua.inl" + namespace { const std::string _loggerCat = "ModuleEngine"; } @@ -80,4 +82,19 @@ std::vector ModuleEngine::modules() const { return result; } +scripting::ScriptEngine::LuaLibrary ModuleEngine::luaLibrary() { + return { + "modules", + { + { + "isLoaded", + &luascriptfunctions::isLoaded, + "string", + "Checks whether a specific module is loaded" + } + } + + }; +} + } // namespace openspace diff --git a/src/engine/moduleengine_lua.inl b/src/engine/moduleengine_lua.inl new file mode 100644 index 0000000000..a0524891e0 --- /dev/null +++ b/src/engine/moduleengine_lua.inl @@ -0,0 +1,65 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +namespace openspace { +namespace luascriptfunctions { + +/** + * \ingroup LuaScripts + * isLoaded(string): + * Checks whether the passed OpenSpaceModule is loaded or not + */ +int isLoaded(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + + const int type = lua_type(L, -1); + if (type != LUA_TSTRING) + return luaL_error(L, "Expected argument of type 'string'"); + std::string moduleName = lua_tostring(L, -1); + + std::vector modules = OsEng.moduleEngine().modules(); + + auto it = std::find_if( + modules.begin(), + modules.end(), + [moduleName](OpenSpaceModule* module) { + return module->name() == moduleName; + } + ); + + if (it != modules.end()) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + + return 1; +} + +} // namespace luascriptfunctions +} // namespace openspace diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 7160ce2a55..28b5fb4777 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -123,13 +123,15 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, )) , _console(new LuaConsole) , _moduleEngine(new ModuleEngine) +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED , _gui(new gui::GUI) +#endif , _parallelConnection(new network::ParallelConnection) , _windowWrapper(std::move(windowWrapper)) , _globalPropertyNamespace(new properties::PropertyOwner) , _isMaster(false) , _runTime(0.0) - , _syncBuffer(new SyncBuffer(1024)) + , _syncBuffer(new SyncBuffer(4096)) { _interactionHandler->setPropertyOwner(_globalPropertyNamespace.get()); _globalPropertyNamespace->addPropertySubOwner(_interactionHandler.get()); @@ -147,7 +149,9 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, } OpenSpaceEngine::~OpenSpaceEngine() { +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED _gui->deinitializeGL(); +#endif _renderEngine->deinitialize(); _globalPropertyNamespace = nullptr; @@ -161,7 +165,9 @@ OpenSpaceEngine::~OpenSpaceEngine() { _commandlineParser = nullptr; _console = nullptr; _moduleEngine = nullptr; +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED _gui = nullptr; +#endif _syncBuffer = nullptr; } @@ -364,6 +370,7 @@ bool OpenSpaceEngine::initialize() { _scriptEngine->addLibrary(LuaConsole::luaLibrary()); _scriptEngine->addLibrary(gui::GUI::luaLibrary()); _scriptEngine->addLibrary(network::ParallelConnection::luaLibrary()); + _scriptEngine->addLibrary(ModuleEngine::luaLibrary()); #ifdef OPENSPACE_MODULE_ISWA_ENABLED _scriptEngine->addLibrary(IswaManager::luaLibrary()); @@ -417,8 +424,10 @@ bool OpenSpaceEngine::initialize() { // Load a light and a monospaced font loadFonts(); +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED LINFO("Initializing GUI"); _gui->initialize(); +#endif #ifdef OPENSPACE_MODULE_ISWA_ENABLED IswaManager::initialize(); @@ -659,6 +668,7 @@ void OpenSpaceEngine::configureLogging() { bool OpenSpaceEngine::initializeGL() { LINFO("Initializing Rendering Engine"); bool success = _renderEngine->initializeGL(); +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED LINFO("Initializing OnScreen GUI GL"); try { _gui->initializeGL(); @@ -666,6 +676,7 @@ bool OpenSpaceEngine::initializeGL() { catch (const ghoul::RuntimeError& e) { LERROR(e.what()); } +#endif LINFO("Finished initializing OpenGL"); return success; } @@ -707,15 +718,29 @@ void OpenSpaceEngine::postSynchronizationPreDraw() { _scriptEngine->postSynchronizationPreDraw(); _renderEngine->postSynchronizationPreDraw(); +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED if (_isMaster && _gui->isEnabled() && _windowWrapper->isRegularRendering()) { glm::vec2 mousePosition = _windowWrapper->mousePosition(); glm::ivec2 drawBufferResolution = _windowWrapper->currentDrawBufferResolution(); + glm::ivec2 windowSize = _windowWrapper->currentWindowSize(); uint32_t mouseButtons = _windowWrapper->mouseButtons(2); + + glm::vec2 windowBufferCorrectionFactor = glm::vec2( + static_cast(drawBufferResolution.x) / static_cast(windowSize.x), + static_cast(drawBufferResolution.y) / static_cast(windowSize.y) + ); double dt = _windowWrapper->averageDeltaTime(); - _gui->startFrame(static_cast(dt), glm::vec2(drawBufferResolution), mousePosition, mouseButtons); + _gui->startFrame( + static_cast(dt), + glm::vec2(drawBufferResolution), + windowBufferCorrectionFactor, + mousePosition, + mouseButtons + ); } +#endif // Testing this every frame has minimal impact on the performance --- abock // Debug build: 1-2 us ; Release build: <= 1 us @@ -740,8 +765,10 @@ void OpenSpaceEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 if (_isMaster && _windowWrapper->isRegularRendering()) { if (_console->isVisible()) _console->render(); +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED if (_gui->isEnabled()) _gui->endFrame(); +#endif } } @@ -751,11 +778,13 @@ void OpenSpaceEngine::postDraw() { void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction action) { if (_isMaster) { +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED if (_gui->isEnabled()) { bool isConsumed = _gui->keyCallback(key, mod, action); if (isConsumed) return; } +#endif if (key == _console->commandInputButton() && (action == KeyAction::Press || action == KeyAction::Repeat)) _console->toggleVisibility(); @@ -771,12 +800,13 @@ void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction actio void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier) { if (_isMaster) { +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED if (_gui->isEnabled()) { const bool isConsumed = _gui->charCallback(codepoint, modifier); if (isConsumed) return; } - +#endif if (_console->isVisible()) { _console->charCallback(codepoint, modifier); } @@ -785,12 +815,13 @@ void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier) void OpenSpaceEngine::mouseButtonCallback(MouseButton button, MouseAction action) { if (_isMaster) { +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED if (_gui->isEnabled()) { const bool isConsumed = _gui->mouseButtonCallback(button, action); if (isConsumed && action != MouseAction::Release) return; } - +#endif _interactionHandler->mouseButtonCallback(button, action); } } @@ -803,12 +834,13 @@ void OpenSpaceEngine::mousePositionCallback(double x, double y) { void OpenSpaceEngine::mouseScrollWheelCallback(double pos) { if (_isMaster) { +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED if (_gui->isEnabled()) { const bool isConsumed = _gui->mouseWheelCallback(pos); if (isConsumed) return; } - +#endif _interactionHandler->mouseScrollWheelCallback(pos); } } @@ -887,10 +919,12 @@ LuaConsole& OpenSpaceEngine::console() { return *_console; } +#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED gui::GUI& OpenSpaceEngine::gui() { ghoul_assert(_gui, "GUI must not be nullptr"); return *_gui; } +#endif network::ParallelConnection& OpenSpaceEngine::parallelConnection() { ghoul_assert(_parallelConnection, "ParallelConnection must not be nullptr"); diff --git a/src/performance/performancelayout.cpp b/src/performance/performancelayout.cpp new file mode 100644 index 0000000000..5856f9f7e4 --- /dev/null +++ b/src/performance/performancelayout.cpp @@ -0,0 +1,50 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +namespace openspace { +namespace performance { + +PerformanceLayout::PerformanceLayout() + : nScaleGraphEntries(0) + , nFunctionEntries(0) +{ + std::memset( + sceneGraphEntries, + 0, + MaxValues * sizeof(SceneGraphPerformanceLayout) + ); + + std::memset( + functionEntries, + 0, + MaxValues * sizeof(FunctionPerformanceLayout) + ); +} + +} // namespace performance +} // namespace openspace diff --git a/src/performance/performancemanager.cpp b/src/performance/performancemanager.cpp new file mode 100644 index 0000000000..91731768a0 --- /dev/null +++ b/src/performance/performancemanager.cpp @@ -0,0 +1,167 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +#include +#include + +namespace { + const std::string _loggerCat = "PerformanceManager"; +} + +namespace openspace { +namespace performance { + +const std::string PerformanceManager::PerformanceMeasurementSharedData = + "OpenSpacePerformanceMeasurementSharedData"; + +PerformanceManager::PerformanceManager() + : _performanceMemory(nullptr) +{ + // Compute the total size + const int totalSize = sizeof(PerformanceLayout); + LINFO("Create shared memory of " << totalSize << " bytes"); + + try { + ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); + } + catch (const ghoul::SharedMemory::SharedMemoryError& e) { + LINFOC(e.component, e.what()); + } + + ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize); + _performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData); + void* ptr = _performanceMemory->memory(); + + // Using the placement-new to create a PerformanceLayout in the shared memory + PerformanceLayout* layout = new (ptr) PerformanceLayout; +} + +PerformanceManager::~PerformanceManager() { + if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData)) + ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); +} + +void PerformanceManager::resetPerformanceMeasurements() { + // Using the placement-new to create a PerformanceLayout in the shared memory + _performanceMemory->acquireLock(); + void* ptr = _performanceMemory->memory(); + new (ptr) PerformanceLayout; + _performanceMemory->releaseLock(); + + individualPerformanceLocations.clear(); +} + +bool PerformanceManager::isMeasuringPerformance() const { + return _doPerformanceMeasurements; +} + +void PerformanceManager::storeIndividualPerformanceMeasurement + (std::string identifier, long long microseconds) +{ + void* ptr = _performanceMemory->memory(); + PerformanceLayout* layout = reinterpret_cast(ptr); + _performanceMemory->acquireLock(); + + auto it = individualPerformanceLocations.find(identifier); + PerformanceLayout::FunctionPerformanceLayout* p = nullptr; + if (it == individualPerformanceLocations.end()) { + p = &(layout->functionEntries[layout->nFunctionEntries]); + individualPerformanceLocations[identifier] = layout->nFunctionEntries; + ++(layout->nFunctionEntries); + } + else { + p = &(layout->functionEntries[it->second]); + } +#ifdef _MSC_VER + strcpy_s(p->name, identifier.length() + 1, identifier.c_str()); +#else + strcpy(p->name, identifier.c_str()); +#endif + + std::rotate( + std::begin(p->time), + std::next(std::begin(p->time)), + std::end(p->time) + ); + p->time[PerformanceLayout::NumberValues - 1] = + static_cast(microseconds); + + _performanceMemory->releaseLock(); +} + +void PerformanceManager::storeScenePerformanceMeasurements( + const std::vector& sceneNodes) +{ + using namespace performance; + + void* ptr = _performanceMemory->memory(); + PerformanceLayout* layout = reinterpret_cast(ptr); + _performanceMemory->acquireLock(); + + int nNodes = static_cast(sceneNodes.size()); + layout->nScaleGraphEntries = nNodes; + for (int i = 0; i < nNodes; ++i) { + SceneGraphNode* node = sceneNodes[i]; + + memset(layout->sceneGraphEntries[i].name, 0, PerformanceLayout::LengthName); +#ifdef _MSC_VER + strcpy_s(layout->sceneGraphEntries[i].name, node->name().length() + 1, node->name().c_str()); +#else + strcpy(layout->sceneGraphEntries[i].name, node->name().c_str()); +#endif + + SceneGraphNode::PerformanceRecord r = node->performanceRecord(); + PerformanceLayout::SceneGraphPerformanceLayout& entry = layout->sceneGraphEntries[i]; + + std::rotate( + std::begin(entry.renderTime), + std::next(std::begin(entry.renderTime)), + std::end(entry.renderTime) + ); + entry.renderTime[PerformanceLayout::NumberValues - 1] = r.renderTime / 1000.f; + + std::rotate( + std::begin(entry.updateEphemeris), + std::next(std::begin(entry.updateEphemeris)), + std::end(entry.updateEphemeris) + ); + entry.updateEphemeris[PerformanceLayout::NumberValues - 1] = r.updateTimeEphemeris / 1000.f; + + std::rotate( + std::begin(entry.updateRenderable), + std::next(std::begin(entry.updateRenderable)), + std::end(entry.updateRenderable) + ); + entry.updateRenderable[PerformanceLayout::NumberValues - 1] = r.updateTimeRenderable / 1000.f; + } + _performanceMemory->releaseLock(); +} + +} // namespace performance +} // namespace openspace diff --git a/src/performance/performancemeasurement.cpp b/src/performance/performancemeasurement.cpp new file mode 100644 index 0000000000..a62a6d5d4e --- /dev/null +++ b/src/performance/performancemeasurement.cpp @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#include + +#include + +namespace openspace { +namespace performance { + +PerformanceMeasurement::PerformanceMeasurement(std::string identifier, + performance::PerformanceManager* manager) + : _identifier(std::move(identifier)) + , _manager(manager) +{ + if (_manager) { + glFinish(); + + _startTime = std::chrono::high_resolution_clock::now(); + } +} + +PerformanceMeasurement::~PerformanceMeasurement() { + auto endTime = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast( + endTime - _startTime).count(); + + if (_manager) { + _manager->storeIndividualPerformanceMeasurement(std::move(_identifier), duration); + } +} + + +} // namespace performance +} // namespace openspace diff --git a/src/rendering/abufferrenderer.cpp b/src/rendering/abufferrenderer.cpp index 5be6bb75b1..2620cb2a86 100644 --- a/src/rendering/abufferrenderer.cpp +++ b/src/rendering/abufferrenderer.cpp @@ -35,9 +35,12 @@ #include +#include #include #include + + #include #include @@ -45,8 +48,9 @@ namespace { const std::string _loggerCat = "ABufferRenderer"; const std::string BoundsFragmentShaderPath = "${SHADERS}/abuffer/boundsabuffer.frag"; const std::string RenderFragmentShaderPath = "${SHADERS}/abuffer/renderabuffer.frag"; + const std::string PostRenderFragmentShaderPath = "${SHADERS}/abuffer/postrenderabuffer.frag"; const int MaxRaycasters = 32; - const int MaxLayers = 16; + const int MaxLayers = 32; const int MaxAverageLayers = 8; } @@ -97,26 +101,42 @@ void ABufferRenderer::initialize() { glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); glGenBuffers(1, &_fragmentBuffer); glGenTextures(1, &_fragmentTexture); - - _nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); - if (_nAaSamples == 0) { - _nAaSamples = 1; - } - if (_nAaSamples > 8) { - LERROR("ABuffer renderer does not support more than 8 MSAA samples."); - _nAaSamples = 8; - } + + glGenTextures(1, &_mainColorTexture); + glGenTextures(1, &_mainDepthTexture); + glGenFramebuffers(1, &_mainFramebuffer); + + GLint defaultFbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); + + updateResolution(); updateRendererData(); updateRaycastData(); updateResolveDictionary(); + glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Main framebuffer is not complete"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + + try { + ghoul::Dictionary dict; + dict.setValue("resolveData", _resolveDictionary); + dict.setValue("rendererData", _rendererData); + _resolveProgram = ghoul::opengl::ProgramObject::Build("ABuffer Resolve", "${SHADERS}/abuffer/resolveabuffer.vert", "${SHADERS}/abuffer/resolveabuffer.frag", - _resolveDictionary); + dict); } catch (ghoul::RuntimeError e) { LERROR(e.message); } @@ -171,7 +191,10 @@ void ABufferRenderer::update() { if (_dirtyResolveDictionary) { updateResolveDictionary(); - _resolveProgram->setDictionary(_resolveDictionary); + ghoul::Dictionary dict; + dict.setValue("resolveData", _resolveDictionary); + dict.setValue("rendererData", _rendererData); + _resolveProgram->setDictionary(dict); } // If the resolve dictionary changed (or a file changed on disk) @@ -201,6 +224,23 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement if (_scene == nullptr) return; if (_camera == nullptr) return; + + + _mainColorTextureUnit = std::make_unique(); + _mainColorTextureUnit->activate(); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + + _mainDepthTextureUnit = std::make_unique(); + _mainDepthTextureUnit->activate(); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + GLint defaultFbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); + glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // Reset clear(); glEnable(GL_DEPTH_TEST); @@ -218,6 +258,12 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement RendererTasks tasks; _scene->render(data, tasks); + _rendererTasks = std::make_unique(tasks); + _renderData = std::make_unique(data); + _blackoutFactor = blackoutFactor; + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + // Step 2: Perform raycasting tasks requested by the scene for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { @@ -239,33 +285,65 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement // Step 3: Resolve the buffer _resolveProgram->activate(); - // 3a: Perform the pre-raycast step for all raycaster tasks. - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { - VolumeRaycaster* raycaster = raycasterTask.raycaster; - auto raycastData = _raycastData.find(raycaster); - if (raycastData != _raycastData.end()) { - raycaster->preRaycast(raycastData->second, *_resolveProgram.get()); + // TEMPORARY GAMMA CORRECTION. + + float gamma = 1.0; + glm::vec3 cameraPos = data.camera.position().vec3(); + float maxComponent = std::max(std::max(std::abs(cameraPos.x), std::abs(cameraPos.y)), std::abs(cameraPos.z)); + float logDistance = std::log(glm::length(cameraPos / maxComponent) * maxComponent) / std::log(10); + + float minLogDist = 15; + float maxLogDist = 20; + + float t = (logDistance - minLogDist) / (maxLogDist - minLogDist); + t = glm::clamp(t, 0.0f, 1.0f); + gamma = 1.0 * (1 - t) + 2.2 * t; + + _resolveProgram->setUniform("gamma", gamma); + + // END TEMPORARY GAMMA CORRECTION. + + preRaycast(*_resolveProgram); + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + postRaycast(*_resolveProgram); + + _resolveProgram->deactivate(); + + _scene->postRender(data); + + _mainColorTextureUnit = nullptr; + _mainDepthTextureUnit = nullptr; +} + + +void ABufferRenderer::preRaycast(ghoul::opengl::ProgramObject& program) { + + program.setUniform("mainColorTexture", _mainColorTextureUnit->unitNumber()); + program.setUniform("mainDepthTexture", _mainDepthTextureUnit->unitNumber()); + + for (const auto& raycastData : _raycastData) { + raycastData.first->preRaycast(raycastData.second, program); + + glm::vec3 localCameraPosition; + bool cameraIsInside = raycastData.first->cameraIsInside(*_renderData, localCameraPosition); + int uniformIndex = raycastData.second.id + 1; // uniforms are indexed from 1 (not from 0) + program.setUniform("insideRaycaster" + std::to_string(uniformIndex), cameraIsInside); + if (cameraIsInside) { + program.setUniform("cameraPosInRaycaster" + std::to_string(uniformIndex), localCameraPosition); } } // 3b: Set "global" uniforms, and start the resolve pass. - _resolveProgram->setUniform("blackoutFactor", blackoutFactor); - _resolveProgram->setUniform("nAaSamples", _nAaSamples); - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - - // 3c: Perform the post-raycast step for all raycaster tasks. - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { - VolumeRaycaster* raycaster = raycasterTask.raycaster; - auto raycastData = _raycastData.find(raycaster); - if (raycastData != _raycastData.end()) { - raycaster->postRaycast(raycastData->second, *_resolveProgram.get()); - } - } - - _resolveProgram->deactivate(); + program.setUniform("blackoutFactor", _blackoutFactor); + program.setUniform("nAaSamples", _nAaSamples); } +void ABufferRenderer::postRaycast(ghoul::opengl::ProgramObject& program) { + for (const auto& raycastData : _raycastData) { + raycastData.first->postRaycast(raycastData.second, program); + } +} void ABufferRenderer::setScene(Scene* scene) { _scene = scene; @@ -282,6 +360,18 @@ void ABufferRenderer::setResolution(glm::ivec2 res) { } } +void ABufferRenderer::setNAaSamples(int nAaSamples) { + _nAaSamples = nAaSamples; + if (_nAaSamples == 0) { + _nAaSamples = 1; + } + if (_nAaSamples > 8) { + LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); + _nAaSamples = 8; + } + _dirtyResolution = true; +} + void ABufferRenderer::clear() { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); @@ -293,6 +383,7 @@ void ABufferRenderer::clear() { glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); + } void ABufferRenderer::updateResolution() { @@ -320,6 +411,25 @@ void ABufferRenderer::updateResolution() { glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + true); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_DEPTH_COMPONENT32F, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + true); + _dirtyResolution = false; } @@ -353,11 +463,14 @@ void ABufferRenderer::updateResolveDictionary() { } dict.setValue("helperPaths", helperPathsDict); - dict.setValue("rendererData", _rendererData); dict.setValue("raycastingEnabled", _raycastData.size() > 0); + dict.setValue("storeSorted", true); dict.setValue("nRaycasters", static_cast(_raycastData.size())); _resolveDictionary = dict; + + OsEng.renderEngine().setResolveData(dict); + _dirtyResolveDictionary = false; } @@ -434,6 +547,7 @@ void ABufferRenderer::updateRendererData() { dict.setValue("windowWidth", _resolution.x); dict.setValue("windowHeight", _resolution.y); dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); + dict.setValue("postFragmentRendererPath", std::string(PostRenderFragmentShaderPath)); dict.setValue("maxLayers", MaxLayers); dict.setValue("maxTotalFragments", MaxLayers * _resolution.x * _resolution.y); diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index b2e6d7f809..bd6b920987 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include #include #include @@ -44,6 +46,7 @@ namespace { const std::string ExitFragmentShaderPath = "${SHADERS}/framebuffer/exitframebuffer.frag"; const std::string RaycastFragmentShaderPath = "${SHADERS}/framebuffer/raycastframebuffer.frag"; const std::string RenderFragmentShaderPath = "${SHADERS}/framebuffer/renderframebuffer.frag"; + const std::string PostRenderFragmentShaderPath = "${SHADERS}/framebuffer/postrenderframebuffer.frag"; } namespace openspace { @@ -122,14 +125,7 @@ void FramebufferRenderer::initialize() { OsEng.renderEngine().raycasterManager().addListener(*this); - _nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); - if (_nAaSamples == 0) { - _nAaSamples = 1; - } - if (_nAaSamples > 8) { - LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); - _nAaSamples = 8; - } + } void FramebufferRenderer::deinitialize() { @@ -156,6 +152,8 @@ void FramebufferRenderer::raycastersChanged(VolumeRaycaster& raycaster, bool att } void FramebufferRenderer::update() { + PerfMeasure("FramebufferRenderer::update"); + if (_dirtyResolution) { updateResolution(); } @@ -193,10 +191,23 @@ void FramebufferRenderer::update() { } } } + + for (auto &program : _insideRaycastPrograms) { + if (program.second->isDirty()) { + try { + program.second->rebuildFromFile(); + } + catch (ghoul::RuntimeError e) { + LERROR(e.message); + } + } + } } void FramebufferRenderer::updateResolution() { - int nSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); + int nSamples = _nAaSamples; + PerfMeasure("FramebufferRenderer::updateResolution"); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); glTexImage2DMultisample( @@ -246,12 +257,17 @@ void FramebufferRenderer::updateResolution() { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + _dirtyResolution = false; } void FramebufferRenderer::updateRaycastData() { + PerfMeasure("FramebufferRenderer::updateRaycastData"); + _raycastData.clear(); _exitPrograms.clear(); _raycastPrograms.clear(); + _insideRaycastPrograms.clear(); const std::vector& raycasters = OsEng.renderEngine().raycasterManager().raycasters(); int nextId = 0; @@ -288,17 +304,26 @@ void FramebufferRenderer::updateRaycastData() { } catch (ghoul::RuntimeError e) { LERROR(e.message); } + try { + _insideRaycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( + "Volume " + std::to_string(data.id) + " inside raycast", + "${SHADERS}/framebuffer/resolveframebuffer.vert", + RaycastFragmentShaderPath, dict); + } + catch (ghoul::RuntimeError e) { + LERROR(e.message); + } } _dirtyRaycastData = false; } void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) { - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - - if (_scene == nullptr) return; - if (_camera == nullptr) return; + PerfMeasure("FramebufferRenderer::render"); + + if (!_scene) + return; + if (!_camera) + return; glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); @@ -332,9 +357,25 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - ghoul::opengl::ProgramObject* raycastProgram = _raycastPrograms[raycaster].get(); + + ghoul::opengl::ProgramObject* insideRaycastProgram = _raycastPrograms[raycaster].get(); + + glm::vec3 cameraPosition; + bool cameraIsInside = raycaster->cameraIsInside(raycasterTask.renderData, cameraPosition); + ghoul::opengl::ProgramObject* raycastProgram = nullptr; + + if (cameraIsInside) { + raycastProgram = _insideRaycastPrograms[raycaster].get(); + } else { + raycastProgram = _raycastPrograms[raycaster].get(); + } + if (raycastProgram) { raycastProgram->activate(); + + raycastProgram->setUniform("insideRaycaster", cameraIsInside); + raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); + raycaster->preRaycast(_raycastData[raycaster], *raycastProgram); ghoul::opengl::TextureUnit exitColorTextureUnit; @@ -354,12 +395,21 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure raycastProgram->setUniform("nAaSamples", _nAaSamples); + glDisable(GL_DEPTH_TEST); glDepthMask(false); - raycaster->renderEntryPoints(raycasterTask.renderData, *raycastProgram); + if (cameraIsInside) { + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + } else { + raycaster->renderEntryPoints(raycasterTask.renderData, *raycastProgram); + } glDepthMask(true); glEnable(GL_DEPTH_TEST); + + raycaster->postRaycast(_raycastData[raycaster], *raycastProgram); raycastProgram->deactivate(); } else { @@ -379,6 +429,7 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure _resolveProgram->setUniform("nAaSamples", _nAaSamples); glBindVertexArray(_screenQuad); glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); _resolveProgram->deactivate(); } @@ -393,11 +444,27 @@ void FramebufferRenderer::setCamera(Camera* camera) { void FramebufferRenderer::setResolution(glm::ivec2 res) { _resolution = res; + _dirtyResolution = true; +} + +void FramebufferRenderer::setNAaSamples(int nAaSamples) { + _nAaSamples = nAaSamples; + if (_nAaSamples == 0) { + _nAaSamples = 1; + } + if (_nAaSamples > 8) { + LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); + _nAaSamples = 8; + } + _dirtyResolution = true; } void FramebufferRenderer::updateRendererData() { + PerfMeasure("FramebufferRenderer::updateRendererData"); + ghoul::Dictionary dict; - dict.setValue("fragmentRendererPath", RenderFragmentShaderPath); + dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); + dict.setValue("postFragmentRendererPath", std::string(PostRenderFragmentShaderPath)); dict.setValue("windowWidth", _resolution.x); dict.setValue("windowHeight", _resolution.y); diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 0f7f167c2a..22883a98e8 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -122,6 +122,10 @@ void Renderable::render(const RenderData& data) { } +void Renderable::postRender(const RenderData& data) +{ +} + void Renderable::setPscUniforms( ghoul::opengl::ProgramObject& program, const Camera& camera, diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index aecc8bf4e5..ded090b893 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -36,6 +36,8 @@ #include #include +#include + #include #include #include @@ -58,7 +60,6 @@ #include #include - #include #include #ifdef GHOUL_USE_DEVIL @@ -96,14 +97,12 @@ namespace { std::chrono::seconds ScreenLogTimeToLive(15); const std::string DefaultRenderingMethod = "ABuffer"; const std::string RenderFsPath = "${SHADERS}/render.frag"; + const std::string PostRenderFsPath = "${SHADERS}/postrender.frag"; } namespace openspace { -const std::string RenderEngine::PerformanceMeasurementSharedData = - "OpenSpacePerformanceMeasurementSharedData"; - const std::string RenderEngine::KeyFontMono = "Mono"; const std::string RenderEngine::KeyFontLight = "Light"; @@ -112,12 +111,11 @@ RenderEngine::RenderEngine() , _sceneGraph(nullptr) , _renderer(nullptr) , _rendererImplementation(RendererImplementation::Invalid) + , _performanceManager(nullptr) , _log(nullptr) , _showInfo(true) , _showLog(true) , _takeScreenshot(false) - , _doPerformanceMeasurements(false) - , _performanceMemory(nullptr) , _globalBlackOutFactor(1.f) , _fadeDuration(2.f) , _currentFadeTime(0.f) @@ -136,11 +134,8 @@ RenderEngine::~RenderEngine() { _sceneGraph = nullptr; delete _mainCamera; - delete _performanceMemory; delete _raycasterManager; - if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData)) - ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); } bool RenderEngine::deinitialize() { @@ -190,6 +185,7 @@ bool RenderEngine::initialize() { } _raycasterManager = new RaycasterManager(); + _nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); LINFO("Seting renderer from string: " << renderingMethod); setRendererFromString(renderingMethod); @@ -228,7 +224,6 @@ bool RenderEngine::initializeGL() { // development OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f); - try { const float fontSizeTime = 15.f; _fontDate = OsEng.fontManager().font(KeyFontMono, fontSizeTime); @@ -364,15 +359,20 @@ void RenderEngine::postSynchronizationPreDraw() { Time::ref().currentTime(), Time::ref().timeJumped(), Time::ref().deltaTime(), - _doPerformanceMeasurements + _performanceManager != nullptr }); _sceneGraph->evaluate(_mainCamera); _renderer->update(); for (auto program : _programs) { - if (program->isDirty()) { - program->rebuildFromFile(); + try { + if (program->isDirty()) { + program->rebuildFromFile(); + } + } + catch (const ghoul::opengl::ShaderObject::ShaderCompileError& e) { + LERRORC(e.component, e.what()); } } @@ -393,7 +393,7 @@ void RenderEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 &vi if (!(OsEng.isMaster() && _disableMasterRendering)) { - _renderer->render(_globalBlackOutFactor, _doPerformanceMeasurements); + _renderer->render(_globalBlackOutFactor, _performanceManager != nullptr); } // Print some useful information on the master viewport @@ -420,8 +420,8 @@ void RenderEngine::postDraw() { _takeScreenshot = false; } - if (_doPerformanceMeasurements) - storePerformanceMeasurements(); + if (_performanceManager) + _performanceManager->storeScenePerformanceMeasurements(scene()->allSceneGraphNodes()); } void RenderEngine::takeScreenshot() { @@ -502,7 +502,8 @@ std::unique_ptr RenderEngine::buildRenderProgram( std::string name, std::string vsPath, std::string fsPath, - const ghoul::Dictionary& data) { + const ghoul::Dictionary& data, + RenderEngine::RenderProgramType type) { ghoul::Dictionary dict = data; @@ -513,10 +514,16 @@ std::unique_ptr RenderEngine::buildRenderProgram( // instead of a void main() setting glFragColor, glFragDepth, etc. dict.setValue("fragmentPath", fsPath); + if (type == RenderEngine::RenderProgramType::Post) { + dict.setValue("resolveData", _resolveData); + } + + std::string path = (type == RenderEngine::RenderProgramType::Post) ? PostRenderFsPath : RenderFsPath; + std::unique_ptr program = ghoul::opengl::ProgramObject::Build( name, vsPath, - RenderFsPath, + path, dict); if (program) { @@ -533,20 +540,27 @@ std::unique_ptr RenderEngine::buildRenderProgram( std::string vsPath, std::string fsPath, std::string csPath, - const ghoul::Dictionary& data) { + const ghoul::Dictionary& data, + RenderEngine::RenderProgramType type) { ghoul::Dictionary dict = data; dict.setValue("rendererData", _rendererData); + if (type == RenderEngine::RenderProgramType::Post) { + dict.setValue("resolveData", _resolveData); + } + // parameterize the main fragment shader program with specific contents. // fsPath should point to a shader file defining a Fragment getFragment() function // instead of a void main() setting glFragColor, glFragDepth, etc. dict.setValue("fragmentPath", fsPath); + std::string path = (type == RenderEngine::RenderProgramType::Post) ? PostRenderFsPath : RenderFsPath; + std::unique_ptr program = ghoul::opengl::ProgramObject::Build( name, vsPath, - RenderFsPath, + path, csPath, dict); @@ -557,6 +571,9 @@ std::unique_ptr RenderEngine::buildRenderProgram( } void RenderEngine::removeRenderProgram(const std::unique_ptr& program) { + if (!program) + return; + ghoul::opengl::ProgramObject* ptr = program.get(); auto it = std::find( _programs.begin(), @@ -583,6 +600,37 @@ void RenderEngine::setRendererData(const ghoul::Dictionary& data) { } } + +/** +* Set resolve data +* Called from the renderer, whenever it needs to update +* the dictionary of all post rendering programs. +*/ +void RenderEngine::setResolveData(const ghoul::Dictionary& data) { + _resolveData = data; + for (auto program : _programs) { + ghoul::Dictionary dict = program->dictionary(); + dict.setValue("resolveData", _resolveData); + program->setDictionary(dict); + } +} + +/** +* Set raycasting uniforms on the program object, and setup raycasting. +*/ +void RenderEngine::preRaycast(ghoul::opengl::ProgramObject& programObject) { + _renderer->preRaycast(programObject); +} + +/** +* Tear down raycasting for the specified program object. +*/ +void RenderEngine::postRaycast(ghoul::opengl::ProgramObject& programObject) { + _renderer->postRaycast(programObject); +} + + + /** * Set renderer */ @@ -595,11 +643,20 @@ void RenderEngine::setRenderer(std::unique_ptr renderer) { _renderer = std::move(renderer); _renderer->setResolution(res); + _renderer->setNAaSamples(_nAaSamples); _renderer->initialize(); _renderer->setCamera(_mainCamera); _renderer->setScene(_sceneGraph); } + +void RenderEngine::setNAaSamples(int nAaSamples) { + _nAaSamples = nAaSamples; + if (_renderer) { + _renderer->setNAaSamples(_nAaSamples); + } +} + scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() { return { "", @@ -616,6 +673,12 @@ scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() { "string", "Sets the renderer (ABuffer or FrameBuffer)" }, + { + "setNAaSamples", + &luascriptfunctions::setNAaSamples, + "int", + "Sets the number of anti-aliasing (msaa) samples" + }, { "showRenderInformation", &luascriptfunctions::showRenderInformation, @@ -660,101 +723,20 @@ scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() { } void RenderEngine::setPerformanceMeasurements(bool performanceMeasurements) { - _doPerformanceMeasurements = performanceMeasurements; + if (performanceMeasurements) { + if (!_performanceManager) + _performanceManager = std::make_unique(); + } + else + _performanceManager = nullptr; } bool RenderEngine::doesPerformanceMeasurements() const { - return _doPerformanceMeasurements; + return _performanceManager != nullptr; } -void RenderEngine::storePerformanceMeasurements() { - const int8_t Version = 0; - const int nValues = 250; - const int lengthName = 256; - const int maxValues = 256; - - struct PerformanceLayout { - int8_t version; - int32_t nValuesPerEntry; - int32_t nEntries; - int32_t maxNameLength; - int32_t maxEntries; - - struct PerformanceLayoutEntry { - char name[lengthName]; - float renderTime[nValues]; - float updateRenderable[nValues]; - float updateEphemeris[nValues]; - - int32_t currentRenderTime; - int32_t currentUpdateRenderable; - int32_t currentUpdateEphemeris; - }; - - PerformanceLayoutEntry entries[maxValues]; - }; - - const int nNodes = static_cast(scene()->allSceneGraphNodes().size()); - if (!_performanceMemory) { - - // Compute the total size - const int totalSize = sizeof(int8_t) + 4 * sizeof(int32_t) + - maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry); - LINFO("Create shared memory of " << totalSize << " bytes"); - - try { - ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); - } - catch (const ghoul::SharedMemory::SharedMemoryError& e) { - LINFOC(e.component, e.what()); - } - - ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize); - _performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData); - - void* ptr = _performanceMemory->memory(); - PerformanceLayout* layout = reinterpret_cast(ptr); - layout->version = Version; - layout->nValuesPerEntry = nValues; - layout->nEntries = nNodes; - layout->maxNameLength = lengthName; - layout->maxEntries = maxValues; - - memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry)); - - for (int i = 0; i < nNodes; ++i) { - SceneGraphNode* node = scene()->allSceneGraphNodes()[i]; - - memset(layout->entries[i].name, 0, lengthName); -#ifdef _MSC_VER - strcpy_s(layout->entries[i].name, node->name().length() + 1, node->name().c_str()); -#else - strcpy(layout->entries[i].name, node->name().c_str()); -#endif - - layout->entries[i].currentRenderTime = 0; - layout->entries[i].currentUpdateRenderable = 0; - layout->entries[i].currentUpdateEphemeris = 0; - } - } - - void* ptr = _performanceMemory->memory(); - PerformanceLayout* layout = reinterpret_cast(ptr); - _performanceMemory->acquireLock(); - for (int i = 0; i < nNodes; ++i) { - SceneGraphNode* node = scene()->allSceneGraphNodes()[i]; - SceneGraphNode::PerformanceRecord r = node->performanceRecord(); - PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; - - entry.renderTime[entry.currentRenderTime] = r.renderTime / 1000.f; - entry.updateEphemeris[entry.currentUpdateEphemeris] = r.updateTimeEphemeris / 1000.f; - entry.updateRenderable[entry.currentUpdateRenderable] = r.updateTimeRenderable / 1000.f; - - entry.currentRenderTime = (entry.currentRenderTime + 1) % nValues; - entry.currentUpdateEphemeris = (entry.currentUpdateEphemeris + 1) % nValues; - entry.currentUpdateRenderable = (entry.currentUpdateRenderable + 1) % nValues; - } - _performanceMemory->releaseLock(); +performance::PerformanceManager* RenderEngine::performanceManager() { + return _performanceManager.get(); } // This method is temporary and will be removed once the scalegraph is in effect ---abock diff --git a/src/rendering/renderengine_lua.inl b/src/rendering/renderengine_lua.inl index 087df65e83..5e3937aeb6 100644 --- a/src/rendering/renderengine_lua.inl +++ b/src/rendering/renderengine_lua.inl @@ -26,18 +26,6 @@ namespace openspace { namespace luascriptfunctions { -/** -int changeCoordinateSystem(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 1) - return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); - - std::string newCenter = std::string(lua_tostring(L, -1)); - OsEng.renderEngine()->changeViewPoint(newCenter); - return 1; -} -*/ - /** * \ingroup LuaScripts * takeScreenshot(): @@ -63,12 +51,29 @@ int setRenderer(lua_State* L) { const int type = lua_type(L, -1); if (type != LUA_TSTRING) - return luaL_error(L, "Expected argument of type 'bool'"); + return luaL_error(L, "Expected argument of type 'string'"); std::string r = lua_tostring(L, -1); OsEng.renderEngine().setRendererFromString(r); return 0; } +/** +* \ingroup LuaScripts +* setNAaSamples(int): +* set the number of anti-aliasing samples (msaa) +*/ +int setNAaSamples(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + + double t = luaL_checknumber(L, -1); + + OsEng.renderEngine().setNAaSamples(static_cast(t)); + return 0; +} + + /** * \ingroup LuaScripts * visualizeABuffer(bool): diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 84e65718c6..8230b2087c 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -153,6 +153,12 @@ void Scene::render(const RenderData& data, RendererTasks& tasks) { } } +void Scene::postRender(const RenderData& data) { + for (SceneGraphNode* node : _graph.nodes()) { + node->postRender(data); + } +} + void Scene::scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath) { _sceneGraphToLoad = sceneDescriptionFilePath; } diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index c60560174c..b1499ef446 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -269,6 +269,18 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) { // child->render(newData); } +void SceneGraphNode::postRender(const RenderData& data) { + const psc thisPosition = worldPosition(); + RenderData newData = { data.camera, thisPosition, data.doPerformanceMeasurement }; + + _performanceRecord.renderTime = 0; + if (_renderableVisible && _renderable->isVisible() && _renderable->isReady() && _renderable->isEnabled()) { + _renderable->postRender(newData); + } +} + + + // not used anymore @AA //void SceneGraphNode::addNode(SceneGraphNode* child) diff --git a/src/util/transformationmanager.cpp b/src/util/transformationmanager.cpp index c624915fed..c9818205a8 100644 --- a/src/util/transformationmanager.cpp +++ b/src/util/transformationmanager.cpp @@ -45,7 +45,9 @@ } TransformationManager::~TransformationManager(){ +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED _kameleon = nullptr; +#endif } glm::dmat3 TransformationManager::kameleonTransformationMatrix( std::string from, @@ -79,6 +81,7 @@ std::string to, double ephemerisTime) const { +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED auto fromit = _dipoleFrames.find(from); auto toit = _dipoleFrames.find(to); @@ -110,7 +113,6 @@ return SpiceManager::ref().frameTransformationMatrix(from, to, ephemerisTime); } -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED if(fromKameleon && toKameleon){ return kameleonTransformationMatrix(from, to, ephemerisTime);