Atmosphere frustum culling and distance culling enabled.

This commit is contained in:
Jonathas Costa
2017-07-27 13:42:15 -04:00
parent c135cadb51
commit efeca7eac6
4 changed files with 348 additions and 335 deletions

View File

@@ -99,8 +99,8 @@ return {
--"moon",
"lodglobes/earth",
--"lodglobes/mars",
--"lodglobes/moon",
"lodglobes/mars",
"lodglobes/moon",
--"satellites",
--"mars-satellites",
--"toyvolume",

View File

@@ -217,90 +217,105 @@ void AtmosphereDeferredcaster::deinitialize()
void AtmosphereDeferredcaster::preRaycast(const RenderData & renderData, const DeferredcastData& deferredData,
ghoul::opengl::ProgramObject& program)
{
program.setUniform("Rg", _atmospherePlanetRadius);
program.setUniform("Rt", _atmosphereRadius);
program.setUniform("AverageGroundReflectance", _planetAverageGroundReflectance);
program.setUniform("HR", _rayleighHeightScale);
program.setUniform("betaRayleigh", _rayleighScatteringCoeff);
program.setUniform("HM", _mieHeightScale);
program.setUniform("betaMieScattering", _mieScatteringCoeff);
program.setUniform("betaMieExtinction", _mieExtinctionCoeff);
program.setUniform("mieG", _miePhaseConstant);
program.setUniform("sunRadiance", _sunRadianceIntensity);
program.setUniform("ozoneLayerEnabled", (bool)_ozoneEnabled);
program.setUniform("HO", _ozoneHeightScale);
program.setUniform("betaOzoneExtinction", _ozoneExtinctionCoeff);
// Atmosphere Frustum Culling
glm::dvec3 tPlanetPosWorld = glm::dvec3(_modelTransform * glm::dvec4(0.0, 0.0, 0.0, 1.0));
program.setUniform("exposure", _exposureConstant);
program.setUniform("backgroundExposure", _exposureBackgroundConstant);
program.setUniform("gamma", _gammaConstant);
program.setUniform("RenderableClass", static_cast<int>(_renderableClass));
program.setUniform("TRANSMITTANCE_W", (int)_transmittance_table_width);
program.setUniform("TRANSMITTANCE_H", (int)_transmittance_table_height);
program.setUniform("SKY_W", (int)_irradiance_table_width);
program.setUniform("SKY_H", (int)_irradiance_table_height);
program.setUniform("OTHER_TEXTURES_W", (int)_delta_e_table_width);
program.setUniform("OTHER_TEXTURES_H", (int)_delta_e_table_height);
program.setUniform("SAMPLES_R", (int)_r_samples);
program.setUniform("SAMPLES_MU", (int)_mu_samples);
program.setUniform("SAMPLES_MU_S", (int)_mu_s_samples);
program.setUniform("SAMPLES_NU", (int)_nu_samples);
program.setUniform("ModelTransformMatrix", _modelTransform);
// Object Space
glm::dmat4 inverseModelMatrix = glm::inverse(_modelTransform);
program.setUniform("dInverseModelTransformMatrix", inverseModelMatrix);
// The following scale comes from PSC transformations.
float fScaleFactor = renderData.camera.scaling().x * pow(10.0, renderData.camera.scaling().y);
glm::dmat4 dfScaleCamTransf = glm::scale(glm::dvec3(fScaleFactor));
program.setUniform("dInverseScaleTransformMatrix", glm::inverse(dfScaleCamTransf));
// World to Eye Space in OS
program.setUniform("dInverseCamRotTransform", glm::mat4_cast((glm::dquat)renderData.camera.rotationQuaternion()));
program.setUniform("dInverseSgctEyeToWorldTranform", glm::inverse(renderData.camera.combinedViewMatrix()));
// Eye Space in OS to Eye Space in SGCT
glm::dmat4 dOsEye2SGCTEye = glm::dmat4(renderData.camera.viewMatrix());
glm::dmat4 dSgctEye2OSEye = glm::inverse(dOsEye2SGCTEye);
program.setUniform("dSgctEyeToOSEyeTranform", dSgctEye2OSEye);
// Eye Space in SGCT to Projection (Clip) Space in SGCT
glm::dmat4 dSgctEye2Clip = glm::dmat4(renderData.camera.projectionMatrix());
glm::dmat4 dInverseProjection = glm::inverse(dSgctEye2Clip);
program.setUniform("dInverseSgctProjectionMatrix", dInverseProjection);
program.setUniform("dObjpos", glm::dvec4(renderData.position.dvec3(), 1.0));
program.setUniform("dCampos", renderData.camera.positionVec3());
double lt;
glm::dvec3 sunPosWorld = SpiceManager::ref().targetPosition("SUN", "SUN", "GALACTIC", {}, _time, lt);
glm::dvec4 sunPosObj = glm::dvec4(0.0);
// Sun following camera position
if (_sunFollowingCameraEnabled) {
sunPosObj = inverseModelMatrix * glm::dvec4(renderData.camera.positionVec3(), 1.0);
if (glm::distance(tPlanetPosWorld, renderData.camera.positionVec3()) > DISTANCE_CULLING) {
program.setUniform("cullAtmosphere", 1);
}
else {
if (_renderableClass == RenderablePlanet) {
sunPosObj = inverseModelMatrix *
glm::dvec4(sunPosWorld - renderData.position.dvec3(), 1.0);
glm::dmat4 MV = glm::dmat4(renderData.camera.sgctInternal.projectionMatrix()) * renderData.camera.combinedViewMatrix();
if (!isAtmosphereInFrustum(glm::value_ptr(MV), tPlanetPosWorld, (_atmosphereRadius + 2.0)*1000.0)) {
program.setUniform("cullAtmosphere", 1);
}
else if (_renderableClass == RenderableGlobe) {
sunPosObj = inverseModelMatrix *
glm::dvec4(sunPosWorld - renderData.modelTransform.translation, 1.0);
}
}
// Sun Position in Object Space
program.setUniform("sunDirectionObj", glm::normalize(glm::dvec3(sunPosObj)));
program.setUniform("ellipsoidRadii", _ellipsoidRadii);
else {
program.setUniform("cullAtmosphere", 0);
program.setUniform("Rg", _atmospherePlanetRadius);
program.setUniform("Rt", _atmosphereRadius);
program.setUniform("AverageGroundReflectance", _planetAverageGroundReflectance);
program.setUniform("HR", _rayleighHeightScale);
program.setUniform("betaRayleigh", _rayleighScatteringCoeff);
program.setUniform("HM", _mieHeightScale);
program.setUniform("betaMieScattering", _mieScatteringCoeff);
program.setUniform("betaMieExtinction", _mieExtinctionCoeff);
program.setUniform("mieG", _miePhaseConstant);
program.setUniform("sunRadiance", _sunRadianceIntensity);
program.setUniform("ozoneLayerEnabled", (bool)_ozoneEnabled);
program.setUniform("HO", _ozoneHeightScale);
program.setUniform("betaOzoneExtinction", _ozoneExtinctionCoeff);
program.setUniform("exposure", _exposureConstant);
program.setUniform("backgroundExposure", _exposureBackgroundConstant);
program.setUniform("gamma", _gammaConstant);
program.setUniform("RenderableClass", static_cast<int>(_renderableClass));
program.setUniform("TRANSMITTANCE_W", (int)_transmittance_table_width);
program.setUniform("TRANSMITTANCE_H", (int)_transmittance_table_height);
program.setUniform("SKY_W", (int)_irradiance_table_width);
program.setUniform("SKY_H", (int)_irradiance_table_height);
program.setUniform("OTHER_TEXTURES_W", (int)_delta_e_table_width);
program.setUniform("OTHER_TEXTURES_H", (int)_delta_e_table_height);
program.setUniform("SAMPLES_R", (int)_r_samples);
program.setUniform("SAMPLES_MU", (int)_mu_samples);
program.setUniform("SAMPLES_MU_S", (int)_mu_s_samples);
program.setUniform("SAMPLES_NU", (int)_nu_samples);
program.setUniform("ModelTransformMatrix", _modelTransform);
// Object Space
glm::dmat4 inverseModelMatrix = glm::inverse(_modelTransform);
program.setUniform("dInverseModelTransformMatrix", inverseModelMatrix);
// The following scale comes from PSC transformations.
float fScaleFactor = renderData.camera.scaling().x * pow(10.0, renderData.camera.scaling().y);
glm::dmat4 dfScaleCamTransf = glm::scale(glm::dvec3(fScaleFactor));
program.setUniform("dInverseScaleTransformMatrix", glm::inverse(dfScaleCamTransf));
// World to Eye Space in OS
program.setUniform("dInverseCamRotTransform", glm::mat4_cast((glm::dquat)renderData.camera.rotationQuaternion()));
program.setUniform("dInverseSgctEyeToWorldTranform", glm::inverse(renderData.camera.combinedViewMatrix()));
// Eye Space in OS to Eye Space in SGCT
glm::dmat4 dOsEye2SGCTEye = glm::dmat4(renderData.camera.viewMatrix());
glm::dmat4 dSgctEye2OSEye = glm::inverse(dOsEye2SGCTEye);
program.setUniform("dSgctEyeToOSEyeTranform", dSgctEye2OSEye);
// Eye Space in SGCT to Projection (Clip) Space in SGCT
glm::dmat4 dSgctEye2Clip = glm::dmat4(renderData.camera.projectionMatrix());
glm::dmat4 dInverseProjection = glm::inverse(dSgctEye2Clip);
program.setUniform("dInverseSgctProjectionMatrix", dInverseProjection);
program.setUniform("dObjpos", glm::dvec4(renderData.position.dvec3(), 1.0));
program.setUniform("dCampos", renderData.camera.positionVec3());
double lt;
glm::dvec3 sunPosWorld = SpiceManager::ref().targetPosition("SUN", "SUN", "GALACTIC", {}, _time, lt);
glm::dvec4 sunPosObj = glm::dvec4(0.0);
// Sun following camera position
if (_sunFollowingCameraEnabled) {
sunPosObj = inverseModelMatrix * glm::dvec4(renderData.camera.positionVec3(), 1.0);
}
else {
if (_renderableClass == RenderablePlanet) {
sunPosObj = inverseModelMatrix *
glm::dvec4(sunPosWorld - renderData.position.dvec3(), 1.0);
}
else if (_renderableClass == RenderableGlobe) {
sunPosObj = inverseModelMatrix *
glm::dvec4(sunPosWorld - renderData.modelTransform.translation, 1.0);
}
}
// Sun Position in Object Space
program.setUniform("sunDirectionObj", glm::normalize(glm::dvec3(sunPosObj)));
program.setUniform("ellipsoidRadii", _ellipsoidRadii);
}
}
_transmittanceTableTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture);
program.setUniform("transmittanceTexture", _transmittanceTableTextureUnit);
@@ -311,16 +326,7 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData & renderData, const D
_inScatteringTableTextureUnit.activate();
glBindTexture(GL_TEXTURE_3D, _inScatteringTableTexture);
program.setUniform("inscatterTexture", _inScatteringTableTextureUnit);
// Atmosphere Frustum Culling
glm::dmat4 MV = glm::dmat4(renderData.camera.sgctInternal.projectionMatrix()) * renderData.camera.combinedViewMatrix();
glm::dvec3 tPlanetPosWorld = glm::dvec3(_modelTransform * glm::dvec4(0.0, 0.0, 0.0, 1.0));
if (isAtmosphereInFrustum(glm::value_ptr(MV), tPlanetPosWorld, (_atmosphereRadius + 2.0)*1000.0))
std::cout << "========= Inside Frustum ========" << std::endl;
else
std::cout << "--------- Outside Frustum -------" << std::endl;
program.setUniform("inscatterTexture", _inScatteringTableTextureUnit);
}
void AtmosphereDeferredcaster::postRaycast(const RenderData & renderData, const DeferredcastData& deferredData,
@@ -1521,25 +1527,26 @@ void AtmosphereDeferredcaster::saveTextureToPPMFile(const GLenum color_buffer_at
bool AtmosphereDeferredcaster::isAtmosphereInFrustum(const double * MVMatrix, const glm::dvec3 position, const double radius) const {
// Frustum Planes
glm::dvec3 col1(MVMatrix[0], MVMatrix[1], MVMatrix[2]);
glm::dvec3 col2(MVMatrix[4], MVMatrix[5], MVMatrix[6]);
glm::dvec3 col3(MVMatrix[8], MVMatrix[9], MVMatrix[10]);
glm::dvec3 col4(MVMatrix[12], MVMatrix[13], MVMatrix[14]);
glm::dvec3 col1(MVMatrix[0], MVMatrix[4], MVMatrix[8]);
glm::dvec3 col2(MVMatrix[1], MVMatrix[5], MVMatrix[9]);
glm::dvec3 col3(MVMatrix[2], MVMatrix[6], MVMatrix[10]);
glm::dvec3 col4(MVMatrix[3], MVMatrix[7], MVMatrix[11]);
glm::dvec3 leftNormal = col4 + col1;
glm::dvec3 rightNormal = col4 - col1;
glm::dvec3 leftNormal = col4 + col1;
glm::dvec3 rightNormal = col4 - col1;
glm::dvec3 bottomNormal = col4 + col2;
glm::dvec3 topNormal = col4 - col2;
glm::dvec3 nearNormal = col3 + col4; // maybe only col3?
glm::dvec3 farNormal = col4 - col3;
glm::dvec3 topNormal = col4 - col2;
glm::dvec3 nearNormal = col3 + col4;
glm::dvec3 farNormal = col4 - col3;
// Plane Distances
double leftDistance = MVMatrix[15] + MVMatrix[3];
double rightDistance = MVMatrix[15] - MVMatrix[3];
double bottomDistance = MVMatrix[15] + MVMatrix[7];
double topDistance = MVMatrix[15] - MVMatrix[7];
double nearDistance = MVMatrix[15] + MVMatrix[11];
double farDistance = MVMatrix[15] - MVMatrix[11];
double leftDistance = MVMatrix[15] + MVMatrix[12];
double rightDistance = MVMatrix[15] - MVMatrix[12];
double bottomDistance = MVMatrix[15] + MVMatrix[13];
double topDistance = MVMatrix[15] - MVMatrix[13];
double nearDistance = MVMatrix[15] + MVMatrix[14];
double farDistance = MVMatrix[15] - MVMatrix[14];
// Normalize Planes
double invMag = 1.0 / glm::length(leftNormal);
@@ -1565,7 +1572,7 @@ bool AtmosphereDeferredcaster::isAtmosphereInFrustum(const double * MVMatrix, co
invMag = 1.0 / glm::length(farNormal);
farNormal *= invMag;
farDistance *= invMag;
if ((glm::dot(leftNormal, position) + leftDistance) < -radius) {
return false;
} else if ((glm::dot(rightNormal, position) + rightDistance) < -radius) {
@@ -1576,9 +1583,9 @@ bool AtmosphereDeferredcaster::isAtmosphereInFrustum(const double * MVMatrix, co
return false;
} else if ((glm::dot(nearNormal, position) + nearDistance) < -radius) {
return false;
} else if ((glm::dot(farNormal, position) + farDistance) < -radius) {
} /*else if ((glm::dot(farNormal, position) + farDistance) < -radius) {
return false;
}
}*/
return true;
}

View File

@@ -120,6 +120,9 @@ private:
bool isAtmosphereInFrustum(const double * MVMatrix, const glm::dvec3 position, const double radius) const;
private:
const double DISTANCE_CULLING = 1e10;
std::unique_ptr<ghoul::opengl::ProgramObject> _transmittanceProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _irradianceProgramObject;
std::unique_ptr<ghoul::opengl::ProgramObject> _irradianceSupTermsProgramObject;

View File

@@ -75,6 +75,7 @@ in vec3 interpolatedNDCPos;
// a RenderableGlobe
uniform int RenderableClass;
uniform int nAaSamples;
uniform int cullAtmosphere;
// Background exposure hack
uniform float backgroundExposure;
@@ -501,240 +502,242 @@ vec3 sunColor(const vec3 x, const float t, const vec3 v, const vec3 s, const flo
return transmittance * sunFinalColor;
}
void main() {
//float mainDepth = 0.0;
vec4 meanColor = vec4(0.0);
vec4 meanNormal = vec4(0.0);
vec4 meanPosition = vec4(0.0);
vec4 meanOtherData = vec4(0.0);
//vec4 positionArray[nAaSamples];
//vec4 positionArray[8];
float maxAlpha = -1.0;
for (int i = 0; i < nAaSamples; i++) {
meanNormal += texelFetch(mainNormalTexture, ivec2(gl_FragCoord), i);
vec4 color = texelFetch(mainColorTexture, ivec2(gl_FragCoord), i);
if ( color.a > maxAlpha )
maxAlpha = color.a;
meanColor += color;
meanPosition += texelFetch(mainPositionTexture, ivec2(gl_FragCoord), i);
meanOtherData += texelFetch(otherDataTexture, ivec2(gl_FragCoord), i);
//positionArray[i] = texelFetch(mainPositionTexture, ivec2(gl_FragCoord), i);
//mainDepth += denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), i).x);
}
float invNaaSamples = 1.0/nAaSamples;
meanColor *= invNaaSamples;
meanNormal *= invNaaSamples;
meanPosition *= invNaaSamples;
meanOtherData *= invNaaSamples;
//mainDepth /= nAaSamples;
meanColor.a = maxAlpha;
/*
// Temporary:
meanNormal += texelFetch(mainNormalTexture, ivec2(gl_FragCoord), 0);
meanColor += texelFetch(mainColorTexture, ivec2(gl_FragCoord), 0);;
meanPosition += texelFetch(mainPositionTexture, ivec2(gl_FragCoord), 0);
meanOtherData += texelFetch(otherDataTexture, ivec2(gl_FragCoord), 0);
*/
// Ray in object space
dRay ray;
dvec4 planetPositionObjectCoords = dvec4(0.0);
dvec4 cameraPositionInObject = dvec4(0.0);
if (RenderableClass == RenderablePlanet) {
// Get the ray from camera to atm in object space
dCalculateRayRenderablePlanet(ray, planetPositionObjectCoords, cameraPositionInObject);
bool insideATM = false;
double offset = 0.0;
double maxLength = 0.0;
bool intersectATM = false;
void main() {
if (cullAtmosphere == 0) {
//float mainDepth = 0.0;
vec4 meanColor = vec4(0.0);
vec4 meanNormal = vec4(0.0);
vec4 meanPosition = vec4(0.0);
vec4 meanOtherData = vec4(0.0);
intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, ray, Rt-10*EPSILON,
insideATM, offset, maxLength );
//vec4 positionArray[nAaSamples];
//vec4 positionArray[8];
float maxAlpha = -1.0;
for (int i = 0; i < nAaSamples; i++) {
meanNormal += texelFetch(mainNormalTexture, ivec2(gl_FragCoord), i);
vec4 color = texelFetch(mainColorTexture, ivec2(gl_FragCoord), i);
if ( color.a > maxAlpha )
maxAlpha = color.a;
meanColor += color;
meanPosition += texelFetch(mainPositionTexture, ivec2(gl_FragCoord), i);
meanOtherData += texelFetch(otherDataTexture, ivec2(gl_FragCoord), i);
//positionArray[i] = texelFetch(mainPositionTexture, ivec2(gl_FragCoord), i);
//mainDepth += denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), i).x);
}
float invNaaSamples = 1.0/nAaSamples;
meanColor *= invNaaSamples;
meanNormal *= invNaaSamples;
meanPosition *= invNaaSamples;
meanOtherData *= invNaaSamples;
//mainDepth /= nAaSamples;
if ( intersectATM ) {
/*
vec4 farthestPosition = vec4(0.0);
float farthest = -1.0;
for (int i = 0; i < nAaSamples; i++) {
float tmpDistance = float(distance(dCampos.xyz, dvec3(positionArray[i].xyz)));
if ( positionArray[i].w > 0.0 && tmpDistance >= farthest ) {
farthest = tmpDistance;
farthestPosition = positionArray[i];
}
}
dvec3 tmpPos = dmat3(dInverseCamRotTransform) * dvec3(dInverseScaleTransformMatrix * farthestPosition);
*/
dvec4 fragWorldCoords = dInverseSgctEyeToWorldTranform * meanPosition;
dvec4 fragObjectCoords = dInverseModelTransformMatrix * fragWorldCoords;
//dvec4 fragObjectCoords = dInverseModelTransformMatrix * meanPosition;//fragWorldCoords;
double pixelDepth = distance(cameraPositionInObject.xyz, fragObjectCoords.xyz);
// All calculations are done in Km:
pixelDepth *= 0.001;
fragObjectCoords.xyz *= 0.001;
// Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel
// in the depth buffer is less than the distance to the atmosphere then the atmosphere
// is occluded
// Fragments positions into G-Buffer are written in OS Eye Space (Camera Rig Coords)
// when using their positions later, one must convert them to the planet's coords
if ((pixelDepth > 0.0) && (pixelDepth < offset)) {
renderTarget = vec4(HDR(meanColor.xyz * backgroundExposure), meanColor.a);
} else {
// Following paper nomenclature
double t = offset;
vec3 attenuation;
// Moving observer from camera location to top atmosphere
vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz);
float r = 0.0;//length(x);
vec3 v = vec3(ray.direction.xyz);
float mu = 0.0;//dot(x, v) / r;
vec3 s = vec3(sunDirectionObj);
float tF = float(maxLength - t);
// Because we may move the camera origin to the top of atmosphere
// we also need to adjust the pixelDepth for this offset so the
// next comparison with the planet's ground make sense:
pixelDepth -= offset;
float irradianceFactor = 0.0;
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v,
s, r, mu, attenuation,
vec3(fragObjectCoords.xyz),
maxLength, pixelDepth,
meanColor);
vec3 groundColor = groundColor(x, tF, v, s, r, mu, attenuation,
meanColor, meanNormal.xyz, irradianceFactor,
meanOtherData.r);
vec3 sunColor = sunColor(x, tF, v, s, r, mu, irradianceFactor);
vec4 finalRadiance = vec4(HDR(inscatterColor + groundColor + sunColor), 1.0);
renderTarget = finalRadiance;
}
}
} else if ( RenderableClass == RenderableGlobe) {
// Get the ray from camera to atm in object space
dCalculateRayRenderableGlobe(ray, planetPositionObjectCoords, cameraPositionInObject);
meanColor.a = maxAlpha;
bool insideATM = false;
double offset = 0.0;
double maxLength = 0.0;
bool intersectATM = false;
// Instead of ray-ellipsoid intersection lets transform the ray to a sphere:
dRay transfRay;
transfRay.origin = ray.origin;
transfRay.direction = ray.direction;
// transfRay.origin.z *= 1000.0/ellipsoidRadii.x;
// transfRay.direction.z *= 1000.0/ellipsoidRadii.x;
// transfRay.origin.x *= 1000.0/ellipsoidRadii.y;
// transfRay.direction.x *= 1000.0/ellipsoidRadii.y;
// transfRay.origin.y *= 1000.0/ellipsoidRadii.z;
// transfRay.direction.y *= 1000.0/ellipsoidRadii.z;
// transfRay.direction.xyz = normalize(transfRay.direction.xyz);
// intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay, 1.0,
// insideATM, offset, maxLength );
// intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay, Rt+EPSILON,
// insideATM, offset, maxLength );
intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay,
Rt-10*EPSILON, insideATM, offset, maxLength );
if ( intersectATM ) {
// Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel
// in the depth buffer is less than the distance to the atmosphere then the atmosphere
// is occluded
// Fragments positions into G-Buffer are written in OS Eye Space (Camera Rig Coords)
// when using their positions later, one must convert them to the planet's coords
/*
// Temporary:
meanNormal += texelFetch(mainNormalTexture, ivec2(gl_FragCoord), 0);
meanColor += texelFetch(mainColorTexture, ivec2(gl_FragCoord), 0);;
meanPosition += texelFetch(mainPositionTexture, ivec2(gl_FragCoord), 0);
meanOtherData += texelFetch(otherDataTexture, ivec2(gl_FragCoord), 0);
*/
// Ray in object space
dRay ray;
dvec4 planetPositionObjectCoords = dvec4(0.0);
dvec4 cameraPositionInObject = dvec4(0.0);
if (RenderableClass == RenderablePlanet) {
// Get the ray from camera to atm in object space
dCalculateRayRenderablePlanet(ray, planetPositionObjectCoords, cameraPositionInObject);
bool insideATM = false;
double offset = 0.0;
double maxLength = 0.0;
bool intersectATM = false;
// OS Eye to World coords
intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, ray, Rt-10*EPSILON,
insideATM, offset, maxLength );
// Version when no milkway is present (performance hit)
/*
vec4 farthestPosition = vec4(0.0);
float farthest = -1.0;
for (int i = 0; i < nAaSamples; i++) {
float tmpDistance = float(distance(dCampos.xyz, dvec3(positionArray[i].xyz)));
if ( positionArray[i].w > 0.0 && tmpDistance >= farthest ) {
farthest = tmpDistance;
farthestPosition = positionArray[i];
if ( intersectATM ) {
/*
vec4 farthestPosition = vec4(0.0);
float farthest = -1.0;
for (int i = 0; i < nAaSamples; i++) {
float tmpDistance = float(distance(dCampos.xyz, dvec3(positionArray[i].xyz)));
if ( positionArray[i].w > 0.0 && tmpDistance >= farthest ) {
farthest = tmpDistance;
farthestPosition = positionArray[i];
}
}
}
dvec4 tmpRInvPos = dInverseCamRotTransform * farthestPosition;
*/
// Version with milkway enabled
dvec4 tmpRInvPos = dInverseCamRotTransform * dSgctEyeToOSEyeTranform * meanPosition;
dvec4 fragWorldCoords = dvec4(dvec3(tmpRInvPos) + dCampos, 1.0);
//dvec4 tmpRInvNormal = dInverseCamRotTransform * meanNormal;
//dvec4 fragNormalWorldCoords = dvec4(dvec3(tmpRInvNormal) + dCampos, 1.0);
dvec3 tmpPos = dmat3(dInverseCamRotTransform) * dvec3(dInverseScaleTransformMatrix * farthestPosition);
*/
dvec4 fragWorldCoords = dInverseSgctEyeToWorldTranform * meanPosition;
dvec4 fragObjectCoords = dInverseModelTransformMatrix * fragWorldCoords;
//dvec4 fragObjectCoords = dInverseModelTransformMatrix * meanPosition;//fragWorldCoords;
double pixelDepth = distance(cameraPositionInObject.xyz, fragObjectCoords.xyz);
// World to Object (Normal and Position in meters)
dvec4 fragObjectCoords = dInverseModelTransformMatrix * fragWorldCoords;
//dvec4 fragNormalObjectCoords = dInverseTransformMatrix * fragNormalWorldCoords;
// Normal in Object Space already (changed 05/26/2017).
//dvec4 fragNormalObjectCoords = dvec4(normalize(meanNormal.xyz), 1.0);
// Distance of the pixel in the gBuffer to the observer
double pixelDepth = distance(cameraPositionInObject.xyz, fragObjectCoords.xyz);
// All calculations are done in Km:
pixelDepth *= 0.001;
fragObjectCoords.xyz *= 0.001;
if (meanPosition.xyz != vec3(0.0) && (pixelDepth < offset)) {
renderTarget = vec4(HDR(meanColor.xyz * backgroundExposure), meanColor.a);
} else {
// Following paper nomenclature
double t = offset;
vec3 attenuation;
// Moving observer from camera location to top atmosphere
// If the observer is already inside the atm, offset = 0.0
// and no changes at all.
vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz);
float r = 0.0;//length(x);
vec3 v = vec3(ray.direction.xyz);
float mu = 0.0;//dot(x, v) / r;
vec3 s = vec3(sunDirectionObj);
float tF = float(maxLength - t);
// Because we may move the camera origin to the top of atmosphere
// we also need to adjust the pixelDepth for this offset so the
// next comparison with the planet's ground make sense:
pixelDepth -= offset;
float irradianceFactor = 0.0;
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v,
s, r, mu, attenuation,
vec3(fragObjectCoords.xyz),
maxLength, pixelDepth,
meanColor);
vec3 groundColor = groundColor(x, tF, v, s, r, mu, attenuation,
meanColor, meanNormal.xyz, irradianceFactor,
meanOtherData.r);
vec3 sunColor = sunColor(x, tF, v, s, r, mu, irradianceFactor);
// All calculations are done in Km:
pixelDepth *= 0.001;
fragObjectCoords.xyz *= 0.001;
// Final Color of ATM plus terrain:
vec4 finalRadiance = vec4(HDR(inscatterColor + groundColor + sunColor), 1.0);
// Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel
// in the depth buffer is less than the distance to the atmosphere then the atmosphere
// is occluded
// Fragments positions into G-Buffer are written in OS Eye Space (Camera Rig Coords)
// when using their positions later, one must convert them to the planet's coords
if ((pixelDepth > 0.0) && (pixelDepth < offset)) {
renderTarget = vec4(HDR(meanColor.xyz * backgroundExposure), meanColor.a);
} else {
// Following paper nomenclature
double t = offset;
vec3 attenuation;
// Moving observer from camera location to top atmosphere
vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz);
float r = 0.0;//length(x);
vec3 v = vec3(ray.direction.xyz);
float mu = 0.0;//dot(x, v) / r;
vec3 s = vec3(sunDirectionObj);
float tF = float(maxLength - t);
// Because we may move the camera origin to the top of atmosphere
// we also need to adjust the pixelDepth for this offset so the
// next comparison with the planet's ground make sense:
pixelDepth -= offset;
float irradianceFactor = 0.0;
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v,
s, r, mu, attenuation,
vec3(fragObjectCoords.xyz),
maxLength, pixelDepth,
meanColor);
vec3 groundColor = groundColor(x, tF, v, s, r, mu, attenuation,
meanColor, meanNormal.xyz, irradianceFactor,
meanOtherData.r);
vec3 sunColor = sunColor(x, tF, v, s, r, mu, irradianceFactor);
vec4 finalRadiance = vec4(HDR(inscatterColor + groundColor + sunColor), 1.0);
renderTarget = finalRadiance;
}
}
} else if ( RenderableClass == RenderableGlobe) {
// Get the ray from camera to atm in object space
dCalculateRayRenderableGlobe(ray, planetPositionObjectCoords, cameraPositionInObject);
bool insideATM = false;
double offset = 0.0;
double maxLength = 0.0;
bool intersectATM = false;
// Instead of ray-ellipsoid intersection lets transform the ray to a sphere:
dRay transfRay;
transfRay.origin = ray.origin;
transfRay.direction = ray.direction;
// transfRay.origin.z *= 1000.0/ellipsoidRadii.x;
// transfRay.direction.z *= 1000.0/ellipsoidRadii.x;
// transfRay.origin.x *= 1000.0/ellipsoidRadii.y;
// transfRay.direction.x *= 1000.0/ellipsoidRadii.y;
// transfRay.origin.y *= 1000.0/ellipsoidRadii.z;
// transfRay.direction.y *= 1000.0/ellipsoidRadii.z;
// transfRay.direction.xyz = normalize(transfRay.direction.xyz);
// intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay, 1.0,
// insideATM, offset, maxLength );
// intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay, Rt+EPSILON,
// insideATM, offset, maxLength );
intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, transfRay,
Rt-10*EPSILON, insideATM, offset, maxLength );
if ( intersectATM ) {
// Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel
// in the depth buffer is less than the distance to the atmosphere then the atmosphere
// is occluded
// Fragments positions into G-Buffer are written in OS Eye Space (Camera Rig Coords)
// when using their positions later, one must convert them to the planet's coords
renderTarget = finalRadiance;
}
}
}
// OS Eye to World coords
// Version when no milkway is present (performance hit)
/*
vec4 farthestPosition = vec4(0.0);
float farthest = -1.0;
for (int i = 0; i < nAaSamples; i++) {
float tmpDistance = float(distance(dCampos.xyz, dvec3(positionArray[i].xyz)));
if ( positionArray[i].w > 0.0 && tmpDistance >= farthest ) {
farthest = tmpDistance;
farthestPosition = positionArray[i];
}
}
dvec4 tmpRInvPos = dInverseCamRotTransform * farthestPosition;
*/
// Version with milkway enabled
dvec4 tmpRInvPos = dInverseCamRotTransform * dSgctEyeToOSEyeTranform * meanPosition;
dvec4 fragWorldCoords = dvec4(dvec3(tmpRInvPos) + dCampos, 1.0);
//dvec4 tmpRInvNormal = dInverseCamRotTransform * meanNormal;
//dvec4 fragNormalWorldCoords = dvec4(dvec3(tmpRInvNormal) + dCampos, 1.0);
// World to Object (Normal and Position in meters)
dvec4 fragObjectCoords = dInverseModelTransformMatrix * fragWorldCoords;
//dvec4 fragNormalObjectCoords = dInverseTransformMatrix * fragNormalWorldCoords;
// Normal in Object Space already (changed 05/26/2017).
//dvec4 fragNormalObjectCoords = dvec4(normalize(meanNormal.xyz), 1.0);
// Distance of the pixel in the gBuffer to the observer
double pixelDepth = distance(cameraPositionInObject.xyz, fragObjectCoords.xyz);
// All calculations are done in Km:
pixelDepth *= 0.001;
fragObjectCoords.xyz *= 0.001;
if (meanPosition.xyz != vec3(0.0) && (pixelDepth < offset)) {
renderTarget = vec4(HDR(meanColor.xyz * backgroundExposure), meanColor.a);
} else {
// Following paper nomenclature
double t = offset;
vec3 attenuation;
// Moving observer from camera location to top atmosphere
// If the observer is already inside the atm, offset = 0.0
// and no changes at all.
vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz);
float r = 0.0;//length(x);
vec3 v = vec3(ray.direction.xyz);
float mu = 0.0;//dot(x, v) / r;
vec3 s = vec3(sunDirectionObj);
float tF = float(maxLength - t);
// Because we may move the camera origin to the top of atmosphere
// we also need to adjust the pixelDepth for this offset so the
// next comparison with the planet's ground make sense:
pixelDepth -= offset;
float irradianceFactor = 0.0;
vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v,
s, r, mu, attenuation,
vec3(fragObjectCoords.xyz),
maxLength, pixelDepth,
meanColor);
vec3 groundColor = groundColor(x, tF, v, s, r, mu, attenuation,
meanColor, meanNormal.xyz, irradianceFactor,
meanOtherData.r);
vec3 sunColor = sunColor(x, tF, v, s, r, mu, irradianceFactor);
// Final Color of ATM plus terrain:
vec4 finalRadiance = vec4(HDR(inscatterColor + groundColor + sunColor), 1.0);
renderTarget = finalRadiance;
}
}
}
}
}