From d5fbd2001b0ad3591a7f969dfd75c809ab55b40e Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Fri, 30 Jun 2023 04:34:10 +1000 Subject: [PATCH] RenderPrimitive micro-optimizations --- source/application/StarRenderer.cpp | 95 ++++++++++++------- source/application/StarRenderer.hpp | 27 +++++- source/application/StarRenderer_opengl20.cpp | 15 ++- source/application/StarRenderer_opengl20.hpp | 3 +- source/core/StarVariant.hpp | 17 ++++ source/frontend/StarCinematic.cpp | 21 +++-- source/game/StarWorldClient.cpp | 60 ++++++------ source/game/StarWorldClient.hpp | 1 + source/rendering/StarDrawablePainter.cpp | 35 +++---- source/rendering/StarEnvironmentPainter.cpp | 97 +++++++++++--------- source/rendering/StarTextPainter.cpp | 5 +- source/rendering/StarTilePainter.cpp | 75 +++++++-------- source/rendering/StarWorldPainter.cpp | 17 ++-- source/windowing/StarGuiContext.cpp | 36 ++++---- 14 files changed, 307 insertions(+), 197 deletions(-) diff --git a/source/application/StarRenderer.cpp b/source/application/StarRenderer.cpp index 51b11c7..f4aa4fe 100644 --- a/source/application/StarRenderer.cpp +++ b/source/application/StarRenderer.cpp @@ -12,49 +12,78 @@ EnumMap const TextureFilteringNames{ {TextureFiltering::Linear, "Linear"} }; -RenderQuad renderTexturedRect(TexturePtr texture, Vec2F minPosition, float textureScale, Vec4B color, float param1) { - if (!texture) - throw RendererException("renderTexturedRect called with null texture"); +RenderQuad::RenderQuad(Vec2F posA, Vec2F posB, Vec2F posC, Vec2F posD, Vec4B color, float param1) : texture() { + a = { posA, { 0, 0 }, color, param1 }; + b = { posB, { 0, 0 }, color, param1 }; + c = { posC, { 0, 0 }, color, param1 }; + d = { posD, { 0, 0 }, color, param1 }; +} - auto textureSize = Vec2F(texture->size()); - return { - move(texture), - RenderVertex{minPosition, Vec2F(0, 0), color, param1}, - RenderVertex{minPosition + Vec2F(textureSize[0], 0) * textureScale, Vec2F(textureSize[0], 0), color, param1}, - RenderVertex{minPosition + Vec2F(textureSize[0], textureSize[1]) * textureScale, Vec2F(textureSize[0], textureSize[1]), color, param1}, - RenderVertex{minPosition + Vec2F(0, textureSize[1]) * textureScale, Vec2F(0, textureSize[1]), color, param1} - }; +RenderQuad::RenderQuad(TexturePtr tex, Vec2F minPosition, float textureScale, Vec4B color, float param1) : texture(move(tex)) { + Vec2F size = Vec2F(texture->size()); + a = { minPosition, { 0, 0 }, color, param1}; + b = { { (minPosition[0] + size[0] * textureScale), minPosition[1] }, { size[0], 0 }, color, param1 }; + c = { { (minPosition[0] + size[0] * textureScale), (minPosition[1] + size[1] * textureScale) }, size, color, param1 }; + d = { { minPosition[0], (minPosition[1] + size[1] * textureScale) }, { 0, size[1] }, color, param1 }; +} + +RenderQuad::RenderQuad(TexturePtr tex, RectF const& screenCoords, Vec4B color, float param1) : texture(move(tex)) { + Vec2F size = Vec2F(texture->size()); + a = { screenCoords.min(), { 0, 0 }, color, param1 }; + b = { { screenCoords.xMax(), screenCoords.yMin(), }, { size[0], 0.f }, color, param1 }; + c = { screenCoords.max(), size, color, param1}; + d = { { screenCoords.xMin(), screenCoords.yMax(), }, { 0.f, size[1] }, color, param1 }; +} + +RenderQuad::RenderQuad(TexturePtr tex, Vec2F posA, Vec2F uvA, Vec2F posB, Vec2F uvB, Vec2F posC, Vec2F uvC, Vec2F posD, Vec2F uvD, Vec4B color, float param1) : texture(move(tex)) { + a = { posA, uvA, color, param1 }; + b = { posB, uvB, color, param1 }; + c = { posC, uvC, color, param1 }; + d = { posD, uvD, color, param1 }; +} + +RenderQuad::RenderQuad(TexturePtr tex, RenderVertex vA, RenderVertex vB, RenderVertex vC, RenderVertex vD) + : texture(move(tex)), a(move(vA)), b(move(vB)), c(move(vC)), d(move(vD)) {} + +RenderQuad::RenderQuad(RectF const& rect, Vec4B color, float param1) + : a{ rect.min(), {}, color, param1 } + , b{ { rect.xMax(), rect.yMin()}, {}, color, param1 } + , c{ rect.max(), {}, color, param1 } + , d{ { rect.xMin() ,rect.yMax() }, {}, color, param1 } {}; + + +RenderPoly::RenderPoly(List const& verts, Vec4B color, float param1) { + vertexes.reserve(verts.size()); + for (Vec2F const& v : verts) + vertexes.append({ v, { 0, 0 }, color, param1 }); +} + +RenderTriangle::RenderTriangle(Vec2F posA, Vec2F posB, Vec2F posC, Vec4B color, float param1) : texture() { + a = { posA, { 0, 0 }, color, param1 }; + b = { posB, { 0, 0 }, color, param1 }; + c = { posC, { 0, 0 }, color, param1 }; +} + +RenderTriangle::RenderTriangle(TexturePtr tex, Vec2F posA, Vec2F uvA, Vec2F posB, Vec2F uvB, Vec2F posC, Vec2F uvC, Vec4B color, float param1) : texture(move(tex)) { + a = { posA, uvA, color, param1 }; + b = { posB, uvB, color, param1 }; + c = { posC, uvC, color, param1 }; +} + +RenderQuad renderTexturedRect(TexturePtr texture, Vec2F minPosition, float textureScale, Vec4B color, float param1) { + return RenderQuad(move(texture), minPosition, textureScale, color, param1); } RenderQuad renderTexturedRect(TexturePtr texture, RectF const& screenCoords, Vec4B color, float param1) { - if (!texture) - throw RendererException("renderTexturedRect called with null texture"); - - auto textureSize = Vec2F(texture->size()); - return { - move(texture), - RenderVertex{{screenCoords.xMin(), screenCoords.yMin()}, Vec2F(0, 0), color, param1}, - RenderVertex{{screenCoords.xMax(), screenCoords.yMin()}, Vec2F(textureSize[0], 0), color, param1}, - RenderVertex{{screenCoords.xMax(), screenCoords.yMax()}, Vec2F(textureSize[0], textureSize[1]), color, param1}, - RenderVertex{{screenCoords.xMin(), screenCoords.yMax()}, Vec2F(0, textureSize[1]), color, param1} - }; + return RenderQuad(move(texture), screenCoords, color, param1); } RenderQuad renderFlatRect(RectF const& rect, Vec4B color, float param1) { - return { - {}, - RenderVertex{{rect.xMin(), rect.yMin()}, {}, color, param1}, - RenderVertex{{rect.xMax(), rect.yMin()}, {}, color, param1}, - RenderVertex{{rect.xMax(), rect.yMax()}, {}, color, param1}, - RenderVertex{{rect.xMin(), rect.yMax()}, {}, color, param1} - }; + return RenderQuad(rect, color, param1); } RenderPoly renderFlatPoly(PolyF const& poly, Vec4B color, float param1) { - RenderPoly renderPoly; - for (auto const& v : poly) - renderPoly.vertexes.append({v, {}, color, param1}); - return renderPoly; + return RenderPoly(poly.vertexes(), color, param1); } } diff --git a/source/application/StarRenderer.hpp b/source/application/StarRenderer.hpp index e12590f..908f121 100644 --- a/source/application/StarRenderer.hpp +++ b/source/application/StarRenderer.hpp @@ -50,17 +50,35 @@ struct RenderVertex { float param1; }; -struct RenderTriangle { +class RenderTriangle { +public: + RenderTriangle() = default; + RenderTriangle(Vec2F posA, Vec2F posB, Vec2F posC, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + RenderTriangle(TexturePtr tex, Vec2F posA, Vec2F uvA, Vec2F posB, Vec2F uvB, Vec2F posC, Vec2F uvC, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + TexturePtr texture; RenderVertex a, b, c; }; -struct RenderQuad { +class RenderQuad { +public: + RenderQuad() = default; + RenderQuad(Vec2F posA, Vec2F posB, Vec2F posC, Vec2F posD, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + RenderQuad(TexturePtr tex, Vec2F minScreen, float textureScale = 1.0f, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + RenderQuad(TexturePtr tex, RectF const& screenCoords, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + RenderQuad(TexturePtr tex, Vec2F posA, Vec2F uvA, Vec2F posB, Vec2F uvB, Vec2F posC, Vec2F uvC, Vec2F posD, Vec2F uvD, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + RenderQuad(TexturePtr tex, RenderVertex vA, RenderVertex vB, RenderVertex vC, RenderVertex vD); + RenderQuad(RectF const& rect, Vec4B color = Vec4B::filled(255), float param1 = 0.0f); + TexturePtr texture; RenderVertex a, b, c, d; }; -struct RenderPoly { +class RenderPoly { +public: + RenderPoly() = default; + RenderPoly(List const& verts, Vec4B color, float param1 = 0.0f); + TexturePtr texture; List vertexes; }; @@ -100,7 +118,7 @@ public: // Transforms the given primitives into a form suitable for the underlying // graphics system and stores it for fast replaying. - virtual void set(List primitives) = 0; + virtual void set(List& primitives) = 0; }; typedef Variant RenderEffectParameter; @@ -136,6 +154,7 @@ public: virtual TextureGroupPtr createTextureGroup(TextureGroupSize size = TextureGroupSize::Medium, TextureFiltering filtering = TextureFiltering::Nearest) = 0; virtual RenderBufferPtr createRenderBuffer() = 0; + virtual List& immediatePrimitives() = 0; virtual void render(RenderPrimitive primitive) = 0; virtual void renderBuffer(RenderBufferPtr const& renderBuffer, Mat3F const& transformation = Mat3F::identity()) = 0; diff --git a/source/application/StarRenderer_opengl20.cpp b/source/application/StarRenderer_opengl20.cpp index 82d4845..375149e 100644 --- a/source/application/StarRenderer_opengl20.cpp +++ b/source/application/StarRenderer_opengl20.cpp @@ -366,6 +366,10 @@ RenderBufferPtr OpenGl20Renderer::createRenderBuffer() { return createGlRenderBuffer(); } +List& OpenGl20Renderer::immediatePrimitives() { + return m_immediatePrimitives; +} + void OpenGl20Renderer::render(RenderPrimitive primitive) { m_immediatePrimitives.append(move(primitive)); } @@ -399,7 +403,8 @@ void OpenGl20Renderer::finishFrame() { flushImmediatePrimitives(); // Make sure that the immediate render buffer doesn't needlessly lock texutres // from being compressed. - m_immediateRenderBuffer->set({}); + List empty; + m_immediateRenderBuffer->set(empty); filter(m_liveTextureGroups, [](auto const& p) { unsigned const CompressionsPerFrame = 1; @@ -569,7 +574,7 @@ OpenGl20Renderer::GlRenderBuffer::~GlRenderBuffer() { glDeleteBuffers(1, &vb.vertexBuffer); } -void OpenGl20Renderer::GlRenderBuffer::set(List primitives) { +void OpenGl20Renderer::GlRenderBuffer::set(List& primitives) { for (auto const& texture : usedTextures) { if (auto gt = as(texture.get())) gt->decrementBufferUseCount(); @@ -637,7 +642,7 @@ void OpenGl20Renderer::GlRenderBuffer::set(List primitives) { return {float(textureIndex), Vec2F(glTexture->glTextureCoordinateOffset())}; }; - auto appendBufferVertex = [&](RenderVertex v, float textureIndex, Vec2F textureCoordinateOffset) { + auto appendBufferVertex = [&](RenderVertex const& v, float textureIndex, Vec2F textureCoordinateOffset) { GlRenderVertex glv { v.screenCoordinate, v.textureCoordinate + textureCoordinateOffset, @@ -682,6 +687,7 @@ void OpenGl20Renderer::GlRenderBuffer::set(List primitives) { } } + vertexBuffers.reserve(primitives.size() * 6); finishCurrentBuffer(); for (auto const& vb : oldVertexBuffers) @@ -733,7 +739,8 @@ void OpenGl20Renderer::flushImmediatePrimitives() { if (m_immediatePrimitives.empty()) return; - m_immediateRenderBuffer->set(take(m_immediatePrimitives)); + m_immediateRenderBuffer->set(m_immediatePrimitives); + m_immediatePrimitives.resize(0); renderGlBuffer(*m_immediateRenderBuffer, Mat3F::identity()); } diff --git a/source/application/StarRenderer_opengl20.hpp b/source/application/StarRenderer_opengl20.hpp index dfab534..ff82d3a 100644 --- a/source/application/StarRenderer_opengl20.hpp +++ b/source/application/StarRenderer_opengl20.hpp @@ -32,6 +32,7 @@ public: TextureGroupPtr createTextureGroup(TextureGroupSize size, TextureFiltering filtering) override; RenderBufferPtr createRenderBuffer() override; + List& immediatePrimitives() override; void render(RenderPrimitive primitive) override; void renderBuffer(RenderBufferPtr const& renderBuffer, Mat3F const& transformation) override; @@ -128,7 +129,7 @@ private: ~GlRenderBuffer(); - void set(List primitives) override; + void set(List& primitives) override; RefPtr whiteTexture; ByteArray accumulationBuffer; diff --git a/source/core/StarVariant.hpp b/source/core/StarVariant.hpp index 043cd1d..39779c1 100644 --- a/source/core/StarVariant.hpp +++ b/source/core/StarVariant.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "StarAlgorithm.hpp" #include "StarMaybe.hpp" @@ -70,6 +71,22 @@ public: template > Variant(T&& x); + template , typename... Args, + typename std::enable_if< std::is_constructible::value, int >::type = 0 + > + Variant(std::in_place_type_t, Args&&... args) { + new (&m_buffer) T(forward(args)...); + m_typeIndex = TypeIndex::value; + } + + template , typename... Args, + typename std::enable_if< std::is_constructible&, Args...>::value, int >::type = 0 + > + Variant(std::in_place_type_t, std::initializer_list il, Args&&... args) { + new (&m_buffer) T(il, forward(args)...); + m_typeIndex = TypeIndex::value; + } + Variant(Variant const& x); Variant(Variant&& x) noexcept(detail::IsNothrowMoveConstructible::value); diff --git a/source/frontend/StarCinematic.cpp b/source/frontend/StarCinematic.cpp index 7408264..7470410 100644 --- a/source/frontend/StarCinematic.cpp +++ b/source/frontend/StarCinematic.cpp @@ -245,15 +245,17 @@ void Cinematic::render() { void Cinematic::drawDrawable(Drawable const& drawable, float drawableScale, Vec2F const& drawableTranslation) { auto& guiContext = GuiContext::singleton(); - auto renderer = guiContext.renderer(); - auto textureGroup = guiContext.assetTextureGroup(); + auto& renderer = guiContext.renderer(); + auto& textureGroup = guiContext.assetTextureGroup(); + + auto& primitives = renderer->immediatePrimitives(); if (drawable.isImage()) { auto const& imagePart = drawable.imagePart(); auto texture = textureGroup->loadTexture(imagePart.image); - auto textureSize = Vec2F(texture->size()); + auto size = Vec2F(texture->size()); - RectF imageRect(Vec2F(), textureSize); + RectF imageRect(Vec2F(), size); Vec2F screenTranslation = drawable.position * drawableScale + drawableTranslation; @@ -272,11 +274,12 @@ void Cinematic::drawDrawable(Drawable const& drawable, float drawableScale, Vec2 Vec4B drawableColor = drawable.color.toRgba(); - renderer->render(RenderQuad{move(texture), - RenderVertex{lowerLeft, Vec2F(0, 0), drawableColor, 0.0f}, - RenderVertex{lowerRight, Vec2F(textureSize[0], 0), drawableColor, 0.0f}, - RenderVertex{upperRight, Vec2F(textureSize[0], textureSize[1]), drawableColor, 0.0f}, - RenderVertex{upperLeft, Vec2F(0, textureSize[1]), drawableColor, 0.0f}}); + primitives.emplace_back(std::in_place_type_t(), move(texture), + lowerLeft, Vec2F{0, 0}, + lowerRight, Vec2F{size[0], 0}, + upperRight, Vec2F{size[0], size[1]}, + upperLeft, Vec2F{0, size[1]}, + drawableColor, 0.0f); } else { starAssert(drawable.part.empty()); } diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index 758ba12..ed04d67 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -384,32 +384,8 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) { } else { m_lightingCalculator.begin(lightRange); - Vec3F environmentLight = m_sky->environmentLight().toRgbF(); - float undergroundLevel = m_worldTemplate->undergroundLevel(); - auto liquidsDatabase = Root::singleton().liquidsDatabase(); - auto materialDatabase = Root::singleton().materialDatabase(); - - // Each column in tileEvalColumns is guaranteed to be no larger than the sector size. - m_tileArray->tileEvalColumns(m_lightingCalculator.calculationRegion(), [&](Vec2I const& pos, ClientTile const* column, size_t ySize) { - size_t baseIndex = m_lightingCalculator.baseIndexFor(pos); - for (size_t y = 0; y < ySize; ++y) { - auto& tile = column[y]; - - Vec3F light; - if (tile.foreground != EmptyMaterialId || tile.foregroundMod != NoModId) - light += materialDatabase->radiantLight(tile.foreground, tile.foregroundMod); - - if (tile.liquid.liquid != EmptyLiquidId && tile.liquid.level != 0.0f) - light += liquidsDatabase->radiantLight(tile.liquid); - if (tile.foregroundLightTransparent) { - if (tile.background != EmptyMaterialId || tile.backgroundMod != NoModId) - light += materialDatabase->radiantLight(tile.background, tile.backgroundMod); - if (tile.backgroundLightTransparent && pos[1] + y > undergroundLevel) - light += environmentLight; - } - m_lightingCalculator.setCellIndex(baseIndex + y, move(light), !tile.foregroundLightTransparent); - } - }); + if (!m_asyncLighting) + lightingTileGather(); for (auto const& light : renderLightSources) { Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), light.position); @@ -1439,6 +1415,35 @@ RpcPromise WorldClient::interact(InteractRequest const& request) return pair.first; } +void WorldClient::lightingTileGather() { + Vec3F environmentLight = m_sky->environmentLight().toRgbF(); + float undergroundLevel = m_worldTemplate->undergroundLevel(); + auto liquidsDatabase = Root::singleton().liquidsDatabase(); + auto materialDatabase = Root::singleton().materialDatabase(); + + // Each column in tileEvalColumns is guaranteed to be no larger than the sector size. + m_tileArray->tileEvalColumns(m_lightingCalculator.calculationRegion(), [&](Vec2I const& pos, ClientTile const* column, size_t ySize) { + size_t baseIndex = m_lightingCalculator.baseIndexFor(pos); + for (size_t y = 0; y < ySize; ++y) { + auto& tile = column[y]; + + Vec3F light; + if (tile.foreground != EmptyMaterialId || tile.foregroundMod != NoModId) + light += materialDatabase->radiantLight(tile.foreground, tile.foregroundMod); + + if (tile.liquid.liquid != EmptyLiquidId && tile.liquid.level != 0.0f) + light += liquidsDatabase->radiantLight(tile.liquid); + if (tile.foregroundLightTransparent) { + if (tile.background != EmptyMaterialId || tile.backgroundMod != NoModId) + light += materialDatabase->radiantLight(tile.background, tile.backgroundMod); + if (tile.backgroundLightTransparent && pos[1] + y > undergroundLevel) + light += environmentLight; + } + m_lightingCalculator.setCellIndex(baseIndex + y, move(light), !tile.foregroundLightTransparent); + } + }); +} + void WorldClient::lightingMain() { while (true) { if (m_stopLightingThread) @@ -1448,6 +1453,9 @@ void WorldClient::lightingMain() { if (m_renderData) { int64_t start = Time::monotonicMilliseconds(); + + lightingTileGather(); + m_lightingCalculator.calculate(m_renderData->lightMap); m_renderData = nullptr; LogMap::set("render_light_calc", strf("{}ms", Time::monotonicMilliseconds() - start)); diff --git a/source/game/StarWorldClient.hpp b/source/game/StarWorldClient.hpp index c5fbfd0..0686057 100644 --- a/source/game/StarWorldClient.hpp +++ b/source/game/StarWorldClient.hpp @@ -190,6 +190,7 @@ private: bool operator<(DamageNumberKey const& other) const; }; + void lightingTileGather(); void lightingMain(); void initWorld(WorldStartPacket const& packet); diff --git a/source/rendering/StarDrawablePainter.cpp b/source/rendering/StarDrawablePainter.cpp index 647d209..8c50b2b 100644 --- a/source/rendering/StarDrawablePainter.cpp +++ b/source/rendering/StarDrawablePainter.cpp @@ -9,24 +9,25 @@ DrawablePainter::DrawablePainter(RendererPtr renderer, AssetTextureGroupPtr text void DrawablePainter::drawDrawable(Drawable const& drawable) { Vec4B color = drawable.color.toRgba(); + auto& primitives = m_renderer->immediatePrimitives(); if (auto linePart = drawable.part.ptr()) { auto line = linePart->line; line.translate(drawable.position); - Vec2F left = Vec2F(vnorm(line.diff())).rot90() * linePart->width / 2.0f; - m_renderer->render(RenderQuad{{}, - RenderVertex{Vec2F(line.min()) + left, Vec2F(), color, drawable.fullbright ? 0.0f : 1.0f}, - RenderVertex{Vec2F(line.min()) - left, Vec2F(), color, drawable.fullbright ? 0.0f : 1.0f}, - RenderVertex{Vec2F(line.max()) - left, Vec2F(), color, drawable.fullbright ? 0.0f : 1.0f}, - RenderVertex{Vec2F(line.max()) + left, Vec2F(), color, drawable.fullbright ? 0.0f : 1.0f} - }); - + + float fullbright = drawable.fullbright ? 0.0f : 1.0f; + primitives.emplace_back(std::in_place_type_t(), + line.min() + left, + line.min() - left, + line.max() - left, + line.max() + left, + color, fullbright); } else if (auto polyPart = drawable.part.ptr()) { - auto poly = polyPart->poly; + PolyF poly = polyPart->poly; poly.translate(drawable.position); - m_renderer->render(renderFlatPoly(poly, color, 0.0f)); + primitives.emplace_back(std::in_place_type_t(), poly.vertexes(), color, 0.0f); } else if (auto imagePart = drawable.part.ptr()) { TexturePtr texture = m_textureGroup->loadTexture(imagePart->image); @@ -41,12 +42,14 @@ void DrawablePainter::drawDrawable(Drawable const& drawable) { Vec2F upperRight = transformation.transformVec2(Vec2F(imageRect.xMax(), imageRect.yMax())); Vec2F upperLeft = transformation.transformVec2(Vec2F(imageRect.xMin(), imageRect.yMax())); - m_renderer->render(RenderQuad{move(texture), - {lowerLeft, {0, 0}, color, drawable.fullbright ? 0.0f : 1.0f}, - {lowerRight, {textureSize[0], 0}, color, drawable.fullbright ? 0.0f : 1.0f}, - {upperRight, {textureSize[0], textureSize[1]}, color, drawable.fullbright ? 0.0f : 1.0f}, - {upperLeft, {0, textureSize[1]}, color, drawable.fullbright ? 0.0f : 1.0f} - }); + float param1 = drawable.fullbright ? 0.0f : 1.0f; + + primitives.emplace_back(std::in_place_type_t(), move(texture), + lowerLeft, Vec2F{0, 0}, + lowerRight, Vec2F{textureSize[0], 0}, + upperRight, Vec2F{textureSize[0], textureSize[1]}, + upperLeft, Vec2F{0, textureSize[1]}, + color, param1); } } diff --git a/source/rendering/StarEnvironmentPainter.cpp b/source/rendering/StarEnvironmentPainter.cpp index 9d3e45a..94bf364 100644 --- a/source/rendering/StarEnvironmentPainter.cpp +++ b/source/rendering/StarEnvironmentPainter.cpp @@ -3,6 +3,8 @@ #include "StarTime.hpp" #include "StarXXHash.hpp" #include "StarJsonExtra.hpp" +#include "StarLogging.hpp" +#include "StarMathCommon.hpp" namespace Star { @@ -80,12 +82,14 @@ void EnvironmentPainter::renderStars(float pixelRatio, Vec2F const& screenSize, RectF viewRect = RectF::withSize(Vec2F(), viewSize).padded(screenBuffer); + auto& primitives = m_renderer->immediatePrimitives(); + for (auto& star : stars) { Vec2F screenPos = transform.transformVec2(star.first); if (viewRect.contains(screenPos)) { size_t starFrame = (size_t)(sky.epochTime + star.second.second) % sky.starFrames; auto const& texture = m_starTextures[star.second.first * sky.starFrames + starFrame]; - m_renderer->render(renderTexturedRect(texture, screenPos * pixelRatio - Vec2F(texture->size()) / 2, 1.0, color, 0.0f)); + primitives.emplace_back(std::in_place_type_t(), texture, screenPos * pixelRatio - Vec2F(texture->size()) / 2, 1.0, color, 0.0f); } } @@ -99,7 +103,6 @@ void EnvironmentPainter::renderDebrisFields(float pixelRatio, Vec2F const& scree if (sky.type == SkyType::Orbital || sky.type == SkyType::Warp) { Vec2F viewSize = screenSize / pixelRatio; Vec2F viewCenter = viewSize / 2; - Vec2F viewMin = sky.starOffset - viewCenter; Mat3F rotMatrix = Mat3F::rotation(sky.starRotation, viewCenter); @@ -114,23 +117,29 @@ void EnvironmentPainter::renderDebrisFields(float pixelRatio, Vec2F const& scree // Translate the entire field to make the debris seem as though they are moving Vec2F velocityOffset = -Vec2F(debrisXVel, debrisYVel) * sky.epochTime; - float screenBuffer = debrisField.queryFloat("screenBuffer"); - PolyF field = PolyF(RectF::withSize(viewMin, viewSize).padded(screenBuffer).translated(velocityOffset)); + JsonArray imageOptions = debrisField.query("list").toArray(); + Vec2U biggest = Vec2U(); + for (Json const& json : imageOptions) { + TexturePtr texture = m_textureGroup->loadTexture(*json.stringPtr()); + biggest = biggest.piecewiseMax(texture->size()); + } + + float screenBuffer = ceil((float)biggest.max() * (float)Constants::sqrt2) * 2.0f; + PolyF field = PolyF(RectF::withSize(sky.starOffset, viewSize).padded(screenBuffer).translated(velocityOffset)); Vec2F debrisAngularVelocityRange = jsonToVec2F(debrisField.query("angularVelocityRange")); - JsonArray imageOptions = debrisField.query("list").toArray(); auto debrisItems = m_debrisGenerators[i]->generate(field, [&](RandomSource& rand) { - String debrisImage = rand.randFrom(imageOptions).toString(); + StringView debrisImage = *rand.randFrom(imageOptions).stringPtr(); float debrisAngularVelocity = rand.randf(debrisAngularVelocityRange[0], debrisAngularVelocityRange[1]); - return pair(debrisImage, debrisAngularVelocity); + return pair(debrisImage, debrisAngularVelocity); }); - Vec2F debrisPositionOffset = -(sky.starOffset + velocityOffset + viewCenter); + Vec2F debrisPositionOffset = -(sky.starOffset + velocityOffset); - for (auto debrisItem : debrisItems) { + for (auto& debrisItem : debrisItems) { Vec2F debrisPosition = rotMatrix.transformVec2(debrisItem.first + debrisPositionOffset); float debrisAngle = fmod(Constants::deg2rad * debrisItem.second.second * sky.epochTime, Constants::pi * 2) + sky.starRotation; drawOrbiter(pixelRatio, screenSize, sky, {SkyOrbiterType::SpaceDebris, 1.0f, debrisAngle, debrisItem.second.first, debrisPosition}); @@ -166,6 +175,8 @@ void EnvironmentPainter::renderPlanetHorizon(float pixelRatio, Vec2F const& scre float planetPixelRatio = pixelRatio * planetHorizon.scale; Vec2F center = planetHorizon.center * pixelRatio; + auto& primitives = m_renderer->immediatePrimitives(); + for (auto const& layer : planetHorizon.layers) { TexturePtr leftTexture = m_textureGroup->loadTexture(layer.first); Vec2F leftTextureSize(leftTexture->size()); @@ -182,17 +193,17 @@ void EnvironmentPainter::renderPlanetHorizon(float pixelRatio, Vec2F const& scre PolyF rightImage = PolyF(rightRect); rightImage.rotate(planetHorizon.rotation, center); - m_renderer->render(RenderQuad{move(leftTexture), - {leftImage[0], Vec2F(0, 0), {255, 255, 255, 255}, 0.0f}, - {leftImage[1], Vec2F(leftTextureSize[0], 0), {255, 255, 255, 255}, 0.0f}, - {leftImage[2], Vec2F(leftTextureSize[0], leftTextureSize[1]), {255, 255, 255, 255}, 0.0f}, - {leftImage[3], Vec2F(0, leftTextureSize[1]), {255, 255, 255, 255}, 0.0f}}); + primitives.emplace_back(std::in_place_type_t(), move(leftTexture), + leftImage[0], Vec2F(0, 0), + leftImage[1], Vec2F(leftTextureSize[0], 0), + leftImage[2], Vec2F(leftTextureSize[0], leftTextureSize[1]), + leftImage[3], Vec2F(0, leftTextureSize[1]), Vec4B::filled(255), 0.0f); - m_renderer->render(RenderQuad{move(rightTexture), - {rightImage[0], Vec2F(0, 0), {255, 255, 255, 255}, 0.0f}, - {rightImage[1], Vec2F(rightTextureSize[0], 0), {255, 255, 255, 255}, 0.0f}, - {rightImage[2], Vec2F(rightTextureSize[0], rightTextureSize[1]), {255, 255, 255, 255}, 0.0f}, - {rightImage[3], Vec2F(0, rightTextureSize[1]), {255, 255, 255, 255}, 0.0f}}); + primitives.emplace_back(std::in_place_type_t(), move(rightTexture), + rightImage[0], Vec2F(0, 0), + rightImage[1], Vec2F(rightTextureSize[0], 0), + rightImage[2], Vec2F(rightTextureSize[0], rightTextureSize[1]), + rightImage[3], Vec2F(0, rightTextureSize[1]), Vec4B::filled(255), 0.0f); } m_renderer->flush(); @@ -206,15 +217,16 @@ void EnvironmentPainter::renderFrontOrbiters(float pixelRatio, Vec2F const& scre } void EnvironmentPainter::renderSky(Vec2F const& screenSize, SkyRenderData const& sky) { - m_renderer->render(RenderQuad{{}, - {Vec2F(0, 0), Vec2F(), sky.bottomRectColor.toRgba(), 0.0f}, - {Vec2F(screenSize[0], 0), Vec2F(), sky.bottomRectColor.toRgba(), 0.0f}, - {screenSize, Vec2F(), sky.topRectColor.toRgba(), 0.0f}, - {Vec2F(0, screenSize[1]), Vec2F(), sky.topRectColor.toRgba(), 0.0f}}); + auto& primitives = m_renderer->immediatePrimitives(); + primitives.emplace_back(std::in_place_type_t(), TexturePtr(), + RenderVertex{Vec2F(0, 0), Vec2F(), sky.bottomRectColor.toRgba(), 0.0f}, + RenderVertex{Vec2F(screenSize[0], 0), Vec2F(), sky.bottomRectColor.toRgba(), 0.0f}, + RenderVertex{screenSize, Vec2F(), sky.topRectColor.toRgba(), 0.0f}, + RenderVertex{Vec2F(0, screenSize[1]), Vec2F(), sky.topRectColor.toRgba(), 0.0f}); // Flash overlay for Interstellar travel Vec4B flashColor = sky.flashColor.toRgba(); - m_renderer->render(renderFlatRect(RectF(Vec2F(), screenSize), flashColor, 0.0f)); + primitives.emplace_back(std::in_place_type_t(), RectF(Vec2F(), screenSize), flashColor, 0.0f); m_renderer->flush(); } @@ -224,6 +236,8 @@ void EnvironmentPainter::renderParallaxLayers( // Note: the "parallax space" referenced below is a grid where the scale of each cell is the size of the parallax image + auto& primitives = m_renderer->immediatePrimitives(); + for (auto& layer : layers) { if (layer.alpha == 0) continue; @@ -307,11 +321,11 @@ void EnvironmentPainter::renderParallaxLayers( withDirectives.directives += layer.directives; if (auto texture = m_textureGroup->tryTexture(withDirectives)) { RectF drawRect = RectF::withSize(anchorPoint, subImage.size() * camera.pixelRatio()); - m_renderer->render(RenderQuad{move(texture), - {{drawRect.xMin(), drawRect.yMin()}, {subImage.xMin(), subImage.yMin()}, drawColor, lightMapMultiplier}, - {{drawRect.xMax(), drawRect.yMin()}, {subImage.xMax(), subImage.yMin()}, drawColor, lightMapMultiplier}, - {{drawRect.xMax(), drawRect.yMax()}, {subImage.xMax(), subImage.yMax()}, drawColor, lightMapMultiplier}, - {{drawRect.xMin(), drawRect.yMax()}, {subImage.xMin(), subImage.yMax()}, drawColor, lightMapMultiplier}}); + primitives.emplace_back(std::in_place_type_t(), move(texture), + RenderVertex{drawRect.min(), subImage.min(), drawColor, lightMapMultiplier}, + RenderVertex{{drawRect.xMax(), drawRect.yMin()}, {subImage.xMax(), subImage.yMin()}, drawColor, lightMapMultiplier}, + RenderVertex{drawRect.max(), subImage.max(), drawColor, lightMapMultiplier}, + RenderVertex{{drawRect.xMin(), drawRect.yMax()}, {subImage.xMin(), subImage.yMax()}, drawColor, lightMapMultiplier}); } } } @@ -365,26 +379,27 @@ void EnvironmentPainter::drawRay(float pixelRatio, // Sum is used to vary the ray intensity based on sky color // Rays show up more on darker backgrounds, so this scales to remove that float sum = std::pow((color[0] + color[1]) * RayColorDependenceScale, RayColorDependenceLevel); - m_renderer->render(RenderQuad{{}, - {start + Vec2F(std::cos(angle + width), std::sin(angle + width)) * length, {}, Vec4B(RayColor, 0), 0.0f}, - {start + Vec2F(std::cos(angle + width), std::sin(angle + width)) * SunRadius * pixelRatio, + m_renderer->immediatePrimitives().emplace_back(std::in_place_type_t(), TexturePtr(), + RenderVertex{start + Vec2F(std::cos(angle + width), std::sin(angle + width)) * length, {}, Vec4B(RayColor, 0), 0.0f}, + RenderVertex{start + Vec2F(std::cos(angle + width), std::sin(angle + width)) * SunRadius * pixelRatio, {}, Vec4B(RayColor, (int)(RayMinUnscaledAlpha + std::abs(m_rayPerlin.get(angle * 896 + time * 30) * RayUnscaledAlphaVariance)) * sum * alpha), 0.0f}, - {start + Vec2F(std::cos(angle), std::sin(angle)) * SunRadius * pixelRatio, + RenderVertex{start + Vec2F(std::cos(angle), std::sin(angle)) * SunRadius * pixelRatio, {}, Vec4B(RayColor, (int)(RayMinUnscaledAlpha + std::abs(m_rayPerlin.get(angle * 626 + time * 30) * RayUnscaledAlphaVariance)) * sum * alpha), 0.0f}, - {start + Vec2F(std::cos(angle), std::sin(angle)) * length, {}, Vec4B(RayColor, 0), 0.0f}}); + RenderVertex{start + Vec2F(std::cos(angle), std::sin(angle)) * length, {}, Vec4B(RayColor, 0), 0.0f}); } void EnvironmentPainter::drawOrbiter(float pixelRatio, Vec2F const& screenSize, SkyRenderData const& sky, SkyOrbiter const& orbiter) { float alpha = 1.0f; - Vec2F position = orbiter.position * pixelRatio; + Vec2F screenCenter = screenSize / 2; + Vec2F position = screenCenter + (orbiter.position - screenCenter) * pixelRatio; if (orbiter.type == SkyOrbiterType::Sun) { alpha = sky.dayLevel; @@ -398,11 +413,11 @@ void EnvironmentPainter::drawOrbiter(float pixelRatio, Vec2F const& screenSize, RectF renderRect = RectF::withCenter(position, texSize * orbiter.scale * pixelRatio); Vec4B renderColor = Vec4B(255, 255, 255, 255 * alpha); - m_renderer->render(RenderQuad{move(texture), - {renderMatrix.transformVec2(renderRect.min()), Vec2F(0, 0), renderColor, 0.0f}, - {renderMatrix.transformVec2(Vec2F{renderRect.xMax(), renderRect.yMin()}), Vec2F(texSize[0], 0), renderColor, 0.0f}, - {renderMatrix.transformVec2(renderRect.max()), Vec2F(texSize[0], texSize[1]), renderColor, 0.0f}, - {renderMatrix.transformVec2(Vec2F{renderRect.xMin(), renderRect.yMax()}), Vec2F(0, texSize[1]), renderColor, 0.0f}}); + m_renderer->immediatePrimitives().emplace_back(std::in_place_type_t(), move(texture), + RenderVertex{renderMatrix.transformVec2(renderRect.min()), Vec2F(0, 0), renderColor, 0.0f}, + RenderVertex{renderMatrix.transformVec2(Vec2F{renderRect.xMax(), renderRect.yMin()}), Vec2F(texSize[0], 0), renderColor, 0.0f}, + RenderVertex{renderMatrix.transformVec2(renderRect.max()), Vec2F(texSize[0], texSize[1]), renderColor, 0.0f}, + RenderVertex{renderMatrix.transformVec2(Vec2F{renderRect.xMin(), renderRect.yMax()}), Vec2F(0, texSize[1]), renderColor, 0.0f}); } uint64_t EnvironmentPainter::starsHash(SkyRenderData const& sky, Vec2F const& viewSize) const { diff --git a/source/rendering/StarTextPainter.cpp b/source/rendering/StarTextPainter.cpp index 631000e..ca69fb1 100644 --- a/source/rendering/StarTextPainter.cpp +++ b/source/rendering/StarTextPainter.cpp @@ -539,6 +539,7 @@ RectF TextPainter::doRenderLine(StringView text, TextPositioning const& position RectF TextPainter::doRenderGlyph(String::Char c, TextPositioning const& position, bool reallyRender) { if (m_nonRenderedCharacters.find(String(c)) != NPos) return RectF(); + m_fontTextureGroup.switchFont(m_renderSettings.font); int width = glyphWidth(c); // Offset left by width if right anchored. @@ -581,8 +582,8 @@ void TextPainter::renderGlyph(String::Char c, Vec2F const& screenPos, unsigned f return; const FontTextureGroup::GlyphTexture& glyphTexture = m_fontTextureGroup.glyphTexture(c, fontSize, processingDirectives); - Vec2F offset = glyphTexture.processingOffset * (scale * 0.5f); //Kae: Re-center the glyph if the image scale was changed by the directives (it is positioned from the bottom left) - m_renderer->render(renderTexturedRect(glyphTexture.texture, Vec2F(screenPos) + offset, scale, color, 0.0f)); + Vec2F offset = glyphTexture.processingOffset * (scale * 0.5f); + m_renderer->immediatePrimitives().emplace_back(std::in_place_type_t(), glyphTexture.texture, screenPos + offset, scale, color, 0.0f); } } diff --git a/source/rendering/StarTilePainter.cpp b/source/rendering/StarTilePainter.cpp index fc115e5..2faf9d5 100644 --- a/source/rendering/StarTilePainter.cpp +++ b/source/rendering/StarTilePainter.cpp @@ -55,9 +55,6 @@ void TilePainter::adjustLighting(WorldRenderData& renderData) const { } void TilePainter::setup(WorldCamera const& camera, WorldRenderData& renderData) { - m_pendingTerrainChunks.clear(); - m_pendingLiquidChunks.clear(); - auto cameraCenter = camera.centerWorldPosition(); if (m_lastCameraCenter) m_cameraPan = renderData.geometry.diff(cameraCenter, *m_lastCameraCenter); @@ -66,10 +63,16 @@ void TilePainter::setup(WorldCamera const& camera, WorldRenderData& renderData) //Kae: Padded by one to fix culling issues with certain tile pieces at chunk borders, such as grass. RectI chunkRange = RectI::integral(RectF(camera.worldTileRect().padded(1)).scaled(1.0f / RenderChunkSize)); + size_t chunks = chunkRange.volume(); + m_pendingTerrainChunks.resize(chunks); + m_pendingLiquidChunks.resize(chunks); + + size_t i = 0; for (int x = chunkRange.xMin(); x < chunkRange.xMax(); ++x) { for (int y = chunkRange.yMin(); y < chunkRange.yMax(); ++y) { - m_pendingTerrainChunks.append(getTerrainChunk(renderData, {x, y})); - m_pendingLiquidChunks.append(getLiquidChunk(renderData, {x, y})); + size_t index = i++; + m_pendingTerrainChunks[index] = getTerrainChunk(renderData, {x, y}); + m_pendingLiquidChunks [index] = getLiquidChunk(renderData, {x, y}); } } } @@ -117,7 +120,7 @@ size_t TilePainter::TextureKeyHash::operator()(TextureKey const& key) const { } TilePainter::ChunkHash TilePainter::terrainChunkHash(WorldRenderData& renderData, Vec2I chunkIndex) { - XXHash64 hasher; + XXHash3 hasher; RectI tileRange = RectI::withSize(chunkIndex * RenderChunkSize, Vec2I::filled(RenderChunkSize)).padded(MaterialRenderProfileMaxNeighborDistance); forEachRenderTile(renderData, tileRange, [&](Vec2I const&, RenderTile const& renderTile) { @@ -128,7 +131,7 @@ TilePainter::ChunkHash TilePainter::terrainChunkHash(WorldRenderData& renderData } TilePainter::ChunkHash TilePainter::liquidChunkHash(WorldRenderData& renderData, Vec2I chunkIndex) { - XXHash64 hasher; + XXHash3 hasher; RectI tileRange = RectI::withSize(chunkIndex * RenderChunkSize, Vec2I::filled(RenderChunkSize)).padded(MaterialRenderProfileMaxNeighborDistance); forEachRenderTile(renderData, tileRange, [&](Vec2I const&, RenderTile const& renderTile) { @@ -334,13 +337,16 @@ bool TilePainter::produceTerrainPrimitives(HashMapvariants.get(materialColorVariant).wrap(variance); RectF worldCoords = RectF::withSize(piecePair.second / TilePixels + Vec2F(pos), textureCoords.size() / TilePixels); - quadList.append(RenderQuad{ - move(texture), - RenderVertex{Vec2F(worldCoords.xMin(), worldCoords.yMin()), Vec2F(textureCoords.xMin(), textureCoords.yMin()), color, 1.0f}, - RenderVertex{Vec2F(worldCoords.xMax(), worldCoords.yMin()), Vec2F(textureCoords.xMax(), textureCoords.yMin()), color, 1.0f}, - RenderVertex{Vec2F(worldCoords.xMax(), worldCoords.yMax()), Vec2F(textureCoords.xMax(), textureCoords.yMax()), color, 1.0f}, - RenderVertex{Vec2F(worldCoords.xMin(), worldCoords.yMax()), Vec2F(textureCoords.xMin(), textureCoords.yMax()), color, 1.0f} - }); + quadList.emplace_back(std::in_place_type_t(), move(texture), + worldCoords .min(), + textureCoords.min(), + Vec2F( worldCoords.xMax(), worldCoords.yMin()), + Vec2F(textureCoords.xMax(), textureCoords.yMin()), + worldCoords .max(), + textureCoords.max(), + Vec2F( worldCoords.xMin(), worldCoords.yMax()), + Vec2F(textureCoords.xMin(), textureCoords.yMax()), + color, 1.0f); } } @@ -354,15 +360,14 @@ bool TilePainter::produceTerrainPrimitives(HashMapvariants.get(modColorVariant).wrap(variance); + auto& textureCoords = piecePair.first->variants.get(modColorVariant).wrap(variance); RectF worldCoords = RectF::withSize(piecePair.second / TilePixels + Vec2F(pos), textureCoords.size() / TilePixels); - quadList.append(RenderQuad{ - move(texture), - RenderVertex{Vec2F(worldCoords.xMin(), worldCoords.yMin()), Vec2F(textureCoords.xMin(), textureCoords.yMin()), color, 1.0f}, - RenderVertex{Vec2F(worldCoords.xMax(), worldCoords.yMin()), Vec2F(textureCoords.xMax(), textureCoords.yMin()), color, 1.0f}, - RenderVertex{Vec2F(worldCoords.xMax(), worldCoords.yMax()), Vec2F(textureCoords.xMax(), textureCoords.yMax()), color, 1.0f}, - RenderVertex{Vec2F(worldCoords.xMin(), worldCoords.yMax()), Vec2F(textureCoords.xMin(), textureCoords.yMax()), color, 1.0f} - }); + quadList.emplace_back(std::in_place_type_t(), move(texture), + worldCoords.min(), textureCoords.min(), + Vec2F(worldCoords.xMax(), worldCoords.yMin()), Vec2F(textureCoords.xMax(), textureCoords.yMin()), + worldCoords.max(), textureCoords.max(), + Vec2F(worldCoords.xMin(), worldCoords.yMax()), Vec2F(textureCoords.xMin(), textureCoords.yMax()), + color, 1.0f); } } @@ -377,13 +382,12 @@ bool TilePainter::produceTerrainPrimitives(HashMap(), move(texture), + worldCoords.min(), textureCoords.min(), + Vec2F(worldCoords.xMax(), worldCoords.yMin()), Vec2F(textureCoords.xMax(), textureCoords.yMin()), + worldCoords.max(), textureCoords.max(), + Vec2F(worldCoords.xMin(), worldCoords.yMax()), Vec2F(textureCoords.xMin(), textureCoords.yMax()), + color, 1.0f); } return occlude; @@ -408,13 +412,12 @@ void TilePainter::produceLiquidPrimitives(HashMap(), move(liquid.texture), + worldRect.min(), texRect.min(), + Vec2F(worldRect.xMax(), worldRect.yMin()), Vec2F(texRect.xMax(), texRect.yMin()), + worldRect.max(), texRect.max(), + Vec2F(worldRect.xMin(), worldRect.yMax()), Vec2F(texRect.xMin(), texRect.yMax()), + liquid.color, 1.0f); } bool TilePainter::determineMatchingPieces(MaterialPieceResultList& resultList, bool* occlude, MaterialDatabaseConstPtr const& materialDb, MaterialRenderMatchList const& matchList, diff --git a/source/rendering/StarWorldPainter.cpp b/source/rendering/StarWorldPainter.cpp index 8e27006..07f61e0 100644 --- a/source/rendering/StarWorldPainter.cpp +++ b/source/rendering/StarWorldPainter.cpp @@ -173,7 +173,10 @@ void WorldPainter::renderParticles(WorldRenderData& renderData, Particle::Layer Vec2F size = Vec2F::filled(particle.size * m_camera.pixelRatio()); if (particle.type == Particle::Type::Ember) { - m_renderer->render(renderFlatRect(RectF(position - size / 2, position + size / 2), particle.color.toRgba(), particle.fullbright ? 0.0f : 1.0f)); + m_renderer->immediatePrimitives().emplace_back(std::in_place_type_t(), + RectF(position - size / 2, position + size / 2), + particle.color.toRgba(), + particle.fullbright ? 0.0f : 1.0f); } else if (particle.type == Particle::Type::Streak) { // Draw a rotated quad streaking in the direction the particle is coming from. @@ -183,12 +186,12 @@ void WorldPainter::renderParticles(WorldRenderData& renderData, Particle::Layer float length = particle.length * m_camera.pixelRatio(); Vec4B color = particle.color.toRgba(); float lightMapMultiplier = particle.fullbright ? 0.0f : 1.0f; - m_renderer->render(RenderQuad{{}, - {position - sideHalf, {}, color, lightMapMultiplier}, - {position + sideHalf, {}, color, lightMapMultiplier}, - {position - dir * length + sideHalf, {}, color, lightMapMultiplier}, - {position - dir * length - sideHalf, {}, color, lightMapMultiplier} - }); + m_renderer->immediatePrimitives().emplace_back(std::in_place_type_t(), + position - sideHalf, + position + sideHalf, + position - dir * length + sideHalf, + position - dir * length - sideHalf, + color, lightMapMultiplier); } else if (particle.type == Particle::Type::Textured || particle.type == Particle::Type::Animated) { Drawable drawable; diff --git a/source/windowing/StarGuiContext.cpp b/source/windowing/StarGuiContext.cpp index e080ecf..9f19294 100644 --- a/source/windowing/StarGuiContext.cpp +++ b/source/windowing/StarGuiContext.cpp @@ -140,23 +140,24 @@ Vec2U GuiContext::textureSize(AssetPath const& texName) { } void GuiContext::drawQuad(RectF const& screenCoords, Vec4B const& color) { - renderer()->render(renderFlatRect(screenCoords, color, 0.0f)); + renderer()->immediatePrimitives().emplace_back(std::in_place_type_t(), screenCoords, color, 0.0f); } void GuiContext::drawQuad(AssetPath const& texName, RectF const& screenCoords, Vec4B const& color) { - renderer()->render(renderTexturedRect(assetTextureGroup()->loadTexture(texName), screenCoords, color, 0.0f)); + renderer()->immediatePrimitives().emplace_back(std::in_place_type_t(), assetTextureGroup()->loadTexture(texName), screenCoords, color, 0.0f); } void GuiContext::drawQuad(AssetPath const& texName, Vec2F const& screenPos, int pixelRatio, Vec4B const& color) { - renderer()->render(renderTexturedRect(assetTextureGroup()->loadTexture(texName), screenPos, pixelRatio, color, 0.0f)); + renderer()->immediatePrimitives().emplace_back(std::in_place_type_t(), assetTextureGroup()->loadTexture(texName), screenPos, pixelRatio, color, 0.0f); } void GuiContext::drawQuad(AssetPath const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color) { - renderer()->render(RenderQuad{assetTextureGroup()->loadTexture(texName), - RenderVertex{Vec2F(screenCoords.xMin(), screenCoords.yMin()), Vec2F(texCoords.xMin(), texCoords.yMin()), color, 0.0f}, - RenderVertex{Vec2F(screenCoords.xMax(), screenCoords.yMin()), Vec2F(texCoords.xMax(), texCoords.yMin()), color, 0.0f}, - RenderVertex{Vec2F(screenCoords.xMax(), screenCoords.yMax()), Vec2F(texCoords.xMax(), texCoords.yMax()), color, 0.0f}, - RenderVertex{Vec2F(screenCoords.xMin(), screenCoords.yMax()), Vec2F(texCoords.xMin(), texCoords.yMax()), color, 0.0f}}); + renderer()->immediatePrimitives().emplace_back(std::in_place_type_t(), assetTextureGroup()->loadTexture(texName), + screenCoords.min(), texCoords.min(), + Vec2F(screenCoords.xMax(), screenCoords.yMin()), Vec2F(texCoords.xMax(), texCoords.yMin()), + screenCoords.max(), texCoords.max(), + Vec2F(screenCoords.xMin(), screenCoords.yMax()), Vec2F(texCoords.xMin(), texCoords.yMax()), + color, 0.0f); } void GuiContext::drawDrawable(Drawable drawable, Vec2F const& screenPos, int pixelRatio, Vec4B const& color) { @@ -171,11 +172,12 @@ void GuiContext::drawDrawable(Drawable drawable, Vec2F const& screenPos, int pix void GuiContext::drawLine(Vec2F const& begin, Vec2F const end, Vec4B const& color, float lineWidth) { Vec2F left = vnorm(Vec2F(end) - Vec2F(begin)).rot90() * lineWidth / 2.0f; - renderer()->render(RenderQuad{{}, - RenderVertex{Vec2F(begin) + left, Vec2F(), color, 0.0f}, - RenderVertex{Vec2F(begin) - left, Vec2F(), color, 0.0f}, - RenderVertex{Vec2F(end) - left, Vec2F(), color, 0.0f}, - RenderVertex{Vec2F(end) + left, Vec2F(), color, 0.0f}}); + renderer()->immediatePrimitives().emplace_back(std::in_place_type_t(), + begin + left, + begin - left, + end - left, + end + left, + color, 0.0f); } void GuiContext::drawPolyLines(PolyF const& poly, Vec4B const& color, float lineWidth) { @@ -184,11 +186,9 @@ void GuiContext::drawPolyLines(PolyF const& poly, Vec4B const& color, float line } void GuiContext::drawTriangles(List> const& triangles, Vec4B const& color) { - for (auto poly : triangles) { - renderer()->render(RenderTriangle{{}, - RenderVertex{get<0>(poly), Vec2F(), color, 0.0f}, - RenderVertex{get<1>(poly), Vec2F(), color, 0.0f}, - RenderVertex{get<2>(poly), Vec2F(), color, 0.0f}}); + for (auto& poly : triangles) { + renderer()->immediatePrimitives().emplace_back(std::in_place_type_t(), + get<0>(poly), get<1>(poly), get<2>(poly), color, 0.0f); } }