Planet Shadows

This commit is contained in:
Jonathas Costa
2016-05-16 15:41:04 -04:00
parent 31e6b0e2b3
commit 3fa5ed39d5
9 changed files with 586 additions and 38 deletions
+193 -11
View File
@@ -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();