From 0af14d4ca8e91f3176a8b6e5884a9f110356b231 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Thu, 31 Oct 2019 21:22:44 +0300 Subject: [PATCH] Add LOD for planet rings --- src/celengine/body.h | 3 ++- src/celengine/render.cpp | 22 ++++++++++++++-------- src/celengine/renderglsl.cpp | 17 ++++++++++++++--- src/celengine/renderglsl.h | 1 + 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/celengine/body.h b/src/celengine/body.h index 02131a68..4c2ccdd7 100644 --- a/src/celengine/body.h +++ b/src/celengine/body.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,7 @@ class RingSystem float outerRadius; Color color; MultiResTexture texture; - GLuint vboId{ 0 }; + std::array vboId {{ 0, 0, 0, 0 }}; RingSystem(float inner, float outer) : innerRadius(inner), outerRadius(outer), diff --git a/src/celengine/render.cpp b/src/celengine/render.cpp index 67d34168..46bb8a8c 100644 --- a/src/celengine/render.cpp +++ b/src/celengine/render.cpp @@ -4783,15 +4783,20 @@ void Renderer::renderObject(const Vector3f& pos, } } - if (obj.rings != nullptr && - (renderFlags & ShowPlanetRings) != 0 && - distance <= obj.rings->innerRadius) + float segmentSizeInPixels = 0.0f; + if (obj.rings != nullptr && (renderFlags & ShowPlanetRings) != 0) { - renderRings_GLSL(*obj.rings, ri, ls, - radius, 1.0f - obj.semiAxes.y(), - textureResolution, - (renderFlags & ShowRingShadows) != 0 && lit, - this); + // calculate ring segment size in pixels, actual size is segmentSizeInPixels * tan(segmentAngle) + segmentSizeInPixels = 2.0f * obj.rings->outerRadius / (max(nearPlaneDistance, altitude) * pixelSize); + if (distance <= obj.rings->innerRadius) + { + renderRings_GLSL(*obj.rings, ri, ls, + radius, 1.0f - obj.semiAxes.y(), + textureResolution, + (renderFlags & ShowRingShadows) != 0 && lit, + segmentSizeInPixels, + this); + } } if (obj.atmosphere != nullptr) @@ -4958,6 +4963,7 @@ void Renderer::renderObject(const Vector3f& pos, radius, 1.0f - obj.semiAxes.y(), textureResolution, (renderFlags & ShowRingShadows) != 0 && lit, + segmentSizeInPixels, this); } } diff --git a/src/celengine/renderglsl.cpp b/src/celengine/renderglsl.cpp index 73e37760..fec323d7 100644 --- a/src/celengine/renderglsl.cpp +++ b/src/celengine/renderglsl.cpp @@ -588,7 +588,8 @@ renderAtmosphere_GLSL(const RenderInfo& ri, static void renderRingSystem(GLuint *vboId, float innerRadius, - float outerRadius) + float outerRadius, + unsigned int nSections = 180) { struct RingVertex { @@ -597,12 +598,12 @@ static void renderRingSystem(GLuint *vboId, }; constexpr const float angle = 2*static_cast(PI); - constexpr const unsigned int nSections = 180; if (*vboId == 0) { struct RingVertex vertex; vector ringCoord; + ringCoord.reserve(2 * nSections); for (unsigned i = 0; i <= nSections; i++) { float t = (float) i / (float) nSections; @@ -669,6 +670,7 @@ void renderRings_GLSL(RingSystem& rings, float planetOblateness, unsigned int textureResolution, bool renderShadow, + float segmentSizeInPixels, const Renderer* renderer) { float inner = rings.innerRadius / planetRadius; @@ -773,7 +775,16 @@ void renderRings_GLSL(RingSystem& rings, else glDisable(GL_TEXTURE_2D); - renderRingSystem(&rings.vboId, inner, outer); + unsigned nSections = 180; + size_t i = 0; + for (i = 0; i < rings.vboId.size() - 1; i++) + { + float s = segmentSizeInPixels * tan(PI / nSections); + if (s < 30.0f) // TODO: make configurable + break; + nSections <<= 1; + } + renderRingSystem(&rings.vboId[i], inner, outer, nSections); glBlendFunc(GL_SRC_ALPHA, GL_ONE); diff --git a/src/celengine/renderglsl.h b/src/celengine/renderglsl.h index 016719ee..91b28844 100644 --- a/src/celengine/renderglsl.h +++ b/src/celengine/renderglsl.h @@ -68,6 +68,7 @@ void renderRings_GLSL(RingSystem& rings, float planetOblateness, unsigned int textureResolution, bool renderShadow, + float segmentSizeInPixels, const Renderer* renderer); void renderGeometry_GLSL_Unlit(Geometry* geometry,