Added shadow and ring components to Globebrowsing and shaders for shadows.

This commit is contained in:
Jonathas Costa
2019-10-08 16:38:12 -04:00
parent cbc8845ddf
commit ab076fd3d2
13 changed files with 1885 additions and 32 deletions

View File

@@ -9,9 +9,9 @@ asset.onInitialize(function ()
openspace.globebrowsing.goToGeo("Earth", 58.5877, 16.1924, 20000000)
openspace.markInterestingNodes({ "Earth", "Mars", "Moon", "Sun" })
openspace.markInterestingNodes({ "Saturn", "Mars", "Moon", "Sun", "Saturn" })
end)
asset.onDeinitialize(function ()
openspace.removeInterestingNodes({ "Earth", "Mars", "Moon", "Sun" })
openspace.removeInterestingNodes({ "Earth", "Mars", "Moon", "Sun", "Saturn" })
end)

View File

@@ -34,6 +34,15 @@ local Saturn = {
Enabled = true
}
}
},
Rings = {
Texture = textures .. "/saturn_rings.png",
Size = 140445000,
Offset = { 74500 / 140445.100671159, 1.0 }, -- min / max extend
Shadows = {
Enabled = true,
DistanceFraction = 50.0
}
}
},
Tag = { "planet_solarSystem", "planet_giants" },
@@ -42,21 +51,22 @@ local Saturn = {
}
}
local SaturnRings = {
Identifier = "SaturnRings",
Parent = Saturn.Identifier,
Renderable = {
Type = "RenderableRings",
Texture = textures .. "/saturn_rings.png",
Size = 140445000,
Offset = { 74500 / 140445.100671159, 1.0 } -- min / max extend
},
GUI = {
Name = "Saturn Rings",
Path = "/Solar System/Planets/Saturn"
}
}
-- local SaturnRings = {
-- Identifier = "SaturnRings",
-- Parent = Saturn.Identifier,
-- Renderable = {
-- Type = "RenderableRings",
-- Texture = textures .. "/saturn_rings.png",
-- Size = 140445000,
-- Offset = { 74500 / 140445.100671159, 1.0 } -- min / max extend
-- },
-- GUI = {
-- Name = "Saturn Rings",
-- Path = "/Solar System/Planets/Saturn"
-- }
-- }
assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn, SaturnRings })
--assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn, SaturnRings })
assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn })

View File

@@ -51,6 +51,8 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtile.h
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtiledatareader.h
${CMAKE_CURRENT_SOURCE_DIR}/src/renderableglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ringscomponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/shadowcomponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/skirtedgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/src/tileindex.h
${CMAKE_CURRENT_SOURCE_DIR}/src/tileloadjob.h
@@ -80,6 +82,8 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtiledatareader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/renderableglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ringscomponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/shadowcomponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/skirtedgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tileindex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tileloadjob.cpp
@@ -94,6 +98,10 @@ set(SHADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalrenderer_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/localrenderer_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderer_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/rings_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/rings_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/rings_geom_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/rings_geom_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/texturetilemapping.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tile.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tileheight.hglsl

View File

@@ -0,0 +1,129 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 vec2 vs_st;
in float vs_screenSpaceDepth;
in vec4 vs_positionViewSpace;
in flat vec4 shadowCoords;
uniform sampler2D shadowPositionTexture;
uniform sampler2DShadow shadowMap;
uniform sampler1D texture1;
uniform vec2 textureOffset;
uniform float transparency;
uniform bool hasSunPosition;
uniform vec3 sunPosition;
uniform float _nightFactor;
// temp
in vec4 fragPosInLightSpace;
Fragment getFragment() {
// Moving the origin to the center
vec2 st = (vs_st - vec2(0.5)) * 2.0;
// The length of the texture coordinates vector is our distance from the center
float radius = length(st);
// We only want to consider ring-like objects so we need to discard everything else
if (radius > 1.0)
discard;
// Remapping the texture coordinates
// Radius \in [0,1], texCoord \in [textureOffset.x, textureOffset.y]
// textureOffset.x -> 0
// textureOffset.y -> 1
float texCoord = (radius - textureOffset.x) / (textureOffset.y - textureOffset.x);
if (texCoord < 0.f || texCoord > 1.f) {
discard;
}
vec4 diffuse = texture(texture1, texCoord);
float colorValue = length(diffuse.rgb);
// times 3 as length of vec3(1.0, 1.0, 1.0) will return 3 and we want
// to normalize the transparency value to [0,1]
if (colorValue < 3.0 * transparency) {
diffuse.a = pow(colorValue / (3.0 * transparency), 1);
}
// shadow == 1.0 means it is not in shadow
float shadow = 1.0;
if ( shadowCoords.z >= 0 ) {
shadow = textureProj(shadowMap, shadowCoords);
}
// shadow = 1.0;
// vec4 depthInTexture = vec4(0.0, 0.0, 0.0, 1.0);
// //if (shadowCoords.z >= 0) {
// if (true) {
// vec4 byHandCoords = shadowCoords / shadowCoords.w;
// // Distance of the current pixel from the light source
// depthInTexture = texture(shadowPositionTexture, byHandCoords.xy);
// //depthInTexture = texture(shadowPositionTexture, vec2(0.5, 0.5));
// // if (depthInTexture.x < byHandCoords.z) {
// // shadow = 0.0;
// // }
// if (length(fragPosInLightSpace) > depthInTexture.x) {
// shadow = 0.2;
// }
// //shadow = length(fragPosInLightSpace);
// }
// The normal for the one plane depends on whether we are dealing
// with a front facing or back facing fragment
vec3 normal;
// The plane is oriented on the xz plane
// WARNING: This might not be the case for Uranus
if (gl_FrontFacing) {
normal = vec3(-1.0, 0.0, 0.0);
}
else {
normal = vec3(1.0, 0.0, 0.0);
}
// Reduce the color of the fragment by the user factor
// if we are facing away from the Sun
if (dot(sunPosition, normal) < 0) {
diffuse.xyz *= _nightFactor;
}
Fragment frag;
//frag.color = depthInTexture;
frag.color = (0.55 * diffuse * shadow) + diffuse * 0.45;
//frag.color = vec4(shadow * vec3(1.0, 1.0, 1.0), 1.0);
//frag.depth = vs_position.w;
frag.depth = vs_screenSpaceDepth;
if (diffuse.a < 1.0)
frag.gPosition = vec4(1e30, 1e30, 1e30, 1.0);
else
frag.gPosition = vs_positionViewSpace;
frag.gNormal = vec4(normal, 1.0);
return frag;
}

View File

@@ -0,0 +1,75 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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"
layout (location = 3) out vec4 renderedPosition;
in vec2 vs_st;
in float vs_screenSpaceDepth;
in vec4 vs_positionViewSpace;
uniform vec2 textureOffset;
Fragment getFragment() {
// Moving the origin to the center
vec2 st = (vs_st - vec2(0.5)) * 2.0;
// The length of the texture coordinates vector is our distance from the center
float radius = length(st);
// We only want to consider ring-like objects so we need to discard everything else
if (radius > 1.0)
discard;
// Remapping the texture coordinates
// Radius \in [0,1], texCoord \in [textureOffset.x, textureOffset.y]
// textureOffset.x -> 0
// textureOffset.y -> 1
float texCoord = (radius - textureOffset.x) / (textureOffset.y - textureOffset.x);
if (texCoord < 0.f || texCoord > 1.f) {
discard;
}
// The normal for the one plane depends on whether we are dealing
// with a front facing or back facing fragment
//vec3 normal;
// The plane is oriented on the xz plane
// WARNING: This might not be the case for Uranus
// if (gl_FrontFacing) {
// normal = vec3(-1.0, 0.0, 0.0);
// }
// else {
// normal = vec3(1.0, 0.0, 0.0);
// }
Fragment frag;
frag.color = vec4(1.0);;
frag.depth = vs_screenSpaceDepth;
renderedPosition = vec4(vec3(length(vs_positionViewSpace.xyz)), 1.0);//vec4(vs_positionViewSpace.xyz, 1.0);
//renderedPosition = vec4(vec3(vs_screenSpaceDepth.w)/10.0, 1.0);
return frag;
}

View File

@@ -0,0 +1,51 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScalingMath.hglsl"
layout(location = 0) in vec2 in_position;
layout(location = 1) in vec2 in_st;
out vec2 vs_st;
out float vs_screenSpaceDepth;
out vec4 vs_positionViewSpace;
uniform dmat4 modelViewMatrix;
uniform dmat4 projectionMatrix;
void main() {
vs_st = in_st;
dvec4 positionViewSpace = modelViewMatrix * dvec4(in_position, 0.0, 1.0);
vec4 positionClipSpace = vec4(projectionMatrix * positionViewSpace);
vec4 positionClipSpaceZNorm = z_normalization(positionClipSpace);
vs_screenSpaceDepth = positionClipSpaceZNorm.w;
vs_positionViewSpace = vec4(positionViewSpace);
//gl_Position = positionClipSpaceZNorm;
gl_Position = positionClipSpace;
}

View File

@@ -0,0 +1,67 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
layout(location = 0) in vec2 in_position;
layout(location = 1) in vec2 in_st;
out vec2 vs_st;
out float vs_screenSpaceDepth;
out vec4 vs_positionViewSpace;
out vec4 shadowCoords;
// temp
out vec4 fragPosInLightSpace;
uniform dmat4 objectToLightSpaceMatrix;
uniform dmat4 modelViewMatrix;
uniform dmat4 projectionMatrix;
// ShadowMatrix is the matrix defined by:
// textureCoordsMatrix * projectionMatrix * combinedViewMatrix * modelMatrix
// where textureCoordsMatrix is just a scale and bias computation: [-1,1] to [0,1]
uniform dmat4 shadowMatrix;
void main() {
vs_st = in_st;
dvec4 positionViewSpace = modelViewMatrix * dvec4(in_position, 0.0, 1.0);
vec4 positionClipSpace = vec4(projectionMatrix * positionViewSpace);
vec4 positionClipSpaceZNorm = z_normalization(positionClipSpace);
shadowCoords = vec4(shadowMatrix * dvec4(in_position, 0.0, 1.0));
// temp
fragPosInLightSpace = vec4(objectToLightSpaceMatrix *
dvec4(in_position.xy, 0.0, 1.0));
vs_screenSpaceDepth = positionClipSpaceZNorm.w;
vs_positionViewSpace = vec4(positionViewSpace);
//gl_Position = positionClipSpaceZNorm;
gl_Position = positionClipSpace;
}

View File

@@ -505,6 +505,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
, _grid(DefaultSkirtedGridSegments, DefaultSkirtedGridSegments)
, _leftRoot(Chunk(LeftHemisphereIndex))
, _rightRoot(Chunk(RightHemisphereIndex))
, _ringsComponent(dictionary)
, _shadowComponent(dictionary)
{
_generalProperties.currentLodScaleFactor.setReadOnly(true);
@@ -656,6 +658,20 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
_labelsDictionary = dictionary.value<ghoul::Dictionary>(KeyLabels);
}
// Components
if (dictionary.hasKey("Rings")) {
_ringsComponent.initialize();
addPropertySubOwner(_ringsComponent);
_hasRings = true;
ghoul::Dictionary ringsDic;
dictionary.getValue("Rings", ringsDic);
if (ringsDic.hasKey("Shadows")) {
_shadowComponent.initialize();
addPropertySubOwner(_shadowComponent);
}
}
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
_module = global::moduleEngine.module<GlobeBrowsingModule>();
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
@@ -670,6 +686,11 @@ void RenderableGlobe::initializeGL() {
_layerManager.update();
_grid.initializeGL();
_ringsComponent.initializeGL();
_shadowComponent.initializeGL();
// Recompile the shaders directly so that it is not done the first time the render
// function is called.
recompileShaders();
@@ -691,6 +712,10 @@ void RenderableGlobe::deinitializeGL() {
}
_grid.deinitializeGL();
_ringsComponent.deinitializeGL();
_shadowComponent.deinitializeGL();
}
bool RenderableGlobe::isReady() const {
@@ -713,8 +738,49 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
if (distanceToCamera < distance) {
try {
renderChunks(data, rendererTask);
_globeLabelsComponent.draw(data);
// Before Shadows
//renderChunks(data, rendererTask);
//_globeLabelsComponent.draw(data);
if (_hasRings && _ringsComponent.isEnabled()) {
if (_shadowComponent.isEnabled()) {
glDisablei(GL_BLEND, 3);
//glEnablei(GL_DEPTH_TEST, 3);
_shadowComponent.begin(data);
//_ringsComponent.draw(data, RingsComponent::GeometryOnly);
//RenderData tmpRD = data;
//tmpRD.modelTransform.rotation = tmpRD.modelTransform.rotation * glm::dmat3(glm::rotate(glm::dmat4(1), 90.0, glm::dvec3(1.0, 0.0, 0.0)));
//_ringsComponent.draw(tmpRD, RingsComponent::GeometryOnly);
renderChunks(data, rendererTask, true);
_shadowComponent.end(data);
glEnablei(GL_BLEND, 3);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(2.5f, 10.0f);
_ringsComponent.draw(
data,
RingsComponent::GeometryAndShading,
_shadowComponent.shadowMapData()
);
renderChunks(data, rendererTask);
glDisable(GL_POLYGON_OFFSET_FILL);
}
else {
renderChunks(data, rendererTask);
_ringsComponent.draw(data, RingsComponent::GeometryAndShading);
}
}
else {
renderChunks(data, rendererTask);
}
}
catch (const ghoul::opengl::TextureUnit::TextureUnitError&) {
std::string layer = _lastChangedLayer ? _lastChangedLayer->guiName() : "";
@@ -852,7 +918,8 @@ const glm::dmat4& RenderableGlobe::modelTransform() const {
// Rendering code
//////////////////////////////////////////////////////////////////////////////////////////
void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&) {
void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
const bool renderGeomOnly) {
if (_shadersNeedRecompilation) {
recompileShaders();
}
@@ -1086,7 +1153,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&) {
// Render all chunks that want to be rendered globally
_globalRenderer.program->activate();
for (int i = 0; i < std::min(globalCount, ChunkBufferSize); ++i) {
renderChunkGlobally(*global[i], data);
renderChunkGlobally(*global[i], data, renderGeomOnly);
}
_globalRenderer.program->deactivate();
@@ -1094,7 +1161,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&) {
// Render all chunks that need to be rendered locally
_localRenderer.program->activate();
for (int i = 0; i < std::min(localCount, ChunkBufferSize); ++i) {
renderChunkLocally(*local[i], data);
renderChunkLocally(*local[i], data, renderGeomOnly);
}
_localRenderer.program->deactivate();
@@ -1151,7 +1218,8 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&) {
}
}
void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData& data) {
void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData& data,
const bool renderGeomOnly) {
//PerfMeasure("globally");
const TileIndex& tileIndex = chunk.tileIndex;
ghoul::opengl::ProgramObject& program = *_globalRenderer.program;
@@ -1199,16 +1267,21 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
if (!renderGeomOnly) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
_grid.drawUsingActiveProgram();
for (GPULayerGroup& l : _globalRenderer.gpuLayerGroups) {
l.deactivate();
}
}
void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& data) {
void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& data,
const bool renderGeomOnly) {
//PerfMeasure("locally");
const TileIndex& tileIndex = chunk.tileIndex;
ghoul::opengl::ProgramObject& program = *_localRenderer.program;
@@ -1301,9 +1374,11 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
if (!renderGeomOnly) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
_grid.drawUsingActiveProgram();
for (GPULayerGroup& l : _localRenderer.gpuLayerGroups) {

View File

@@ -32,6 +32,8 @@
#include <modules/globebrowsing/src/globelabelscomponent.h>
#include <modules/globebrowsing/src/gpulayergroup.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <modules/globebrowsing/src/ringscomponent.h>
#include <modules/globebrowsing/src/shadowcomponent.h>
#include <modules/globebrowsing/src/skirtedgrid.h>
#include <modules/globebrowsing/src/tileindex.h>
#include <openspace/properties/scalar/floatproperty.h>
@@ -181,7 +183,8 @@ private:
*/
float getHeight(const glm::dvec3& position) const;
void renderChunks(const RenderData& data, RendererTasks& rendererTask);
void renderChunks(const RenderData& data, RendererTasks& rendererTask,
const bool renderGeomOnly = false);
/**
* Chunks can be rendered either globally or locally. Global rendering is performed
@@ -191,7 +194,8 @@ private:
* point precision by doing this which means that the camera too close to a global
* tile will lead to jagging. We only render global chunks for lower chunk levels.
*/
void renderChunkGlobally(const Chunk& chunk, const RenderData& data);
void renderChunkGlobally(const Chunk& chunk, const RenderData& data,
const bool renderGeomOnly = false);
/**
* Local rendering of chunks are done using linear interpolation in camera space.
@@ -204,7 +208,8 @@ private:
* levels) the better the approximation becomes. This is why we only render local
* chunks for higher chunk levels.
*/
void renderChunkLocally(const Chunk& chunk, const RenderData& data);
void renderChunkLocally(const Chunk& chunk, const RenderData& data,
const bool renderGeomOnly = false);
void debugRenderChunk(const Chunk& chunk, const glm::dmat4& mvp,
bool renderBounds, bool renderAABB) const;
@@ -275,6 +280,11 @@ private:
size_t _iterationsOfUnavailableData = 0;
Layer* _lastChangedLayer = nullptr;
// Components
RingsComponent _ringsComponent;
ShadowComponent _shadowComponent;
bool _hasRings = false;
// Labels
GlobeLabelsComponent _globeLabelsComponent;
ghoul::Dictionary _labelsDictionary;

View File

@@ -0,0 +1,445 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/src/ringscomponent.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/util/updatestructures.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <fstream>
#include <cstdlib>
#include <locale>
namespace {
constexpr const std::array<const char*, 7> UniformNames = {
"modelViewMatrix", "projectionMatrix", "textureOffset",
"transparency", "_nightFactor", "sunPosition", "texture1"
};
constexpr const std::array<const char*, 3> GeomUniformNames = {
"modelViewMatrix", "projectionMatrix", "textureOffset"
};
constexpr openspace::properties::Property::PropertyInfo TextureInfo = {
"Texture",
"Texture",
"This value is the path to a texture on disk that contains a one-dimensional "
"texture which is used for these rings."
};
constexpr openspace::properties::Property::PropertyInfo SizeInfo = {
"Size",
"Size",
"This value specifies the radius of the rings in meter."
};
constexpr openspace::properties::Property::PropertyInfo OffsetInfo = {
"Offset",
"Offset",
"This value is used to limit the width of the rings.Each of the two values is a "
"value between 0 and 1, where 0 is the center of the ring and 1 is the maximum "
"extent at the radius. If this value is, for example {0.5, 1.0}, the ring is "
"only shown between radius/2 and radius. It defaults to {0.0, 1.0}."
};
constexpr openspace::properties::Property::PropertyInfo NightFactorInfo = {
"NightFactor",
"Night Factor",
"This value is a multiplicative factor that is applied to the side of the rings "
"that is facing away from the Sun. If this value is equal to '1', no darkening "
"of the night side occurs."
};
constexpr openspace::properties::Property::PropertyInfo TransparencyInfo = {
"Transparency",
"Transparency",
"This value determines the transparency of part of the rings depending on the "
"color values. For this value v, the transparency is equal to length(color) / v."
};
} // namespace
namespace openspace {
documentation::Documentation RingsComponent::Documentation() {
using namespace documentation;
return {
"Rings Component",
"globebrowsing_rings_component",
{
{
TextureInfo.identifier,
new StringVerifier,
Optional::Yes,
TextureInfo.description
},
{
SizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
SizeInfo.description
},
{
OffsetInfo.identifier,
new DoubleVector2Verifier,
Optional::Yes,
OffsetInfo.description
},
{
NightFactorInfo.identifier,
new DoubleVerifier,
Optional::Yes,
NightFactorInfo.description
},
{
TransparencyInfo.identifier,
new DoubleVerifier,
Optional::Yes,
TransparencyInfo.description
}
}
};
}
RingsComponent::RingsComponent(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "Rings" })
, _texturePath(TextureInfo)
, _size(SizeInfo, 1.f, 0.f, 1e25f)
, _offset(OffsetInfo, glm::vec2(0.f, 1.f), glm::vec2(0.f), glm::vec2(1.f))
, _nightFactor(NightFactorInfo, 0.33f, 0.f, 1.f)
, _transparency(TransparencyInfo, 0.15f, 0.f, 1.f)
, _enabled({ "Enabled", "Enabled", "Enable/Disable Rings" }, true)
, _ringsDictionary(dictionary)
{
using ghoul::filesystem::File;
if (dictionary.hasKey("Rings")) {
dictionary.getValue("Rings", _ringsDictionary);
}
documentation::testSpecificationAndThrow(
Documentation(),
_ringsDictionary,
"RingsComponent"
);
}
void RingsComponent::initialize()
{
using ghoul::filesystem::File;
addProperty(_enabled);
_size = static_cast<float>(_ringsDictionary.value<double>(SizeInfo.identifier));
//setBoundingSphere(_size);
_size.onChange([&]() { _planeIsDirty = true; });
addProperty(_size);
_texturePath = absPath(_ringsDictionary.value<std::string>(TextureInfo.identifier));
_textureFile = std::make_unique<File>(_texturePath);
if (_ringsDictionary.hasKeyAndValue<glm::vec2>(OffsetInfo.identifier)) {
_offset = _ringsDictionary.value<glm::vec2>(OffsetInfo.identifier);
}
addProperty(_offset);
_texturePath.onChange([&]() { loadTexture(); });
addProperty(_texturePath);
_textureFile->setCallback([&](const File&) { _textureIsDirty = true; });
if (_ringsDictionary.hasKeyAndValue<double>(NightFactorInfo.identifier)) {
_nightFactor = static_cast<float>(
_ringsDictionary.value<double>(NightFactorInfo.identifier)
);
}
addProperty(_nightFactor);
if (_ringsDictionary.hasKeyAndValue<double>(TransparencyInfo.identifier)) {
_transparency = static_cast<float>(
_ringsDictionary.value<double>(TransparencyInfo.identifier)
);
}
addProperty(_transparency);
}
bool RingsComponent::isReady() const {
return (_shader || _geometryOnlyShader) && _texture;
}
void RingsComponent::initializeGL() {
_shader = global::renderEngine.buildRenderProgram(
"RingsProgram",
absPath("${MODULE_GLOBEBROWSING}/shaders/rings_vs.glsl"),
absPath("${MODULE_GLOBEBROWSING}/shaders/rings_fs.glsl")
);
_geometryOnlyShader = global::renderEngine.buildRenderProgram(
"RingsGeomOnlyProgram",
absPath("${MODULE_GLOBEBROWSING}/shaders/rings_geom_vs.glsl"),
absPath("${MODULE_GLOBEBROWSING}/shaders/rings_geom_fs.glsl")
);
ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames);
ghoul::opengl::updateUniformLocations(
*_geometryOnlyShader,
_geomUniformCache,
GeomUniformNames
);
glGenVertexArrays(1, &_quad);
glGenBuffers(1, &_vertexPositionBuffer);
createPlane();
loadTexture();
}
void RingsComponent::deinitializeGL() {
glDeleteVertexArrays(1, &_quad);
_quad = 0;
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
_textureFile = nullptr;
_texture = nullptr;
global::renderEngine.removeRenderProgram(_shader.get());
_shader = nullptr;
global::renderEngine.removeRenderProgram(_geometryOnlyShader.get());
_geometryOnlyShader = nullptr;
}
void RingsComponent::draw(
const RenderData& data,
const RingsComponent::RenderPass renderPass,
const ShadowComponent::ShadowMapData& shadowData
) {
if (renderPass == GeometryAndShading) {
_shader->activate();
}
else if (renderPass == GeometryOnly) {
_geometryOnlyShader->activate();
}
const glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
glm::dmat4(data.modelTransform.rotation) *
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale));
const glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
const glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix());
ghoul::opengl::TextureUnit unit;
if (renderPass == GeometryAndShading) {
_shader->setUniform(_uniformCache.modelViewMatrix, modelViewTransform);
_shader->setUniform(_uniformCache.projectionMatrix, projectionMatrix);
_shader->setUniform(_uniformCache.textureOffset, _offset);
_shader->setUniform(_uniformCache.transparency, _transparency);
_shader->setUniform(_uniformCache.nightFactor, _nightFactor);
_shader->setUniform(_uniformCache.sunPosition, _sunPosition);
unit.activate();
_texture->bind();
_shader->setUniform(_uniformCache.texture, unit);
// Adding the model transformation to the final shadow matrix so we have a
// complete transformation from the model coordinates to the clip space of
// the light position.
_shader->setUniform("shadowMatrix", shadowData.shadowMatrix * modelTransform);
ghoul::opengl::TextureUnit shadowMapUnit;
shadowMapUnit.activate();
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
_shader->setUniform("shadowMap", shadowMapUnit);
// DEBUGGING
ghoul::opengl::TextureUnit shadowTextureUnit;
shadowTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D, shadowData.positionInLightSpaceTexture);
_shader->setUniform("shadowPositionTexture", shadowTextureUnit);
_shader->setUniform("objectToLightSpaceMatrix",
shadowData.worldToLightSpaceMatrix * modelTransform);
}
else if (renderPass == GeometryOnly) {
_geometryOnlyShader->setUniform(
_geomUniformCache.modelViewMatrix,
modelViewTransform
);
_geometryOnlyShader->setUniform(
_geomUniformCache.projectionMatrix,
projectionMatrix
);
_geometryOnlyShader->setUniform(
_geomUniformCache.textureOffset,
_offset
);
}
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glBindVertexArray(_quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glEnable(GL_CULL_FACE);
if (renderPass == GeometryAndShading) {
_shader->deactivate();
}
else if (renderPass == GeometryOnly) {
_geometryOnlyShader->deactivate();
}
}
void RingsComponent::update(const UpdateData& data) {
if (_shader->isDirty()) {
_shader->rebuildFromFile();
ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames);
}
if (_geometryOnlyShader->isDirty()) {
_geometryOnlyShader->rebuildFromFile();
ghoul::opengl::updateUniformLocations(
*_geometryOnlyShader,
_geomUniformCache,
GeomUniformNames
);
}
if (_planeIsDirty) {
createPlane();
_planeIsDirty = false;
}
if (_textureIsDirty) {
loadTexture();
_textureIsDirty = false;
}
_sunPosition = glm::normalize(
global::renderEngine.scene()->sceneGraphNode("Sun")->worldPosition() -
data.modelTransform.translation
);
}
void RingsComponent::loadTexture() {
if (!_texturePath.value().empty()) {
using namespace ghoul::io;
using namespace ghoul::opengl;
std::unique_ptr<Texture> texture = TextureReader::ref().loadTexture(
absPath(_texturePath)
);
if (texture) {
LDEBUGC(
"RingsComponent",
fmt::format("Loaded texture from '{}'", absPath(_texturePath))
);
_texture = std::move(texture);
_texture->uploadTexture();
_texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
_textureFile->setCallback(
[&](const ghoul::filesystem::File&) { _textureIsDirty = true; }
);
}
}
}
void RingsComponent::createPlane() {
const GLfloat size = _size;
struct VertexData {
GLfloat x;
GLfloat y;
GLfloat s;
GLfloat t;
};
VertexData data[] = {
{ -size, -size, 0.f, 0.f },
{ size, size, 1.f, 1.f },
{ -size, size, 0.f, 1.f },
{ -size, -size, 0.f, 0.f },
{ size, -size, 1.f, 0.f },
{ size, size, 1.f, 1.f },
};
glBindVertexArray(_quad);
glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
2,
GL_FLOAT,
GL_FALSE,
sizeof(VertexData),
nullptr
);
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
sizeof(VertexData),
reinterpret_cast<void*>(offsetof(VertexData, s)) // NOLINT
);
}
bool RingsComponent::isEnabled() const {
return _enabled;
}
} // namespace openspace

View File

@@ -0,0 +1,115 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___RINGSCOMPONENT___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___RINGSCOMPONENT___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/src/shadowcomponent.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/vector/vec2property.h>
#include <openspace/properties/vector/vec4property.h>
#include <openspace/properties/stringproperty.h>
#include <ghoul/glm.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/uniformcache.h>
namespace ghoul {
class Dictionary;
}
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl {
class ProgramObject;
} // namespace ghoul::opengl
namespace openspace {
struct RenderData;
struct UpdateData;
namespace documentation { struct Documentation; }
class RingsComponent : public properties::PropertyOwner {
public:
enum RenderPass {
GeometryOnly,
GeometryAndShading
};
public:
RingsComponent(const ghoul::Dictionary& dictionary);
void initialize();
void initializeGL();
void deinitializeGL();
bool isReady() const;
void draw(
const RenderData& data,
const RingsComponent::RenderPass renderPass,
const ShadowComponent::ShadowMapData& shadowData = {}
);
void update(const UpdateData& data);
static documentation::Documentation Documentation();
bool isEnabled() const;
private:
void loadTexture();
void createPlane();
properties::StringProperty _texturePath;
properties::FloatProperty _size;
properties::Vec2Property _offset;
properties::FloatProperty _nightFactor;
properties::FloatProperty _transparency;
properties::BoolProperty _enabled;
std::unique_ptr<ghoul::opengl::ProgramObject> _shader;
std::unique_ptr<ghoul::opengl::ProgramObject> _geometryOnlyShader;
UniformCache(modelViewMatrix, projectionMatrix, textureOffset,
transparency, nightFactor, sunPosition, texture) _uniformCache;
UniformCache(modelViewMatrix, projectionMatrix, textureOffset) _geomUniformCache;
std::unique_ptr<ghoul::opengl::Texture> _texture;
std::unique_ptr<ghoul::filesystem::File> _textureFile;
ghoul::Dictionary _ringsDictionary;
bool _textureIsDirty = false;
GLuint _quad = 0;
GLuint _vertexPositionBuffer = 0;
bool _planeIsDirty = false;
glm::vec3 _sunPosition;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___RINGSCOMPONENT___H__

View File

@@ -0,0 +1,708 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/src/shadowcomponent.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/util/updatestructures.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/interaction/keyframenavigator.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/util/camera.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <glm/gtc/matrix_transform.hpp>
#include <fstream>
#include <cstdlib>
#include <locale>
namespace {
constexpr const char* _loggerCat = "ShadowComponent";
constexpr openspace::properties::Property::PropertyInfo SaveDepthTextureInfo = {
"SaveDepthTextureInfo",
"Save Depth Texture",
"Debug"
};
constexpr openspace::properties::Property::PropertyInfo DistanceFractionInfo = {
"DistanceFraction",
"Distance Fraction",
"Distance fraction of original distance from light source to the globe to be "
"considered as the new light source distance."
};
void checkFrameBufferState(const std::string& codePosition)
{
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LERROR("Framework not built. " + codePosition);
GLenum fbErr = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (fbErr) {
case GL_FRAMEBUFFER_UNDEFINED:
LERROR("Indefined framebuffer.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
LERROR("Incomplete, missing attachement.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
LERROR("Framebuffer doesn't have at least one image attached to it.");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
LERROR(
"Returned if the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
"GL_NONE for any color attachment point(s) named by GL_DRAW_BUFFERi."
);
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
LERROR(
"Returned if GL_READ_BUFFER is not GL_NONE and the value of "
"GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for the color "
"attachment point named by GL_READ_BUFFER.");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
LERROR(
"Returned if the combination of internal formats of the attached "
"images violates an implementation - dependent set of restrictions."
);
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
LERROR(
"Returned if the value of GL_RENDERBUFFE_r_samples is not the same "
"for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES "
"is the not same for all attached textures; or , if the attached "
"images are a mix of renderbuffers and textures, the value of "
"GL_RENDERBUFFE_r_samples does not match the value of "
"GL_TEXTURE_SAMPLES."
);
LERROR(
"Returned if the value of GL_TEXTURE_FIXED_SAMPLE_LOCATIONS is not "
"the same for all attached textures; or , if the attached images are "
"a mix of renderbuffers and textures, the value of "
"GL_TEXTURE_FIXED_SAMPLE_LOCATIONS is not GL_TRUE for all attached "
"textures."
);
break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
LERROR(
"Returned if any framebuffer attachment is layered, and any "
"populated attachment is not layered, or if all populated color "
"attachments are not from textures of the same target."
);
break;
default:
LDEBUG("No error found checking framebuffer: " + codePosition);
break;
}
}
}
} // namespace
namespace openspace {
documentation::Documentation ShadowComponent::Documentation() {
using namespace documentation;
return {
"ShadowsRing Component",
"globebrowsing_shadows_component",
{
{
DistanceFractionInfo.identifier,
new DoubleVerifier,
Optional::Yes,
DistanceFractionInfo.description
}
}
};
}
ShadowComponent::ShadowComponent(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "Shadows" })
, _saveDepthTexture(SaveDepthTextureInfo)
, _distanceFraction(DistanceFractionInfo, 30, 1, 100000)
, _enabled({ "Enabled", "Enabled", "Enable/Disable Shadows" }, true)
, _shadowMapDictionary(dictionary)
, _shadowDepthTextureHeight(1024)
, _shadowDepthTextureWidth(1024)
, _shadowDepthTexture(-1)
, _positionInLightSpaceTexture(-1)
, _shadowFBO(-1)
, _firstPassSubroutine(-1)
, _secondPassSubroutine(1)
, _defaultFBO(-1)
, _sunPosition(0.0)
, _shadowMatrix(1.0)
, _executeDepthTextureSave(false)
{
using ghoul::filesystem::File;
if (dictionary.hasKey("Rings")) {
ghoul::Dictionary ringsDic;
dictionary.getValue("Rings", ringsDic);
if (ringsDic.hasKey("Shadows")) {
ringsDic.getValue("Shadows", _shadowMapDictionary);
}
}
documentation::testSpecificationAndThrow(
Documentation(),
_shadowMapDictionary,
"ShadowComponent"
);
if (_shadowMapDictionary.hasKey(DistanceFractionInfo.identifier)) {
_distanceFraction = static_cast<int>(
_shadowMapDictionary.value<float>(DistanceFractionInfo.identifier)
);
}
_saveDepthTexture.onChange([&]() {
_executeDepthTextureSave = true;
});
addProperty(_enabled);
addProperty(_saveDepthTexture);
addProperty(_distanceFraction);
}
void ShadowComponent::initialize()
{
using ghoul::filesystem::File;
}
bool ShadowComponent::isReady() const {
return true;
}
void ShadowComponent::initializeGL() {
createDepthTexture();
createShadowFBO();
}
void ShadowComponent::deinitializeGL() {
glDeleteTextures(1, &_shadowDepthTexture);
glDeleteTextures(1, &_positionInLightSpaceTexture);
glDeleteFramebuffers(1, &_shadowFBO);
checkGLError("ShadowComponent::deinitializeGL() -- Deleted Textures and Framebuffer");
}
void ShadowComponent::begin(const RenderData& data) {
// ===========================================
// Builds light's ModelViewProjectionMatrix:
// ===========================================
glm::dvec3 diffVector = glm::dvec3(_sunPosition) - data.modelTransform.translation;
double originalLightDistance = glm::length(diffVector);
glm::dvec3 lightDirection = glm::normalize(diffVector);
// Percentage of the original light source distance (to avoid artifacts)
double multiplier = originalLightDistance *
(static_cast<double>(_distanceFraction)/1.0E5);
// New light source position
glm::dvec3 lightPosition = data.modelTransform.translation +
(lightDirection * multiplier);
// Saving current Camera parameters
_cameraPos = data.camera.positionVec3();
// JCC: We have aim and ancor nodes and position now. Need to fix this.
//_cameraFocus = data.camera.focusPositionVec3();
_cameraRotation = data.camera.rotationQuaternion();
//=============== Automatically Created Camera Matrix ===================
//=======================================================================
//glm::dmat4 lightViewMatrix = glm::lookAt(
// //lightPosition,
// glm::dvec3(0.0),
// //glm::dvec3(_sunPosition), // position
// glm::dvec3(data.modelTransform.translation), // focus
// data.camera.lookUpVectorWorldSpace() // up
// //glm::dvec3(0.0, 1.0, 0.0)
//);
//camera->setPositionVec3(lightPosition);
//camera->setFocusPositionVec3(data.modelTransform.translation);
//camera->setRotation(glm::dquat(glm::inverse(lightViewMatrix)));
//=======================================================================
//=======================================================================
//=============== Manually Created Camera Matrix ===================
//==================================================================
// camera Z
glm::dvec3 cameraZ = lightDirection;
// camera X
glm::dvec3 upVector = glm::dvec3(0.0, -1.0, 0.0);
glm::dvec3 cameraX = glm::normalize(glm::cross(upVector, cameraZ));
// camera Y
glm::dvec3 cameraY = glm::cross(cameraZ, cameraX);
// init 4x4 matrix
glm::dmat4 cameraRotationMatrix(1.0);
double* matrix = glm::value_ptr(cameraRotationMatrix);
matrix[0] = cameraX.x;
matrix[4] = cameraX.y;
matrix[8] = cameraX.z;
matrix[1] = cameraY.x;
matrix[5] = cameraY.y;
matrix[9] = cameraY.z;
matrix[2] = cameraZ.x;
matrix[6] = cameraZ.y;
matrix[10] = cameraZ.z;
// set translation part
// We aren't setting the position here because it is set in
// the camera->setPosition()
//matrix[12] = -glm::dot(cameraX, lightPosition);
//matrix[13] = -glm::dot(cameraY, lightPosition);
//matrix[14] = -glm::dot(cameraZ, lightPosition);
/*Scene* scene = camera->parent()->scene();
global::navigationHandler.setFocusNode(data.);
*/
Camera camera(data.camera);
camera.setPositionVec3(lightPosition);
// JCC: We have aim and ancor nodes and position now. Need to fix this.
//camera.setFocusPositionVec3(data.modelTransform.translation);
camera.setRotation(glm::dquat(glm::inverse(cameraRotationMatrix)));
//=======================================================================
//=======================================================================
//============= Light Matrix by Camera Matrices Composition =============
//=======================================================================
glm::dmat4 lightProjectionMatrix = glm::dmat4(camera.projectionMatrix());
//glm::dmat4 lightProjectionMatrix = glm::ortho(-1000.0, 1000.0, -1000.0, 1000.0, 0.0010, 1000.0);
//glm::dmat4 lightProjectionMatrix = glm::frustum(-1.0, 1.0, -1.0, 1.0, 1.0, 1000000.0);
// The model transformation missing in the final shadow matrix is add when rendering each
// object (using its transformations provided by the RenderData structure)
_shadowData.shadowMatrix =
_toTextureCoordsMatrix *
lightProjectionMatrix *
camera.combinedViewMatrix();
// temp
_shadowData.worldToLightSpaceMatrix = glm::dmat4(camera.combinedViewMatrix());
checkGLError("begin() -- Saving Current GL State");
// Saves current state
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO);
glGetIntegerv(GL_VIEWPORT, _mViewport);
_faceCulling = glIsEnabled(GL_CULL_FACE);
glGetIntegerv(GL_CULL_FACE_MODE, &_faceToCull);
_polygonOffSet = glIsEnabled(GL_POLYGON_OFFSET_FILL);
glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &_polygonOffSetFactor);
glGetFloatv(GL_POLYGON_OFFSET_UNITS, &_polygonOffSetUnits);
glGetFloatv(GL_COLOR_CLEAR_VALUE, _colorClearValue);
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &_depthClearValue);
_depthIsEnabled = glIsEnabled(GL_DEPTH_TEST);
glGetIntegerv(GL_DEPTH_FUNC, &_depthFunction);
_blendIsEnabled = glIsEnabled(GL_BLEND);
checkGLError("begin() -- before binding FBO");
glBindFramebuffer(GL_FRAMEBUFFER, _shadowFBO);
checkGLError("begin() -- after binding FBO");
glViewport(0, 0, _shadowDepthTextureWidth, _shadowDepthTextureHeight);
checkGLError("begin() -- set new viewport");
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
checkGLError("begin() -- after cleanning Depth buffer");
/*glEnable(GL_CULL_FACE);
checkGLError("begin() -- enabled cull face");
glCullFace(GL_FRONT);
checkGLError("begin() -- set cullface to front");*/
/*glEnable(GL_POLYGON_OFFSET_FILL);
checkGLError("begin() -- enabled polygon offset fill");
glPolygonOffset(2.5f, 10.0f);
checkGLError("begin() -- set values for polygon offset");*/
checkGLError("begin() finished");
}
void ShadowComponent::end(const RenderData& data) {
checkGLError("end() -- Flushing");
//glFlush();
if (_executeDepthTextureSave) {
saveDepthBuffer();
_executeDepthTextureSave = false;
}
// Restores Camera Parameters
Camera camera = data.camera;
camera.setPositionVec3(_cameraPos);
// JCC: We have aim and ancor nodes and position now. Need to fix this.
//camera.setFocusPositionVec3(_cameraFocus);
camera.setRotation(_cameraRotation);
// Restores system state
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO);
checkGLError("end() -- Rebinding default FBO");
glViewport(
_mViewport[0],
_mViewport[1],
_mViewport[2],
_mViewport[3]
);
if (_faceCulling) {
glEnable(GL_CULL_FACE);
glCullFace(_faceToCull);
}
else {
glDisable(GL_CULL_FACE);
}
if (_depthIsEnabled) {
glEnable(GL_DEPTH_TEST);
}
else {
glDisable(GL_DEPTH_TEST);
}
glDepthFunc(_depthFunction);
if (_polygonOffSet) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(_polygonOffSetFactor, _polygonOffSetUnits);
}
else {
glDisable(GL_POLYGON_OFFSET_FILL);
}
glClearColor(
_colorClearValue[0],
_colorClearValue[1],
_colorClearValue[2],
_colorClearValue[3]
);
glClearDepth(_depthClearValue);
if (_blendIsEnabled) {
glEnable(GL_BLEND);
}
checkGLError("end() finished");
}
void ShadowComponent::update(const UpdateData& /*data*/) {
_sunPosition = global::renderEngine.scene()->sceneGraphNode("Sun")->worldPosition();
}
void ShadowComponent::createDepthTexture() {
checkGLError("createDepthTexture() -- Starting configuration");
glGenTextures(1, &_shadowDepthTexture);
glBindTexture(GL_TEXTURE_2D, _shadowDepthTexture);
glTexStorage2D(
GL_TEXTURE_2D,
1,
GL_DEPTH_COMPONENT32F,
_shadowDepthTextureWidth,
_shadowDepthTextureHeight
);
/*glTexImage2D(
GL_TEXTURE_2D,
0,
GL_DEPTH_COMPONENT32F,
_shadowDepthTextureWidth,
_shadowDepthTextureHeight,
0,
GL_DEPTH_COMPONENT,
GL_FLOAT,
0
);*/
checkGLError("createDepthTexture() -- Depth testure created");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, shadowBorder);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
checkGLError("createdDepthTexture");
glGenTextures(1, &_positionInLightSpaceTexture);
glBindTexture(GL_TEXTURE_2D, _positionInLightSpaceTexture);
//glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB32F,
_shadowDepthTextureWidth,
_shadowDepthTextureHeight,
0,
GL_RGBA,
GL_FLOAT,
nullptr
);
checkGLError("createDepthTexture() -- Position/Distance buffer created");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
checkGLError("createdPositionTexture");
glBindTexture(GL_TEXTURE_2D, 0);
_shadowData.shadowDepthTexture = _shadowDepthTexture;
_shadowData.positionInLightSpaceTexture = _positionInLightSpaceTexture;
}
void ShadowComponent::createShadowFBO() {
// Saves current FBO first
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO);
/*GLint _mViewport[4];
glGetIntegerv(GL_VIEWPORT, _mViewport);*/
glGenFramebuffers(1, &_shadowFBO);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowFBO);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
_shadowDepthTexture,
0
);
glFramebufferTexture(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT3,
_positionInLightSpaceTexture,
0
);
checkGLError("createShadowFBO() -- Created Shadow Framebuffer");
//GLenum drawBuffers[] = { GL_NONE };
GLenum drawBuffers[] = { GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3 };
glDrawBuffers(4, drawBuffers);
checkFrameBufferState("createShadowFBO()");
// Restores system state
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO);
/*glViewport(
_mViewport[0],
_mViewport[1],
_mViewport[2],
_mViewport[3]
);*/
checkGLError("createShadowFBO() -- createdShadowFBO");
}
void ShadowComponent::saveDepthBuffer() {
int size = _shadowDepthTextureWidth * _shadowDepthTextureHeight;
GLubyte * buffer = new GLubyte[size];
glReadPixels(
0,
0,
_shadowDepthTextureWidth,
_shadowDepthTextureHeight,
GL_DEPTH_COMPONENT,
GL_UNSIGNED_BYTE,
buffer
);
checkGLError("readDepthBuffer To buffer");
std::fstream ppmFile;
ppmFile.open("depthBufferShadowMapping.ppm", std::fstream::out);
if (ppmFile.is_open()) {
ppmFile << "P3" << std::endl;
ppmFile << _shadowDepthTextureWidth << " " << _shadowDepthTextureHeight
<< std::endl;
ppmFile << "255" << std::endl;
std::cout << "\n\nSaving depth texture to file depthBufferShadowMapping.ppm\n\n";
int k = 0;
for (int i = 0; i < _shadowDepthTextureWidth; i++) {
for (int j = 0; j < _shadowDepthTextureHeight; j++, k++) {
unsigned int val = static_cast<unsigned int>(buffer[k]);
ppmFile << val << " " << val << " " << val << " ";
}
ppmFile << std::endl;
}
ppmFile.close();
std::cout << "Texture saved to file depthBufferShadowMapping.ppm\n\n";
}
delete[] buffer;
GLfloat * bBuffer = new GLfloat[size * 4];
glReadBuffer(GL_COLOR_ATTACHMENT3);
glReadPixels(
0,
0,
_shadowDepthTextureWidth,
_shadowDepthTextureHeight,
GL_RGBA,
GL_FLOAT,
bBuffer
);
checkGLError("readPositionBuffer To buffer");
ppmFile.clear();
ppmFile.open("positionBufferShadowMapping.ppm", std::fstream::out);
if (ppmFile.is_open()) {
ppmFile << "P3" << std::endl;
ppmFile << _shadowDepthTextureWidth << " " << _shadowDepthTextureHeight
<< std::endl;
ppmFile << "255" << std::endl;
std::cout << "\n\nSaving texture position to positionBufferShadowMapping.ppm\n\n";
float biggestValue = 0.f;
int k = 0;
for (int i = 0; i < _shadowDepthTextureWidth; i++) {
for (int j = 0; j < _shadowDepthTextureHeight; j++) {
biggestValue = bBuffer[k] > biggestValue ?
bBuffer[k] : biggestValue;
k += 4;
}
}
biggestValue /= 255.f;
k = 0;
for (int i = 0; i < _shadowDepthTextureWidth; i++) {
for (int j = 0; j < _shadowDepthTextureHeight; j++) {
ppmFile << static_cast<unsigned int>(bBuffer[k] / biggestValue) << " "
<< static_cast<unsigned int>(bBuffer[k + 1] / biggestValue) << " "
<< static_cast<unsigned int>(bBuffer[k + 2] / biggestValue) << " ";
k += 4;
}
ppmFile << std::endl;
}
ppmFile.close();
std::cout << "Texture saved to file positionBufferShadowMapping.ppm\n\n";
}
delete[] bBuffer;
}
void ShadowComponent::checkGLError(const std::string & where) const {
const GLenum error = glGetError();
switch (error) {
case GL_NO_ERROR:
break;
case GL_INVALID_ENUM:
LERRORC(
"OpenGL Invalid State",
fmt::format("Function {}: GL_INVALID_ENUM", where)
);
break;
case GL_INVALID_VALUE:
LERRORC(
"OpenGL Invalid State",
fmt::format("Function {}: GL_INVALID_VALUE", where)
);
break;
case GL_INVALID_OPERATION:
LERRORC(
"OpenGL Invalid State",
fmt::format(
"Function {}: GL_INVALID_OPERATION", where
));
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
LERRORC(
"OpenGL Invalid State",
fmt::format(
"Function {}: GL_INVALID_FRAMEBUFFER_OPERATION",
where
)
);
break;
case GL_OUT_OF_MEMORY:
LERRORC(
"OpenGL Invalid State",
fmt::format("Function {}: GL_OUT_OF_MEMORY", where)
);
break;
default:
LERRORC(
"OpenGL Invalid State",
fmt::format("Unknown error code: {0:x}", static_cast<int>(error))
);
}
}
bool ShadowComponent::isEnabled() const {
return _enabled;
}
ShadowComponent::ShadowMapData ShadowComponent::shadowMapData() const {
return _shadowData;
}
} // namespace openspace

View File

@@ -0,0 +1,160 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___SHADOWCOMPONENT___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___SHADOWCOMPONENT___H__
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/vector/vec2property.h>
#include <openspace/properties/vector/vec4property.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/triggerproperty.h>
#include <ghoul/glm.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/uniformcache.h>
#include <string>
#include <sstream>
namespace ghoul {
class Dictionary;
}
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl {
class ProgramObject;
} // namespace ghoul::opengl
namespace openspace {
struct RenderData;
struct UpdateData;
namespace documentation { struct Documentation; }
static const GLfloat shadowBorder[] = { 1.f, 1.f, 1.f, 1.f };
class ShadowComponent : public properties::PropertyOwner {
public:
struct ShadowMapData {
glm::dmat4 shadowMatrix;
// temp
glm::dmat4 worldToLightSpaceMatrix;
GLuint shadowDepthTexture;
GLuint positionInLightSpaceTexture;
};
public:
ShadowComponent(const ghoul::Dictionary& dictionary);
void initialize();
void initializeGL();
void deinitializeGL();
//bool deinitialize();
bool isReady() const;
void begin(const RenderData& data);
void end(const RenderData& data);
void update(const UpdateData& data);
static documentation::Documentation Documentation();
bool isEnabled() const;
ShadowComponent::ShadowMapData shadowMapData() const;
private:
void createDepthTexture();
void createShadowFBO();
// Debug
void saveDepthBuffer();
void checkGLError(const std::string & where) const;
private:
ShadowMapData _shadowData;
// Texture coords in [0, 1], while clip coords in [-1, 1]
const glm::dmat4 _toTextureCoordsMatrix = glm::dmat4(
glm::dvec4(0.5, 0.0, 0.0, 0.0),
glm::dvec4(0.0, 0.5, 0.0, 0.0),
glm::dvec4(0.0, 0.0, 0.5, 0.0),
glm::dvec4(0.5, 0.5, 0.5, 1.0)
);
// DEBUG
properties::TriggerProperty _saveDepthTexture;
properties::IntProperty _distanceFraction;
properties::BoolProperty _enabled;
ghoul::Dictionary _shadowMapDictionary;
int _shadowDepthTextureHeight;
int _shadowDepthTextureWidth;
GLuint _shadowDepthTexture;
GLuint _positionInLightSpaceTexture;
GLuint _shadowFBO;
GLuint _firstPassSubroutine;
GLuint _secondPassSubroutine;
GLint _defaultFBO;
GLint _mViewport[4];
GLboolean _faceCulling;
GLboolean _polygonOffSet;
GLboolean _depthIsEnabled;
GLboolean _blendIsEnabled = false;
GLenum _faceToCull;
GLenum _depthFunction;
GLfloat _polygonOffSetFactor;
GLfloat _polygonOffSetUnits;
GLfloat _colorClearValue[4];
GLfloat _depthClearValue;
glm::vec3 _sunPosition;
glm::dmat4 _shadowMatrix;
glm::dvec3 _cameraPos;
glm::dvec3 _cameraFocus;
glm::dquat _cameraRotation;
std::stringstream _serializedCamera;
// DEBUG
bool _executeDepthTextureSave;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___SHADOWCOMPONENT___H__