Files
OpenSpace/modules/exoplanets/shaders/orbitdisc_fs.glsl
T
Alexander Bock d7d279ea16 Happy new year
2022-01-01 12:32:55 +01:00

129 lines
5.5 KiB
GLSL

/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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. *
****************************************************************************************/
#include "fragment.glsl"
in vec2 vs_st;
in float vs_depth;
uniform sampler1D discTexture;
uniform vec2 offset; // relative to semi major axis
uniform float opacity;
uniform float eccentricity;
uniform float semiMajorAxis;
const float Epsilon = 0.0000001;
// Compute semi minor axis from major axis, a, and eccentricity, e
float semiMinorAxis(float a, float e) {
return a * sqrt(1.0 - e * e);
}
// If returned value <= 1, the point is insdie or on the ellipse specified by the input:
// a and b are the semi-major and semi-minor axes, respectively.
// cx is the displacement of the center of the ellipse along the x-axis (for an orbit,
// the y-displacement is always zero)
float ellipseTest(vec2 point, float a, float b, float cx) {
float x = point.x;
float y = point.y;
return (pow(x - cx, 2.0) / (a*a)) + ((y*y) / (b*b));
}
Fragment getFragment() {
// Moving the origin to the center
vec2 st = (vs_st - vec2(0.5)) * 2.0;
float offsetLower = offset.x * semiMajorAxis;
float offsetUpper = offset.y * semiMajorAxis;
float AUpper = semiMajorAxis + offsetUpper;
float BUpper = semiMinorAxis(AUpper, eccentricity);
float CUpper = sqrt(AUpper*AUpper - BUpper*BUpper);
float outerApoapsisDistance = AUpper * (1.0 + eccentricity);
float ALower = semiMajorAxis - offsetLower;
float BLower = semiMinorAxis(ALower, eccentricity);
float CLower = sqrt(ALower*ALower - BLower*BLower);
float innerApoapsisDistance = ALower * (1.0 + eccentricity);
// Normalize based on outer apoapsis distance (size of plane)
float AU_n = AUpper / outerApoapsisDistance;
float BU_n = BUpper / outerApoapsisDistance;
float CU_n = CUpper / outerApoapsisDistance;
float AL_n = ALower / outerApoapsisDistance;
float BL_n = BLower / outerApoapsisDistance;
float CL_n = CLower / outerApoapsisDistance;
if (eccentricity <= Epsilon) {
CU_n = 0.0;
CL_n = 0.0;
}
float outer = ellipseTest(st, AU_n, BU_n, -CU_n);
float inner = ellipseTest(st, AL_n, BL_n, -CL_n);
if (outer > 1.0 || inner < 1.0) {
// Point is outside outer ellipse or inside inner ellipse
discard;
}
// Remapping the texture coordinates
vec2 dir = normalize(st);
// Find outer ellipse: where along the direction does the equation == 1?
float denominator = pow(BU_n * dir.x, 2.0) + pow(AU_n * dir.y, 2.0);
float first = -(BU_n * BU_n * dir.x * CU_n) / denominator;
float second = pow((BU_n * BU_n * dir.x * CU_n) / denominator, 2.0);
float third = (pow(BU_n * CU_n, 2.0) - pow(AU_n * BU_n, 2.0)) / denominator;
float scale = first + sqrt(second - third);
vec2 outerPoint = dir * scale;
vec2 innerPoint = outerPoint * (innerApoapsisDistance / outerApoapsisDistance);
float discWidth = distance(outerPoint, innerPoint);
float distanceFromOuterEdge = distance(outerPoint, st);
float relativeDistance = distanceFromOuterEdge / discWidth;
// Compute texture coordinate based on the distance to outer edge
float textureCoord = 0.0;
// The midpoint (textureCoord = 0.5) depends on the ratio between the offsets
// (Note that the texture goes from outer to inner edge of disc)
float midPoint = offsetUpper / (offsetUpper + offsetLower);
if (relativeDistance > midPoint) {
textureCoord = 0.5 + 0.5 * (relativeDistance - midPoint) / (1.0 - midPoint);
}
else {
textureCoord = 0.5 * (relativeDistance / midPoint);
}
vec4 diffuse = texture(discTexture, textureCoord);
diffuse.a *= opacity;
Fragment frag;
frag.color = diffuse;
frag.depth = vs_depth;
return frag;
}