mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 11:39:49 -06:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user