#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 #include #include #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 inner, std::shared_ptr 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 newPixmapRenderTarget(imvu::Vec2i size) override; imvu::SharedPtr 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& positions, const imvu::VertexAttributeArray& normals, const imvu::VertexAttributeArray& texCoords, const imvu::VertexAttributeArray& 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 inner_; std::shared_ptr 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 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