Faster rendering for renderableOrbitalKepler (#3739)

* Faster rendering for renderableOrbitalKepler
- Computes relevant vertices on CPU rather than filtering all vertices on the GPU
- Removes geometry shader for trails rendering
- Changed GUI name of RenderingMode "Points+Trails" to "Points and Trails"
This commit is contained in:
Adam Rohdin
2025-07-09 11:33:27 +02:00
committed by GitHub
parent 63907c9750
commit 4306387f69
9 changed files with 244 additions and 230 deletions

View File

@@ -74,12 +74,11 @@ set(SHADER_FILES
shaders/constellationbounds_vs.glsl
shaders/constellationlines_fs.glsl
shaders/constellationlines_vs.glsl
shaders/debrisVizPoints_fs.glsl
shaders/debrisVizPoints_gs.glsl
shaders/debrisVizPoints_vs.glsl
shaders/debrisVizTrails_fs.glsl
shaders/debrisVizTrails_gs.glsl
shaders/debrisVizTrails_vs.glsl
shaders/keplerpoints_fs.glsl
shaders/keplerpoints_gs.glsl
shaders/keplerpoints_vs.glsl
shaders/keplertrails_fs.glsl
shaders/keplertrails_vs.glsl
shaders/fluxnodes_fs.glsl
shaders/fluxnodes_vs.glsl
shaders/habitablezone_vs.glsl

View File

@@ -269,7 +269,7 @@ RenderableOrbitalKepler::Appearance::Appearance()
renderingModes.addOptions({
{ RenderingModeTrail, "Trails" },
{ RenderingModePoint, "Points" },
{ RenderingModePointTrail , "Points+Trails" }
{ RenderingModePointTrail , "Points and Trails" }
});
addProperty(renderingModes);
@@ -331,10 +331,6 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
}
addPropertySubOwner(_appearance);
_path = p.path.string();
_path.onChange([this]() { updateBuffers(); });
addProperty(_path);
_format = codegen::map<kepler::Format>(p.format);
_startRenderIdx = p.startRenderIdx.value_or(0);
@@ -362,6 +358,10 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
_contiguousMode = p.contiguousMode.value_or(false);
_contiguousMode.onChange([this]() { _updateDataBuffersAtNextRender = true; });
addProperty(_contiguousMode);
_path = p.path.string();
_path.onChange([this]() { updateBuffers(); });
addProperty(_path);
}
void RenderableOrbitalKepler::initializeGL() {
@@ -376,9 +376,8 @@ void RenderableOrbitalKepler::initializeGL() {
[]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
return global::renderEngine->buildRenderProgram(
"OrbitalKeplerTrails",
absPath("${MODULE_SPACE}/shaders/debrisVizTrails_vs.glsl"),
absPath("${MODULE_SPACE}/shaders/debrisVizTrails_fs.glsl"),
absPath("${MODULE_SPACE}/shaders/debrisVizTrails_gs.glsl")
absPath("${MODULE_SPACE}/shaders/keplertrails_vs.glsl"),
absPath("${MODULE_SPACE}/shaders/keplertrails_fs.glsl")
);
}
);
@@ -389,9 +388,9 @@ void RenderableOrbitalKepler::initializeGL() {
[]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
return global::renderEngine->buildRenderProgram(
"OrbitalKeplerPoints",
absPath("${MODULE_SPACE}/shaders/debrisVizPoints_vs.glsl"),
absPath("${MODULE_SPACE}/shaders/debrisVizPoints_fs.glsl"),
absPath("${MODULE_SPACE}/shaders/debrisVizPoints_gs.glsl")
absPath("${MODULE_SPACE}/shaders/keplerpoints_vs.glsl"),
absPath("${MODULE_SPACE}/shaders/keplerpoints_fs.glsl"),
absPath("${MODULE_SPACE}/shaders/keplerpoints_gs.glsl")
);
}
);
@@ -440,9 +439,6 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
return;
}
GLint* _si = _startIndex.data();
GLint* _ss = _segmentSize.data();
const int selection = _appearance.renderingModes;
const bool renderPoints = (
selection == RenderingModePoint ||
@@ -454,6 +450,8 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
);
if (renderPoints) {
calculateSegmentsForPoints(data);
_pointProgram->activate();
_pointProgram->setUniform(
_uniformPointCache.modelTransform,
@@ -506,9 +504,9 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
glBindVertexArray(_vertexArray);
glMultiDrawArrays(
GL_LINE_STRIP,
_si,
_ss,
static_cast<GLsizei>(_startIndex.size())
_startIndexPoints.data(),
_segmentSizePoints.data(),
static_cast<GLsizei>(_startIndexPoints.size())
);
glBindVertexArray(0);
@@ -516,6 +514,8 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
}
if (renderTrails) {
calculateSegmentsForTrails(data);
_trailProgram->activate();
_trailProgram->setUniform(_uniformTrailCache.opacity, opacity());
_trailProgram->setUniform(_uniformTrailCache.color, _appearance.color);
@@ -550,9 +550,9 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
glBindVertexArray(_vertexArray);
glMultiDrawArrays(
GL_LINE_STRIP,
_si,
_ss,
static_cast<GLsizei>(_startIndex.size())
_startIndexTrails.data(),
_segmentSizeTrails.data(),
_lineDrawCount
);
glBindVertexArray(0);
@@ -561,9 +561,9 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
}
void RenderableOrbitalKepler::updateBuffers() {
std::vector<kepler::Parameters> parameters = kepler::readFile(_path.value(), _format);
_parameters = kepler::readFile(_path.value(), _format);
_numObjects = parameters.size();
_numObjects = _parameters.size();
if (_startRenderIdx >= _numObjects) {
throw ghoul::RuntimeError(std::format(
@@ -586,57 +586,59 @@ void RenderableOrbitalKepler::updateBuffers() {
}
if (_contiguousMode) {
if (_startRenderIdx >= parameters.size() ||
(_startRenderIdx + _sizeRender) >= parameters.size())
if (_startRenderIdx >= _parameters.size() ||
(_startRenderIdx + _sizeRender) >= _parameters.size())
{
throw ghoul::RuntimeError(std::format(
"Tried to load {} objects but only {} are available",
_startRenderIdx + _sizeRender, parameters.size()
_startRenderIdx + _sizeRender, _parameters.size()
));
}
// Extract subset that starts at _startRenderIdx and contains _sizeRender obejcts
parameters = std::vector<kepler::Parameters>(
parameters.begin() + _startRenderIdx,
parameters.begin() + _startRenderIdx + _sizeRender
_parameters = std::vector<kepler::Parameters>(
_parameters.begin() + _startRenderIdx,
_parameters.begin() + _startRenderIdx + _sizeRender
);
}
else {
// First shuffle the whole array
std::default_random_engine rng;
std::shuffle(parameters.begin(), parameters.end(), rng);
std::shuffle(_parameters.begin(), _parameters.end(), rng);
// Then take the first _sizeRender values
parameters = std::vector<kepler::Parameters>(
parameters.begin(),
parameters.begin() + _sizeRender
_parameters = std::vector<kepler::Parameters>(
_parameters.begin(),
_parameters.begin() + _sizeRender
);
}
_segmentSize.clear();
_startIndex.clear();
_startIndex.push_back(0);
for (size_t i = 0; i < parameters.size(); i++) {
_startIndexPoints.clear();
_segmentSizePoints.clear();
_startIndexTrails.clear();
_segmentSizeTrails.clear();
_segmentSizeRaw.clear();
size_t nVerticesTotal = 0;
const int numOrbits = static_cast<int>(_parameters.size());
for (int i = 0; i < numOrbits; i++) {
// For points rendering as they are always two vertices long
_segmentSizePoints.push_back(2);
const double scale = static_cast<double>(_segmentQuality) * 10.0;
const kepler::Parameters& p = parameters[i];
_segmentSize.push_back(
const kepler::Parameters& p = _parameters[i];
_segmentSizeRaw.push_back(
static_cast<int>(scale + (scale / std::pow(1.0 - p.eccentricity, 1.2)))
);
_startIndex.push_back(_startIndex[i] + static_cast<GLint>(_segmentSize[i]));
}
_startIndex.pop_back();
size_t nVerticesTotal = 0;
const int numOrbits = static_cast<int>(parameters.size());
for (int i = 0; i < numOrbits; i++) {
nVerticesTotal += _segmentSize[i];
nVerticesTotal += _segmentSizeRaw[i];
}
_startIndexPoints.resize(numOrbits);
_startIndexTrails.resize(numOrbits*2);
_segmentSizeTrails.resize(numOrbits*2);
_vertexBufferData.resize(nVerticesTotal);
size_t vertexBufIdx = 0;
for (int orbitIdx = 0; orbitIdx < numOrbits; ++orbitIdx) {
const kepler::Parameters& orbit = parameters[orbitIdx];
const kepler::Parameters& orbit = _parameters[orbitIdx];
ghoul::Dictionary d;
d.setValue("Type", std::string("KeplerTranslation"));
@@ -650,9 +652,10 @@ void RenderableOrbitalKepler::updateBuffers() {
d.setValue("Epoch", orbit.epoch);
KeplerTranslation keplerTranslator = KeplerTranslation(d);
for (GLint j = 0 ; j < (_segmentSize[orbitIdx]); j++) {
const int nSegments = _segmentSizeRaw[orbitIdx];
for (GLint j = 0 ; j < nSegments; j++) {
const double timeOffset = orbit.period *
static_cast<double>(j) / static_cast<double>(_segmentSize[orbitIdx] - 1);
static_cast<double>(j) / static_cast<double>(nSegments - 1);
const glm::dvec3 position = keplerTranslator.position({
{},
@@ -660,15 +663,14 @@ void RenderableOrbitalKepler::updateBuffers() {
Time(0.0)
});
_vertexBufferData[vertexBufIdx].x = static_cast<float>(position.x);
_vertexBufferData[vertexBufIdx].y = static_cast<float>(position.y);
_vertexBufferData[vertexBufIdx].z = static_cast<float>(position.z);
_vertexBufferData[vertexBufIdx].time = static_cast<float>(timeOffset);
_vertexBufferData[vertexBufIdx].epoch = orbit.epoch;
_vertexBufferData[vertexBufIdx].period = orbit.period;
vertexBufIdx++;
_vertexBufferData[vertexBufIdx + j].x = static_cast<float>(position.x);
_vertexBufferData[vertexBufIdx + j].y = static_cast<float>(position.y);
_vertexBufferData[vertexBufIdx + j].z = static_cast<float>(position.z);
_vertexBufferData[vertexBufIdx + j].time = static_cast<float>(timeOffset);
_vertexBufferData[vertexBufIdx + j].epoch = orbit.epoch;
_vertexBufferData[vertexBufIdx + j].period = orbit.period;
}
vertexBufIdx += nSegments;
}
glBindVertexArray(_vertexArray);
@@ -697,7 +699,7 @@ void RenderableOrbitalKepler::updateBuffers() {
glBindVertexArray(0);
double maxSemiMajorAxis = 0.0;
for (const kepler::Parameters& kp : parameters) {
for (const kepler::Parameters& kp : _parameters) {
if (kp.semiMajorAxis > maxSemiMajorAxis) {
maxSemiMajorAxis = kp.semiMajorAxis;
}
@@ -705,4 +707,95 @@ void RenderableOrbitalKepler::updateBuffers() {
setBoundingSphere(maxSemiMajorAxis * 1000);
}
void RenderableOrbitalKepler::calculateSegmentsForPoints(const RenderData& data) {
int startVertexIndex = 0;
for (int i = 0; i < _segmentSizeRaw.size(); i++) {
// Check how far along the trail we are
const kepler::Parameters& orbit = _parameters[i];
const double nRevs = (data.time.j2000Seconds() - orbit.epoch) / orbit.period;
double frac = nRevs - std::trunc(nRevs);
frac += (frac < 0.0) ? 1.0: 0.0;
// Get the closest vertex before that point
const int nSegments = _segmentSizeRaw[i] - 1;
const int offset = static_cast<int>(std::floor(frac * nSegments));
// Set start vertex ID in buffer
_startIndexPoints[i] = startVertexIndex + offset;
startVertexIndex += _segmentSizeRaw[i];
}
}
void RenderableOrbitalKepler::calculateSegmentsForTrails(const RenderData& data) {
const float fade = pow(_appearance.trailFade.maxValue() - _appearance.trailFade, 2.f);
const float threshold = 1.f - pow(0.05f, 1.f / fade);
int nTotalTrailParts = 0;
int startVertexIndex = 0;
for (int i = 0; i < _segmentSizeRaw.size(); i++) {
// Check how far along the trail we are
const kepler::Parameters& orbit = _parameters[i];
const double nRevs = (data.time.j2000Seconds() - orbit.epoch) / orbit.period;
double frac = nRevs - std::trunc(nRevs);
frac += (frac < 0.0) ? 1.0 : 0.0;
int p0Start = 0;
int p0Length = 0;
int p1Start = 0;
int p1Length = 0;
const int nVerts = _segmentSizeRaw[i];
const int nSegments = nVerts - 1;
const int trailLength = static_cast<int>(std::ceil(threshold * nSegments));
if (trailLength == nSegments) {
// Whole trail should be visible
p0Start = startVertexIndex;
p0Length = nVerts;
}
else {
const int headOffset = static_cast<int>(std::ceil(frac * nSegments));
const int headVertexIndex = startVertexIndex + headOffset;
const int correctTrailLength = trailLength + 2;
int correctVertexIndex = headVertexIndex - correctTrailLength + 1;
// If the start of the trail should be at the end of the orbit
if (correctVertexIndex < startVertexIndex) {
correctVertexIndex += nVerts;
}
// If the trail is length passes over the last point of the orbit
const int lastVertexIndex = startVertexIndex + nVerts;
if (correctVertexIndex + correctTrailLength > lastVertexIndex) {
p1Start = correctVertexIndex - 1;
p1Length = lastVertexIndex - correctVertexIndex + 1;
p0Start = startVertexIndex;
p0Length = correctTrailLength - p1Length + 1;
}
else {
// If the entire trail is within the bounds of the orbit
p0Start = correctVertexIndex;
p0Length = correctTrailLength;
}
}
int newTrailParts = 0;
if (p0Length > 1) {
_startIndexTrails[nTotalTrailParts] = p0Start;
_segmentSizeTrails[nTotalTrailParts] = p0Length;
newTrailParts += 1;
}
if (p1Length > 1) {
_startIndexTrails[nTotalTrailParts + newTrailParts] = p1Start;
_segmentSizeTrails[nTotalTrailParts + newTrailParts] = p1Length;
newTrailParts += 1;
}
startVertexIndex += nVerts;
nTotalTrailParts += newTrailParts;
}
_lineDrawCount = static_cast<GLsizei>(nTotalTrailParts);
}
} // namespace openspace

View File

@@ -79,14 +79,21 @@ private:
};
void updateBuffers();
void calculateSegmentsForPoints(const RenderData& data);
void calculateSegmentsForTrails(const RenderData& data);
bool _updateDataBuffersAtNextRender = false;
long long _numObjects = 0;
std::vector<GLint> _segmentSize;
std::vector<GLint> _startIndex;
GLsizei _lineDrawCount = 0;
properties::UIntProperty _segmentQuality;
properties::UIntProperty _startRenderIdx;
properties::UIntProperty _sizeRender;
std::vector<GLint> _segmentSizeRaw;
std::vector<GLint> _startIndexPoints;
std::vector<GLint> _segmentSizePoints;
std::vector<GLint> _startIndexTrails;
std::vector<GLint> _segmentSizeTrails;
std::vector<kepler::Parameters> _parameters;
/// The layout of the VBOs
struct TrailVBOLayout {

View File

@@ -1,85 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
layout(lines) in;
flat in float currentRevolutionFraction[];
flat in float vertexRevolutionFraction[];
flat in vec4 viewSpacePositions[];
layout(line_strip, max_vertices = 2) out;
out float viewSpaceDepth;
out float periodFraction;
out float offsetPeriods;
out vec4 viewSpacePosition;
uniform float trailFadeExponent;
uniform float colorFadeCutoffValue;
void main() {
// cFrac is how far along the trail orbit the head of the trail is.
// v0Frac and v1Frac are how far the two vertices that creates the current line strip
// are along the trail orbit. The variables span between 0 and 1, where 0 is the
// beginning of the trail and 1 is the end of the trail (a full orbit).
float cFrac = currentRevolutionFraction[0];
float v0Frac = vertexRevolutionFraction[0];
float v1Frac = vertexRevolutionFraction[1];
// Distance between current revolution fraction and revolution fraction for
// vertex0 and vertex1
float vd0 = cFrac - v0Frac;
if (vd0 < 0.0) {
vd0 += 1.0;
}
float vd1 = cFrac - v1Frac;
if (vd1 < 0.0) {
vd1 += 1.0;
}
// ==========================
// Calculates if vertex0 is close enough to NOT be discarded in fragment shader
float invert = pow(1.0 - vd1, trailFadeExponent);
float fade = clamp(invert, 0.0, 1.0);
// Only emit vertices for line segments where both vertices should be rendered
if ((fade > colorFadeCutoffValue) || (vd0 < vd1)) {
gl_Position = gl_in[0].gl_Position;
viewSpaceDepth = gl_Position.w;
periodFraction = cFrac;
offsetPeriods = v0Frac;
viewSpacePosition = viewSpacePositions[0];
EmitVertex();
gl_Position = gl_in[1].gl_Position;
viewSpaceDepth = gl_Position.w;
periodFraction = cFrac;
offsetPeriods = v1Frac;
viewSpacePosition = viewSpacePositions[1];
EmitVertex();
}
EndPrimitive();
}

View File

@@ -53,83 +53,79 @@ void main() {
float v0Frac = vertexRevolutionFraction[0];
float v1Frac = vertexRevolutionFraction[1];
// Only create/emit vertices for segments where the head of the trail falls within
if (cFrac >= v0Frac && cFrac <= v1Frac) {
// Interpolate position of current position of the trail head
float dFrac = abs(cFrac - v0Frac);
float vFrac = abs(v1Frac - v0Frac);
float percentage = dFrac / vFrac;
// Interpolate position of current position of the trail head
float dFrac = abs(cFrac - v0Frac);
float vFrac = abs(v1Frac - v0Frac);
float percentage = dFrac / vFrac;
vec4 v0Weighted = (1.0 - percentage) * gl_in[0].gl_Position;
vec4 v1Weighted = (percentage) * gl_in[1].gl_Position;
vec4 pos = v0Weighted + v1Weighted;
// ==========================
vec4 v0Weighted = (1.0 - percentage) * gl_in[0].gl_Position;
vec4 v1Weighted = percentage * gl_in[1].gl_Position;
vec4 pos = v0Weighted + v1Weighted;
// ==========================
// Calculate current vertex position to world space
dvec4 vertPosWorldSpace = modelTransform * pos;
// Calculate current vertex position to world space
dvec4 vertPosWorldSpace = modelTransform * pos;
// Calculate new axis for plane
vec3 camPosToVertPos = vec3(cameraPositionWorld - vertPosWorldSpace.xyz);
vec3 normal = normalize(camPosToVertPos);
vec3 right = normalize(cross(cameraUpWorld, normal));
vec3 up = normalize(cross(normal, right));
// Calculate new axis for plane
vec3 camPosToVertPos = vec3(cameraPositionWorld - vertPosWorldSpace.xyz);
vec3 normal = normalize(camPosToVertPos);
vec3 right = normalize(cross(cameraUpWorld, normal));
vec3 up = normalize(cross(normal, right));
// Calculate size of points
float initialSize = pow(10.0, pointSizeExponent);
right *= initialSize;
up *= initialSize;
// Calculate size of points
float initialSize = pow(10.0, pointSizeExponent);
right *= initialSize;
up *= initialSize;
float opp = length(right);
float adj = length(camPosToVertPos);
float angle = atan(opp/adj);
float maxAngle = radians(maxSize * 0.5);
float opp = length(right);
float adj = length(camPosToVertPos);
float angle = atan(opp/adj);
float maxAngle = radians(maxSize * 0.5);
// Controls the point size
if (enableMaxSize && (angle > maxAngle) && (adj > 0.0)) {
float correction = (adj * tan(maxAngle)) / opp;
right *= correction;
up *= correction;
}
// Controls the point size
if (enableMaxSize && (angle > maxAngle) && (adj > 0.0)) {
float correction = (adj * tan(maxAngle)) / opp;
right *= correction;
up *= correction;
}
// Calculate and set corners of the new quad
dvec4 p0World = vertPosWorldSpace + vec4(up-right, 0.0);
dvec4 p1World = vertPosWorldSpace + vec4(-right-up,0.0);
dvec4 p2World = vertPosWorldSpace + vec4(right+up, 0.0);
dvec4 p3World = vertPosWorldSpace + vec4(right-up, 0.0);
// Calculate and set corners of the new quad
dvec4 p0World = vertPosWorldSpace + vec4(up-right, 0.0);
dvec4 p1World = vertPosWorldSpace + vec4(-right-up,0.0);
dvec4 p2World = vertPosWorldSpace + vec4(right+up, 0.0);
dvec4 p3World = vertPosWorldSpace + vec4(right-up, 0.0);
// Set some additional out parameters
viewSpace = z_normalization(
vec4(projectionTransform * viewTransform * modelTransform * pos)
);
projectionViewDepth = viewSpace.w;
dmat4 ViewProjectionTransform = projectionTransform * viewTransform;
// left-top
vec4 p0Screen = z_normalization(vec4(ViewProjectionTransform * p0World));
gl_Position = p0Screen;
texCoord = vec2(0.0, 0.0);
EmitVertex();
// Set some additional out parameters
viewSpace = z_normalization(
vec4(projectionTransform * viewTransform * modelTransform * pos)
);
projectionViewDepth = viewSpace.w;
// left-bot
vec4 p1Screen = z_normalization(vec4(ViewProjectionTransform * p1World));
gl_Position = p1Screen;
texCoord = vec2(1.0, 0.0);
EmitVertex();
dmat4 ViewProjectionTransform = projectionTransform * viewTransform;
// right-top
vec4 p2Screen = z_normalization(vec4(ViewProjectionTransform * p2World));
gl_Position = p2Screen;
texCoord = vec2(0.0, 1.0);
EmitVertex();
// left-top
vec4 p0Screen = z_normalization(vec4(ViewProjectionTransform * p0World));
gl_Position = p0Screen;
texCoord = vec2(0.0, 0.0);
EmitVertex();
// right-bot
vec4 p3Screen = z_normalization(vec4(ViewProjectionTransform * p3World));
gl_Position = p3Screen;
texCoord = vec2(1.0, 1.0);
EmitVertex();
}
// left-bot
vec4 p1Screen = z_normalization(vec4(ViewProjectionTransform * p1World));
gl_Position = p1Screen;
texCoord = vec2(1.0, 0.0);
EmitVertex();
// right-top
vec4 p2Screen = z_normalization(vec4(ViewProjectionTransform * p2World));
gl_Position = p2Screen;
texCoord = vec2(0.0, 1.0);
EmitVertex();
// right-bot
vec4 p3Screen = z_normalization(vec4(ViewProjectionTransform * p3World));
gl_Position = p3Screen;
texCoord = vec2(1.0, 1.0);
EmitVertex();
EndPrimitive();
}

View File

@@ -29,9 +29,10 @@
layout (location = 0) in vec4 vertexData; // 1: x, 2: y, 3: z, 4: timeOffset,
layout (location = 1) in vec2 orbitData; // 1: epoch, 2: period
flat out float currentRevolutionFraction;
flat out float vertexRevolutionFraction;
flat out vec4 viewSpacePositions;
out vec4 viewSpacePosition;
out float viewSpaceDepth;
out float periodFraction;
out float offsetPeriods;
uniform dmat4 modelViewTransform;
uniform mat4 projectionTransform;
@@ -50,18 +51,21 @@ void main() {
float epoch = orbitData.x;
float period = orbitData.y;
// calculate nr of periods, get fractional part to know where the vertex closest to the
// Calculate nr of periods, get fractional part to know where the vertex closest to the
// debris part is right now
double nrOfRevolutions = (inGameTime - epoch) / period;
currentRevolutionFraction = float(nrOfRevolutions - double(int(nrOfRevolutions)));
if (currentRevolutionFraction < 0.0) {
currentRevolutionFraction += 1.0;
}
double frac = double(int(nrOfRevolutions));
double periodFractiond = nrOfRevolutions - frac;
if (periodFractiond < 0.0) {
periodFractiond += 1.0;
}
periodFraction = float(periodFractiond);
// Same procedure for the current vertex
vertexRevolutionFraction = vertexData.w / period;
viewSpacePositions = vec4(modelViewTransform * dvec4(vertexData.xyz, 1));
vec4 vs_position = z_normalization(projectionTransform * viewSpacePositions);
offsetPeriods = vertexData.w / float(period);
viewSpacePosition = vec4(modelViewTransform * dvec4(vertexData.xyz, 1));
vec4 vs_position = z_normalization(projectionTransform * viewSpacePosition);
gl_Position = vs_position;
viewSpaceDepth = vs_position.w;
}