mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-01 08:19:51 -05:00
Planet Shadows
This commit is contained in:
@@ -48,7 +48,11 @@ namespace {
|
||||
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyRadius = "Radius";
|
||||
const std::string keyShading = "PerformShading";
|
||||
const std::string keyShadowGroup = "Shadow_Group";
|
||||
const std::string keyShadowSource = "Source";
|
||||
const std::string keyShadowCaster = "Caster";
|
||||
|
||||
const std::string keyBody = "Body";
|
||||
}
|
||||
@@ -65,8 +69,9 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
|
||||
, _performShading("performShading", "Perform Shading", true)
|
||||
, _rotation("rotation", "Rotation", 0, 0, 360)
|
||||
, _alpha(1.f)
|
||||
, _planetRadius(0.f)
|
||||
, _nightTexturePath("")
|
||||
, _hasNightTexture(false)
|
||||
, _hasNightTexture(false)
|
||||
{
|
||||
std::string name;
|
||||
bool success = dictionary.getValue(SceneGraphNode::KeyName, name);
|
||||
@@ -84,6 +89,13 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
|
||||
geometryDictionary.setValue(SceneGraphNode::KeyName, name);
|
||||
//geometryDictionary.setValue(constants::scenegraph::keyPathModule, path);
|
||||
_geometry = planetgeometry::PlanetGeometry::createFromDictionary(geometryDictionary);
|
||||
|
||||
glm::vec2 planetRadiusVec;
|
||||
success = geometryDictionary.getValue(keyRadius, planetRadiusVec);
|
||||
if (success)
|
||||
_planetRadius = planetRadiusVec[0] * glm::pow(10, planetRadiusVec[1]);
|
||||
else
|
||||
LWARNING("No Radius value expecified for " << name << " planet.");
|
||||
}
|
||||
|
||||
dictionary.getValue(keyFrame, _frame);
|
||||
@@ -120,6 +132,79 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_performShading);
|
||||
// Mainly for debugging purposes @AA
|
||||
addProperty(_rotation);
|
||||
|
||||
|
||||
// Shadow data:
|
||||
ghoul::Dictionary shadowDictionary;
|
||||
success = dictionary.getValue(keyShadowGroup, shadowDictionary);
|
||||
if (success) {
|
||||
std::vector< std::pair<std::string, float > > sourceArray;
|
||||
unsigned int sourceCounter = 1;
|
||||
while (success) {
|
||||
std::string sourceName;
|
||||
std::stringstream ss;
|
||||
ss << keyShadowSource << sourceCounter << ".Name";
|
||||
success = shadowDictionary.getValue(ss.str(), sourceName);
|
||||
if (success) {
|
||||
glm::vec2 sourceRadius;
|
||||
ss.str(std::string());
|
||||
ss << keyShadowSource << sourceCounter << ".Radius";
|
||||
success = shadowDictionary.getValue(ss.str(), sourceRadius);
|
||||
if (success) {
|
||||
sourceArray.push_back(std::pair< std::string, float>(sourceName, sourceRadius[0] * glm::pow(10, sourceRadius[1])));
|
||||
}
|
||||
else {
|
||||
// TODO: handle not success
|
||||
;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: handle not success
|
||||
;
|
||||
}
|
||||
|
||||
sourceCounter++;
|
||||
}
|
||||
|
||||
success = true;
|
||||
|
||||
std::vector< std::pair<std::string, float > > casterArray;
|
||||
unsigned int casterCounter = 1;
|
||||
while (success) {
|
||||
std::string casterName;
|
||||
std::stringstream ss;
|
||||
ss << keyShadowCaster << casterCounter << ".Name";
|
||||
success = shadowDictionary.getValue(ss.str(), casterName);
|
||||
if (success) {
|
||||
glm::vec2 casterRadius;
|
||||
ss.str(std::string());
|
||||
ss << keyShadowCaster << casterCounter << ".Radius";
|
||||
success = shadowDictionary.getValue(ss.str(), casterRadius);
|
||||
if (success) {
|
||||
casterArray.push_back(std::pair< std::string, float>(casterName, casterRadius[0] * glm::pow(10, casterRadius[1])));
|
||||
}
|
||||
else {
|
||||
// TODO: handle not success
|
||||
;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: handle not success
|
||||
;
|
||||
}
|
||||
|
||||
casterCounter++;
|
||||
}
|
||||
|
||||
for ( const auto & source : sourceArray )
|
||||
for (const auto & caster : casterArray) {
|
||||
ShadowConf sc;
|
||||
sc.source = source;
|
||||
sc.caster = caster;
|
||||
_shadowConfArray.push_back(sc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RenderablePlanet::~RenderablePlanet() {
|
||||
@@ -127,13 +212,32 @@ RenderablePlanet::~RenderablePlanet() {
|
||||
|
||||
bool RenderablePlanet::initialize() {
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
if (_programObject == nullptr && _hasNightTexture) {
|
||||
|
||||
if (_programObject == nullptr && !_shadowConfArray.empty() && _hasNightTexture) {
|
||||
// shadow program
|
||||
_programObject = renderEngine.buildRenderProgram(
|
||||
"shadowNightProgram",
|
||||
"${MODULE_BASE}/shaders/shadow_nighttexture_vs.glsl",
|
||||
"${MODULE_BASE}/shaders/shadow_nighttexture_fs.glsl");
|
||||
if (!_programObject)
|
||||
return false;
|
||||
}
|
||||
else if (_programObject == nullptr && !_shadowConfArray.empty()) {
|
||||
// shadow program
|
||||
_programObject = renderEngine.buildRenderProgram(
|
||||
"shadowProgram",
|
||||
"${MODULE_BASE}/shaders/shadow_vs.glsl",
|
||||
"${MODULE_BASE}/shaders/shadow_fs.glsl");
|
||||
if (!_programObject)
|
||||
return false;
|
||||
}
|
||||
else if (_programObject == nullptr && _hasNightTexture) {
|
||||
// Night texture program
|
||||
_programObject = renderEngine.buildRenderProgram(
|
||||
"nightTextureProgram",
|
||||
"${MODULE_BASE}/shaders/nighttexture_vs.glsl",
|
||||
"${MODULE_BASE}/shaders/nighttexture_fs.glsl");
|
||||
if (!_programObject)
|
||||
if (!_programObject)
|
||||
return false;
|
||||
}
|
||||
else if (_programObject == nullptr) {
|
||||
@@ -142,8 +246,8 @@ bool RenderablePlanet::initialize() {
|
||||
"pscstandard",
|
||||
"${MODULE_BASE}/shaders/pscstandard_vs.glsl",
|
||||
"${MODULE_BASE}/shaders/pscstandard_fs.glsl");
|
||||
if (!_programObject) return false;
|
||||
|
||||
if (!_programObject)
|
||||
return false;
|
||||
}
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
@@ -199,18 +303,28 @@ void RenderablePlanet::render(const RenderData& data)
|
||||
}
|
||||
}
|
||||
transform = transform * rot * roty * rotProp;
|
||||
|
||||
//glm::mat4 modelview = data.camera.viewMatrix()*data.camera.modelMatrix();
|
||||
//glm::vec3 camSpaceEye = (-(modelview*data.position.vec4())).xyz;
|
||||
|
||||
|
||||
// setup the data to the shader
|
||||
double lt;
|
||||
glm::dvec3 p =
|
||||
SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", {}, _time, lt);
|
||||
p *= 1000.0; // from Km to m
|
||||
psc sun_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
|
||||
|
||||
// setup the data to the shader
|
||||
// _programObject->setUniform("camdir", camSpaceEye);
|
||||
//_programObject->setUniform("light_dir", sun_pos.vec4());
|
||||
|
||||
glm::dvec3 pt =
|
||||
SpiceManager::ref().targetPosition(_target, "SUN", "GALACTIC", {}, _time, lt);
|
||||
psc tmppos = PowerScaledCoordinate::CreatePowerScaledCoordinate(pt.x, pt.y, pt.z);
|
||||
glm::vec3 cam_dir = glm::normalize(data.camera.position().vec3() - tmppos.vec3());
|
||||
|
||||
// This is camera position vector (camera direction) in world coordinates.
|
||||
//_programObject->setUniform("cam_dir", cam_dir);
|
||||
|
||||
//glm::mat4 modelview = data.camera.viewMatrix()*data.camera.modelMatrix();
|
||||
//glm::vec3 camSpaceEye = (-(modelview*data.position.vec4())).xyz;
|
||||
//_programObject->setUniform("camdir", camSpaceEye);
|
||||
|
||||
_programObject->setUniform("transparency", _alpha);
|
||||
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
|
||||
_programObject->setUniform("ModelTransform", transform);
|
||||
@@ -235,6 +349,74 @@ void RenderablePlanet::render(const RenderData& data)
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// Shadow calculations..
|
||||
if (!_shadowConfArray.empty()) {
|
||||
std::vector<ShadowRenderingStruct> shadowDataArray;
|
||||
shadowDataArray.reserve(_shadowConfArray.size());
|
||||
|
||||
for (const auto & shadowConf : _shadowConfArray) {
|
||||
// TO REMEMBER: all distances and lengths in world coordinates are in meters!!! We need to move this to view space...
|
||||
// Getting source and caster:
|
||||
glm::dvec3 sourcePos = SpiceManager::ref().targetPosition(shadowConf.source.first, "SUN", "GALACTIC", {}, _time, lt);
|
||||
sourcePos *= 1000.0; // converting to meters
|
||||
glm::dvec3 casterPos = SpiceManager::ref().targetPosition(shadowConf.caster.first, "SUN", "GALACTIC", {}, _time, lt);
|
||||
casterPos *= 1000.0; // converting to meters
|
||||
psc caster_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(casterPos.x, casterPos.y, casterPos.z);
|
||||
|
||||
|
||||
// First we determine if the caster is shadowing the current planet (all calculations in World Coordinates):
|
||||
glm::vec3 planetCasterVec = (caster_pos - data.position).vec3();
|
||||
glm::vec3 sourceCasterVec = glm::vec3(casterPos - sourcePos);
|
||||
float sc_length = glm::length(sourceCasterVec);
|
||||
glm::vec3 planetCaster_proj = (glm::dot(planetCasterVec, sourceCasterVec) / (sc_length*sc_length)) * sourceCasterVec;
|
||||
float d_test = glm::length(planetCasterVec - planetCaster_proj);
|
||||
float xp_test = shadowConf.caster.second * sc_length / (shadowConf.source.second + shadowConf.caster.second);
|
||||
float rp_test = shadowConf.caster.second * (glm::length(planetCaster_proj) + xp_test) / xp_test;
|
||||
|
||||
ShadowRenderingStruct shadowData;
|
||||
shadowData.isShadowing = false;
|
||||
if ((d_test - rp_test) < _planetRadius) {
|
||||
// The current caster is shadowing the current planet
|
||||
shadowData.isShadowing = true;
|
||||
shadowData.rs = shadowConf.source.second;
|
||||
shadowData.rc = shadowConf.caster.second;
|
||||
shadowData.sourceCasterVec = sourceCasterVec;
|
||||
shadowData.xp = xp_test;
|
||||
shadowData.xu = shadowData.rc * sc_length / (shadowData.rs - shadowData.rc);
|
||||
shadowData.casterPositionVec = glm::vec3(casterPos);
|
||||
}
|
||||
shadowDataArray.push_back(shadowData);
|
||||
}
|
||||
|
||||
const std::string uniformVarName("shadowDataArray[");
|
||||
unsigned int counter = 0;
|
||||
for (const auto & sd : shadowDataArray) {
|
||||
std::stringstream ss;
|
||||
ss << uniformVarName << counter << "].isShadowing";
|
||||
_programObject->setUniform(ss.str(), sd.isShadowing);
|
||||
if (sd.isShadowing) {
|
||||
ss.str(std::string());
|
||||
ss << uniformVarName << counter << "].xp";
|
||||
_programObject->setUniform(ss.str(), sd.xp);
|
||||
ss.str(std::string());
|
||||
ss << uniformVarName << counter << "].xu";
|
||||
_programObject->setUniform(ss.str(), sd.xu);
|
||||
/*ss.str(std::string());
|
||||
ss << uniformVarName << counter << "].rs";
|
||||
_programObject->setUniform(ss.str(), sd.rs);*/
|
||||
ss.str(std::string());
|
||||
ss << uniformVarName << counter << "].rc";
|
||||
_programObject->setUniform(ss.str(), sd.rc);
|
||||
ss.str(std::string());
|
||||
ss << uniformVarName << counter << "].sourceCasterVec";
|
||||
_programObject->setUniform(ss.str(), sd.sourceCasterVec);
|
||||
ss.str(std::string());
|
||||
ss << uniformVarName << counter << "].casterPositionVec";
|
||||
_programObject->setUniform(ss.str(), sd.casterPositionVec);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
// render
|
||||
_geometry->render();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user