Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/application/StarRenderer.cpp95
-rw-r--r--source/application/StarRenderer.hpp27
-rw-r--r--source/application/StarRenderer_opengl20.cpp15
-rw-r--r--source/application/StarRenderer_opengl20.hpp3
-rw-r--r--source/core/StarVariant.hpp17
-rw-r--r--source/frontend/StarCinematic.cpp21
-rw-r--r--source/game/StarWorldClient.cpp60
-rw-r--r--source/game/StarWorldClient.hpp1
-rw-r--r--source/rendering/StarDrawablePainter.cpp35
-rw-r--r--source/rendering/StarEnvironmentPainter.cpp99
-rw-r--r--source/rendering/StarTextPainter.cpp5
-rw-r--r--source/rendering/StarTilePainter.cpp75
-rw-r--r--source/rendering/StarWorldPainter.cpp17
-rw-r--r--source/windowing/StarGuiContext.cpp36
14 files changed, 308 insertions, 198 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<TextureFiltering> 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 renderTexturedRect(TexturePtr texture, RectF const& screenCoords, Vec4B color, float param1) {
- if (!texture)
- throw RendererException("renderTexturedRect called with null texture");
+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 } {};
- 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}
- };
+
+RenderPoly::RenderPoly(List<Vec2F> 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) {
+ 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<Vec2F> const& verts, Vec4B color, float param1 = 0.0f);
+
TexturePtr texture;
List<RenderVertex> 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<RenderPrimitive> primitives) = 0;
+ virtual void set(List<RenderPrimitive>& primitives) = 0;
};
typedef Variant<bool, int, float, Vec2F, Vec3F, Vec4F> RenderEffectParameter;
@@ -136,6 +154,7 @@ public:
virtual TextureGroupPtr createTextureGroup(TextureGroupSize size = TextureGroupSize::Medium, TextureFiltering filtering = TextureFiltering::Nearest) = 0;
virtual RenderBufferPtr createRenderBuffer() = 0;
+ virtual List<RenderPrimitive>& 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<RenderPrimitive>& 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<RenderPrimitive> 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<RenderPrimitive> primitives) {
+void OpenGl20Renderer::GlRenderBuffer::set(List<RenderPrimitive>& primitives) {
for (auto const& texture : usedTextures) {
if (auto gt = as<GlGroupedTexture>(texture.get()))
gt->decrementBufferUseCount();
@@ -637,7 +642,7 @@ void OpenGl20Renderer::GlRenderBuffer::set(List<RenderPrimitive> 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<RenderPrimitive> 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<RenderPrimitive>& 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<RenderPrimitive> primitives) override;
+ void set(List<RenderPrimitive>& primitives) override;
RefPtr<GlTexture> 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 <type_traits>
#include <utility>
+#include <initializer_list>
#include "StarAlgorithm.hpp"
#include "StarMaybe.hpp"
@@ -70,6 +71,22 @@ public:
template <typename T, typename = ValidateType<T>>
Variant(T&& x);
+ template <typename T, typename = ValidateType<T>, typename... Args,
+ typename std::enable_if< std::is_constructible<T, Args...>::value, int >::type = 0
+ >
+ Variant(std::in_place_type_t<T>, Args&&... args) {
+ new (&m_buffer) T(forward<Args>(args)...);
+ m_typeIndex = TypeIndex<T>::value;
+ }
+
+ template <typename T, typename U, typename = ValidateType<T>, typename... Args,
+ typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value, int >::type = 0
+ >
+ Variant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args) {
+ new (&m_buffer) T(il, forward<Args>(args)...);
+ m_typeIndex = TypeIndex<T>::value;
+ }
+
Variant(Variant const& x);
Variant(Variant&& x) noexcept(detail::IsNothrowMoveConstructible<FirstType, RestTypes...>::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<RenderQuad>(), 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<InteractAction> 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<Drawable::LinePart>()) {
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<RenderQuad>(),
+ line.min() + left,
+ line.min() - left,
+ line.max() - left,
+ line.max() + left,
+ color, fullbright);
} else if (auto polyPart = drawable.part.ptr<Drawable::PolyPart>()) {
- 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<RenderPoly>(), poly.vertexes(), color, 0.0f);
} else if (auto imagePart = drawable.part.ptr<Drawable::ImagePart>()) {
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<RenderQuad>(), 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<RenderQuad>(), 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<String, float>(debrisImage, debrisAngularVelocity);
+ return pair<StringView, float>(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}});
-
- 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<RenderQuad>(), 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);
+
+ primitives.emplace_back(std::in_place_type_t<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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(HashMap<QuadZLevel, List<RenderPrimit
TexturePtr texture = getPieceTexture(material, piecePair.first, materialHue, false);
RectF textureCoords = piecePair.first->variants.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<RenderQuad>(), 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(HashMap<QuadZLevel, List<RenderPrimit
terrainLayer == TerrainLayer::Background ? TileLayer::Background : TileLayer::Foreground, true);
for (auto const& piecePair : pieces) {
auto texture = getPieceTexture(mod, piecePair.first, modHue, true);
- auto textureCoords = piecePair.first->variants.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<RenderQuad>(), 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<QuadZLevel, List<RenderPrimit
RectF textureCoords = RectF::withSize(Vec2F(), textureSize);
RectF worldCoords = RectF::withSize(crackingImage.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<RenderQuad>(), 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<LiquidId, List<RenderPrimitive
auto texRect = worldRect.scaled(TilePixels);
auto const& liquid = m_liquids[tile.liquidId];
- primitives[tile.liquidId].append(RenderQuad{
- liquid.texture,
- RenderVertex{Vec2F(worldRect.xMin(), worldRect.yMin()), Vec2F(texRect.xMin(), texRect.yMin()), liquid.color, 1.0f},
- RenderVertex{Vec2F(worldRect.xMax(), worldRect.yMin()), Vec2F(texRect.xMax(), texRect.yMin()), liquid.color, 1.0f},
- RenderVertex{Vec2F(worldRect.xMax(), worldRect.yMax()), Vec2F(texRect.xMax(), texRect.yMax()), liquid.color, 1.0f},
- RenderVertex{Vec2F(worldRect.xMin(), worldRect.yMax()), Vec2F(texRect.xMin(), texRect.yMax()), liquid.color, 1.0f}
- });
+ primitives[tile.liquidId].emplace_back(std::in_place_type_t<RenderQuad>(), 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<RenderQuad>(),
+ 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<RenderQuad>(),
+ 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(), 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<RenderQuad>(),
+ 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<tuple<Vec2F, Vec2F, Vec2F>> 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<RenderTriangle>(),
+ get<0>(poly), get<1>(poly), get<2>(poly), color, 0.0f);
}
}