implement shadow mapping for image projections on non-convex bodies

This commit is contained in:
Emil Axelsson
2016-08-19 16:56:57 +02:00
parent c4c9396441
commit 6d56b1d38a
10 changed files with 240 additions and 70 deletions

View File

@@ -62,10 +62,9 @@ return {
Method = "ELLIPSOID",
Aberration = "NONE",
Fovy = 5.00,
Aspect = 1,
Near = 0.01,
Far = 1000000,
Aspect = 1
},
BoundingSphereRadius = 5000.0
},
Ephemeris = {

View File

@@ -40,6 +40,7 @@ namespace {
const std::string keyDestination = "Rotation.Destination";
const std::string keyBody = "Body";
const std::string keyGeometry = "Geometry";
const std::string keyBoundingSphereRadius = "BoundingSphereRadius";
const std::string keyTextureColor = "Textures.Color";
const std::string keyTextureProject = "Textures.Project";
@@ -97,7 +98,10 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di
completeSuccess &= _projectionComponent.initializeProjectionSettings(dictionary);
openspace::SpiceManager::ref().addFrame(_target, _source);
setBoundingSphere(pss(1.f, 9.f));
float boundingSphereRadius = 1.0e9;
dictionary.getValue(keyBoundingSphereRadius, boundingSphereRadius);
setBoundingSphere(PowerScaledScalar::CreatePSS(boundingSphereRadius));
Renderable::addProperty(_performShading);
Renderable::addProperty(_rotation);
@@ -130,11 +134,20 @@ bool RenderableModelProjection::initialize() {
ghoul::opengl::ProgramObject::IgnoreError::Yes
);
_depthFboProgramObject = ghoul::opengl::ProgramObject::Build("DepthPass",
"${MODULE_NEWHORIZONS}/shaders/renderableModelDepth_vs.glsl",
"${MODULE_NEWHORIZONS}/shaders/renderableModelDepth_fs.glsl");
completeSuccess &= loadTextures();
completeSuccess &= _projectionComponent.initialize();
auto bs = getBoundingSphere();
completeSuccess &= _geometry->initialize(this);
setBoundingSphere(bs); // ignore bounding sphere set by geometry.
completeSuccess &= !_source.empty();
completeSuccess &= !_destination.empty();
@@ -164,7 +177,6 @@ void RenderableModelProjection::render(const RenderData& data) {
if (_projectionComponent.needsClearProjection())
_projectionComponent.clearAllProjections();
_camScaling = data.camera.scaling();
_up = data.camera.lookUpVectorCameraSpace();
if (_capture && _projectionComponent.doesPerformProjection())
@@ -205,6 +217,9 @@ void RenderableModelProjection::update(const UpdateData& data) {
if (_fboProgramObject->isDirty())
_fboProgramObject->rebuildFromFile();
if (_depthFboProgramObject->isDirty())
_depthFboProgramObject->rebuildFromFile();
_time = data.time;
if (openspace::ImageSequencer::ref().isReady()) {
@@ -236,8 +251,18 @@ void RenderableModelProjection::update(const UpdateData& data) {
void RenderableModelProjection::imageProjectGPU(
std::shared_ptr<ghoul::opengl::Texture> projectionTexture)
{
_projectionComponent.imageProjectBegin();
_projectionComponent.depthMapRenderBegin();
_depthFboProgramObject->activate();
_depthFboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix);
_depthFboProgramObject->setUniform("ModelTransform", _transform);
_geometry->setUniforms(*_fboProgramObject);
_geometry->render();
_depthFboProgramObject->deactivate();
_projectionComponent.depthMapRenderEnd();
_projectionComponent.imageProjectBegin();
_fboProgramObject->activate();
ghoul::opengl::TextureUnit unitFbo;
@@ -245,9 +270,17 @@ void RenderableModelProjection::imageProjectGPU(
projectionTexture->bind();
_fboProgramObject->setUniform("projectionTexture", unitFbo);
ghoul::opengl::TextureUnit unitDepthFbo;
unitDepthFbo.activate();
_projectionComponent.depthTexture().bind();
_fboProgramObject->setUniform("depthTexture", unitDepthFbo);
glm::vec4 debugVector(0.0, 0.0, 0.0, 1.0);
glm::vec4 debugTransformed = _projectorMatrix * _transform * debugVector;
debugTransformed /= debugTransformed.w;
_fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix);
_fboProgramObject->setUniform("ModelTransform", _transform);
_fboProgramObject->setUniform("_scaling", _camScaling);
_fboProgramObject->setUniform("boresight", _boresight);
_geometry->setUniforms(*_fboProgramObject);
@@ -309,19 +342,24 @@ void RenderableModelProjection::attitudeParameters(double time) {
time, lightTime);
psc position = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
position[3] += (3 + _camScaling[1]);
position[3] += 3;
glm::vec3 cpos = position.vec3();
float distance = glm::length(cpos);
float radius = getBoundingSphere().lengthf();
_projectorMatrix = _projectionComponent.computeProjectorMatrix(
cpos, boresight, _up, _instrumentMatrix,
_projectionComponent.fieldOfViewY(),
_projectionComponent.aspectRatio(),
_projectionComponent.nearPlane(),
_projectionComponent.farPlane(),
distance - radius,
distance + radius,
_boresight
);
}
void RenderableModelProjection::project() {
for (auto img : _imageTimes) {
attitudeParameters(img.startTime);

View File

@@ -74,6 +74,7 @@ private:
std::unique_ptr<ghoul::opengl::ProgramObject> _programObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _fboProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _depthFboProgramObject;
std::unique_ptr<ghoul::opengl::Texture> _baseTexture;
@@ -100,7 +101,6 @@ private:
bool _capture;
psc _sunPosition;
properties::BoolProperty _performShading;
};

View File

@@ -47,6 +47,7 @@ namespace {
const std::string keyFrame = "Frame";
const std::string keyGeometry = "Geometry";
const std::string keyRadius = "Geometry.Radius";
const std::string keyShading = "PerformShading";
const std::string keyBody = "Body";
const std::string _mainFrame = "GALACTIC";
@@ -103,6 +104,10 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
if (success)
_heightMapTexturePath = absPath(heightMapPath);
glm::vec2 radius = glm::vec2(1.0, 9.0);
dictionary.getValue(keyRadius, radius);
setBoundingSphere(pss(radius));
addPropertySubOwner(_geometry.get());
addPropertySubOwner(_projectionComponent);
@@ -136,7 +141,6 @@ bool RenderablePlanetProjection::initialize() {
completeSuccess &= loadTextures();
completeSuccess &= _projectionComponent.initialize();
completeSuccess &= _geometry->initialize(this);
if (completeSuccess) {
@@ -287,6 +291,9 @@ void RenderablePlanetProjection::attitudeParameters(double time) {
//position[3] += 3;
glm::vec3 cpos = position.vec3();
float distance = glm::length(cpos);
float radius = getBoundingSphere().lengthf();
_projectorMatrix = _projectionComponent.computeProjectorMatrix(
cpos,
bs,
@@ -294,8 +301,8 @@ void RenderablePlanetProjection::attitudeParameters(double time) {
_instrumentMatrix,
_projectionComponent.fieldOfViewY(),
_projectionComponent.aspectRatio(),
_projectionComponent.nearPlane(),
_projectionComponent.farPlane(),
distance - radius,
distance + radius,
_boresight
);
}

View File

@@ -0,0 +1,30 @@
/*****************************************************************************************
* *
* 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__
void main() {
gl_FragColor = vec4(1.0);
//gl_FragDepth = gl_FragCoord.z;
}

View File

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

View File

@@ -24,42 +24,41 @@
#version __CONTEXT__
#include "PowerScaling/powerScalingMath.hglsl"
#include "PowerScaling/powerScaling_vs.hglsl"
in vec4 vs_position;
in vec4 vs_ndc;
in vec4 vs_normal;
in vec2 vs_uv;
in vec4 ProjTexCoord;
out vec4 color;
uniform sampler2D projectionTexture;
uniform sampler2D depthTexture;
uniform mat4 ModelTransform;
uniform vec2 _scaling;
uniform vec3 boresight;
uniform vec4 debugColor;
bool inRange(float x, float a, float b) {
return (x >= a && x <= b);
}
void main() {
vec2 uv = vec2(0.5,0.5)*vs_uv+vec2(0.5,0.5);
vec3 n = normalize(vs_normal.xyz);
vec4 projected = ProjTexCoord;
vec4 projected = vs_ndc;
vec2 uv = vec2(0.5) * projected.xy + vec2(0.5);
//normalize
projected.x /= projected.w;
projected.y /= projected.w;
//invert gl coordinates
projected.x = 1 - projected.x;
if ((inRange(projected.x, 0, 1) && inRange(projected.y, 0, 1)) && (dot(n, boresight) < 0)) {
color = texture(projectionTexture, projected.xy);
float thisDepth = projected.z * 0.5 + 0.5;
float closestDepth = texture(depthTexture, uv).r;
float epsilon = 0.001;
if (inRange(uv.x, 0.0, 1.0) && inRange(uv.y, 0.0, 1.0) &&
dot(n, boresight) < 0 && thisDepth <= closestDepth + epsilon) {
color = texture(projectionTexture, uv);
color.a = 1.0;
}
else {
color = vec4(vec3(0.0), 1.0);
} else {
color = vec4(vec3(0.0), 0.0);
}
}

View File

@@ -33,26 +33,20 @@ layout(location = 2) in vec3 in_normal;
out vec4 vs_position;
out vec4 vs_normal;
out vec2 vs_uv;
out vec4 ProjTexCoord;
out vec4 vs_ndc;
uniform mat4 ProjectorMatrix;
uniform mat4 ModelTransform;
uniform vec2 _scaling;
uniform vec3 boresight;
void main() {
vs_position = in_position;
vec4 tmp = in_position;
vec4 position = pscTransform(tmp, ModelTransform);
vs_position = position;
vec4 raw_pos = psc_to_meter(in_position, _scaling);
ProjTexCoord = ProjectorMatrix * ModelTransform * raw_pos;
vec4 raw_pos = psc_to_meter(in_position, vec2(1.0, 0.0));
vs_position = ProjectorMatrix * ModelTransform * raw_pos;
vs_normal = normalize(ModelTransform * vec4(in_normal,0));
vs_ndc = vs_position / vs_position.w;
//match clipping plane
vec2 texco = (in_st * 2) - 1;
vs_uv = texco;

View File

@@ -41,8 +41,6 @@ namespace {
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";
@@ -81,8 +79,10 @@ ProjectionComponent::ProjectionComponent()
}
bool ProjectionComponent::initialize() {
bool a = generateProjectionLayerTexture();
bool b = auxiliaryRendertarget();
bool success = generateProjectionLayerTexture();
success &= generateDepthTexture();
success &= auxiliaryRendertarget();
success &= depthRendertarget();
using std::unique_ptr;
using ghoul::opengl::Texture;
@@ -98,7 +98,7 @@ bool ProjectionComponent::initialize() {
}
_placeholderTexture = std::move(texture);
return a && b;
return success;
}
bool ProjectionComponent::deinitialize() {
@@ -120,8 +120,7 @@ bool ProjectionComponent::initializeProjectionSettings(const Dictionary& diction
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";
@@ -227,11 +226,63 @@ void ProjectionComponent::imageProjectBegin() {
);
}
ghoul::opengl::Texture& ProjectionComponent::depthTexture() {
return *_depthTexture;
}
void ProjectionComponent::depthMapRenderBegin() {
// keep handle to the current bound FBO
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO);
glGetIntegerv(GL_VIEWPORT, _viewport);
glBindFramebuffer(GL_FRAMEBUFFER, _depthFboID);
glEnable(GL_DEPTH_TEST);
glViewport(
0, 0,
static_cast<GLsizei>(_depthTexture->width()),
static_cast<GLsizei>(_depthTexture->height())
);
glClear(GL_DEPTH_BUFFER_BIT);
}
void ProjectionComponent::depthMapRenderEnd() {
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO);
glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]);
}
void ProjectionComponent::imageProjectEnd() {
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO);
glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]);
}
bool ProjectionComponent::depthRendertarget() {
GLint defaultFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
// setup FBO
glGenFramebuffers(1, &_depthFboID);
glBindFramebuffer(GL_FRAMEBUFFER, _depthFboID);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
*_depthTexture,
0);
glDrawBuffer(GL_NONE);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
return false;
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
return true;
}
bool ProjectionComponent::auxiliaryRendertarget() {
bool completeSuccess = true;
@@ -266,26 +317,27 @@ glm::mat4 ProjectionComponent::computeProjectorMatrix(const glm::vec3 loc, glm::
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 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);
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;
return projProjectionMatrix*projViewMatrix;
}
bool ProjectionComponent::doesPerformProjection() const {
@@ -328,14 +380,6 @@ float ProjectionComponent::aspectRatio() const {
return _aspectRatio;
}
float ProjectionComponent::nearPlane() const {
return _nearPlane;
}
float ProjectionComponent::farPlane() const {
return _farPlane;
}
void ProjectionComponent::clearAllProjections() {
// keep handle to the current bound FBO
GLint defaultFBO;
@@ -402,4 +446,24 @@ bool ProjectionComponent::generateProjectionLayerTexture() {
}
bool ProjectionComponent::generateDepthTexture() {
int maxSize = OpenGLCap.max2DTextureSize() / 2;
LINFO(
"Creating depth texture of size '" << maxSize / 2 << ", " << maxSize / 2 << "'"
);
_depthTexture = std::make_unique<ghoul::opengl::Texture>(
glm::uvec3(maxSize / 2, maxSize / 2, 1),
ghoul::opengl::Texture::Format::DepthComponent,
GL_DEPTH_COMPONENT32F
);
if (_depthTexture)
_depthTexture->uploadTexture();
return _depthTexture != nullptr;
}
} // namespace openspace

View File

@@ -46,11 +46,17 @@ public:
bool initializeProjectionSettings(const ghoul::Dictionary& dictionary);
bool initializeParser(const ghoul::Dictionary& dictionary);
ghoul::opengl::Texture& ProjectionComponent::depthTexture();
void imageProjectBegin();
void imageProjectEnd();
void depthMapRenderBegin();
void depthMapRenderEnd();
bool generateProjectionLayerTexture();
bool generateDepthTexture();
bool auxiliaryRendertarget();
bool depthRendertarget();
std::shared_ptr<ghoul::opengl::Texture> loadProjectionTexture(
const std::string& texturePath,
@@ -82,8 +88,6 @@ public:
float fieldOfViewY() const;
float aspectRatio() const;
float nearPlane() const;
float farPlane() const;
protected:
properties::BoolProperty _performProjection;
@@ -91,7 +95,7 @@ protected:
properties::FloatProperty _projectionFading;
std::unique_ptr<ghoul::opengl::Texture> _projectionTexture;
std::unique_ptr<ghoul::opengl::Texture> _depthTexture;
std::shared_ptr<ghoul::opengl::Texture> _placeholderTexture;
std::string _instrumentID;
@@ -101,10 +105,9 @@ protected:
std::vector<std::string> _potentialTargets;
float _fovy;
float _aspectRatio;
float _nearPlane;
float _farPlane;
GLuint _fboID;
GLuint _depthFboID;
GLint _defaultFBO;
GLint _viewport[4];