CI / build (push) Successful in 27s
The point the camera looks at is its position plus an offset (setCameraFocus, at each tick), so between ticks it now moves with the eased position: panning moves the target the position eases to, and was still at 30 per second. Between ticks, an animation is moved on at the rate it moved at the last step (per tick: the client steps several ticks at once when it falls behind), not only when it moved exactly a frame: animations played at other speeds were posed at the tick, between smooth ones. The engine's stats also log the longest time between frames. Co-Authored-By: Claude Opus 5.5 <[email protected]>
105 lines
6.1 KiB
C++
105 lines
6.1 KiB
C++
#pragma once
|
|
// The adapter's engine: what the client draws with. Everything is recorded for the renderer process, which draws the
|
|
// 3D view and the render targets it makes. The client's own Direct3D renderer gets state and resources too (as a
|
|
// fallback, and for reading textures back), but while the renderer process covers the whole view, the client's
|
|
// renderer skips its frames' clears and draws. When the renderer process doesn't cover it (it failed, or shows only
|
|
// part of the view, for comparing) the client's renderer draws everything, from the next frame on.
|
|
|
|
#include <windows.h>
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
#include "recorder.hpp"
|
|
#include "t5de/imvu/render_engine.hpp"
|
|
|
|
namespace t5de {
|
|
|
|
class Engine final : public imvu::PiRenderEngine {
|
|
public:
|
|
// recorder may be inactive (no renderer process); window is the 3D window drawn into (frame_pacer.hpp), or null.
|
|
Engine(imvu::SharedPtr<imvu::PiRenderEngine> inner, std::shared_ptr<Recorder> recorder, HWND window);
|
|
~Engine() override;
|
|
|
|
void resizeFrameBuffer(imvu::Vec2i size) override;
|
|
void enable2dFrameBuffer() override;
|
|
void clear(std::uint32_t flags, imvu::Color color) override;
|
|
void setProjection(imvu::Vec2i viewport, const imvu::Mat4f& projection) override;
|
|
void setModelSpace(const imvu::Transform& model) override;
|
|
void setViewSpace(const imvu::Transform& view) override;
|
|
void setTextures(imvu::PiRenderTexture* texture0, imvu::PiRenderTexture* texture1) override;
|
|
void setDepthTestingOn(bool on) override;
|
|
void setDepthWritingOn(bool on) override;
|
|
void setBlendMode(imvu::RenderBlendMode mode) override;
|
|
void setAlphaTestingOn(bool on) override;
|
|
void setAlphaTestValue(float value) override;
|
|
void setBlendingOn(bool on) override;
|
|
void setBackFaceCullingOn(bool on) override;
|
|
void setNormalInvertingOn(bool on) override;
|
|
void setLightingOn(bool on) override;
|
|
void setLightProperties(std::uint32_t index, const imvu::LightProperties& light) override;
|
|
void setFogOn(bool on) override;
|
|
void setFogAttributes(float start, float end, imvu::Color color) override;
|
|
void setTextureTransformMatrixIdentity(std::uint32_t stage) override;
|
|
void setTextureTransformMatrix(std::uint32_t stage, const imvu::TextureTransform& transform) override;
|
|
void setEnvironmentAmbient(imvu::Color color) override;
|
|
imvu::PiRenderTexture* newRenderTexture(const imvu::Pixmap& pixmap, std::uint32_t flags) override;
|
|
imvu::PiInternalIndexBuffer* newIndexBuffer(std::uint32_t count, const std::uint16_t* indices) override;
|
|
imvu::PiInternalVertexBuffer* newStaticVertexBuffer(const void* data, std::uint32_t stride,
|
|
std::uint32_t elementSize,
|
|
std::uint32_t elementCount) override;
|
|
imvu::PiInternalVertexBuffer* newDynamicVertexBuffer(std::uint32_t elementSize,
|
|
std::uint32_t elementCount) override;
|
|
imvu::SharedPtr<imvu::PiPixmapRenderTarget> newPixmapRenderTarget(imvu::Vec2i size) override;
|
|
imvu::SharedPtr<imvu::PiTextureRenderTarget> newTextureRenderTarget(imvu::Vec2i size) override;
|
|
void beginRendering(imvu::PiRenderTarget* target) override;
|
|
void endRendering() override;
|
|
void drawTriangles(imvu::PiInternalIndexBuffer* indices, imvu::PiInternalVertexBuffer* positions,
|
|
imvu::PiInternalVertexBuffer* normals, imvu::PiInternalVertexBuffer* texCoords,
|
|
imvu::PiInternalVertexBuffer* colors) override;
|
|
void drawLine(imvu::Vec3f from, imvu::Vec3f to, imvu::Color color) override;
|
|
void drawPointSprites(const imvu::PointSpriteVector& sprites) override;
|
|
void drawTrianglesFromMemory(std::uint32_t vertexCount, std::uint32_t indexCount, const std::uint16_t* indices,
|
|
const imvu::VertexAttributeArray<imvu::Vec3f>& positions,
|
|
const imvu::VertexAttributeArray<imvu::Vec3f>& normals,
|
|
const imvu::VertexAttributeArray<imvu::Vec2f>& texCoords,
|
|
const imvu::VertexAttributeArray<imvu::Color>& colors) override;
|
|
|
|
private:
|
|
void setState(protocol::State state, std::uint32_t value);
|
|
// Whether the client's renderer should draw this frame's clears and draws.
|
|
[[nodiscard]] bool innerDraws() const { return !takenOver_; }
|
|
|
|
imvu::SharedPtr<imvu::PiRenderEngine> inner_;
|
|
std::shared_ptr<Recorder> recorder_;
|
|
HWND window_;
|
|
std::uint64_t frames_ = 0;
|
|
bool takenOver_ = false; // this frame is drawn by the renderer process only
|
|
imvu::PiRenderTarget* ourTarget_ = nullptr; // this frame's render target, if it's one of ours
|
|
int foreignLogged_ = 0; // diagnostics: textures the client renderer made, render targets
|
|
|
|
// Diagnostics: what the client draws, summed over 300 frames and logged (the first few times).
|
|
struct Stats {
|
|
std::uint32_t triangles = 0; // drawTriangles with our buffers
|
|
std::uint32_t foreignTriangles = 0; // drawTriangles with buffers that aren't ours (not drawn)
|
|
std::uint32_t indexed = 0; // drawTrianglesFromMemory with indices
|
|
std::uint32_t unindexed = 0; // drawTrianglesFromMemory without
|
|
std::uint32_t sprites = 0;
|
|
std::uint32_t lines = 0;
|
|
std::uint32_t flat = 0; // setProjection with an orthographic projection (2D)
|
|
};
|
|
Stats stats_;
|
|
LARGE_INTEGER statsStart_{}; // when the stats' 300 frames started
|
|
LARGE_INTEGER frameStart_{}; // when the current frame began
|
|
std::int64_t lastWindowFrame_ = 0; // when the last window frame began
|
|
double longestGap_ = 0; // the stats' longest time between window frames' beginnings, in seconds
|
|
double frameSeconds_ = 0; // the stats' window frames' time, beginRendering to endRendering
|
|
bool windowFrame_ = false; // the current frame is drawn into the window
|
|
bool innerFrame_ = false; // the current frame is begun in the client's renderer
|
|
std::int64_t innerTicksAtStats_ = 0; // innerTicks when the stats' 300 frames started
|
|
int statsLogged_ = 0;
|
|
|
|
};
|
|
|
|
} // namespace t5de
|