diff --git a/data/scene/atmosphereearth.scene b/data/scene/atmosphereearth.scene index 3fd4ed412a..6f30e1483f 100644 --- a/data/scene/atmosphereearth.scene +++ b/data/scene/atmosphereearth.scene @@ -99,8 +99,8 @@ return { --"moon", "lodglobes/earth", - --"lodglobes/mars", - --"lodglobes/moon", + "lodglobes/mars", + "lodglobes/moon", --"satellites", --"mars-satellites", --"toyvolume", diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 000109dcd2..e19279bbf0 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -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(_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(_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; } diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.h b/modules/atmosphere/rendering/atmospheredeferredcaster.h index e994c3ed31..be8285fab5 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.h +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.h @@ -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 _transmittanceProgramObject; std::unique_ptr _irradianceProgramObject; std::unique_ptr _irradianceSupTermsProgramObject; diff --git a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl index e6b7d1846b..be9e7592db 100644 --- a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl +++ b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl @@ -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; + } + } + } + } }